最新要闻
- 今头条!北方多地迎沙尘!长春直接下“泥雨”:汽车变泥车
- 环球速讯:OPPO、小米、vivo联盟:跨品牌一键换机新增第三方应用迁移
- 最新消息:史上最强骁龙7系 真我GT Neo5 SE跑分过百万:16+1TB存储确认
- 今日关注:Alphaliner:2月底港口停运船比率达6.4% 增至去年同期3倍
- 4月上映!《长空之王》新预告出炉:王一博驾驶歼20一飞冲天
- 世界今头条!自嗨锅自热煲仔饭4桶到手价32.8元:15分钟速烹美食
- 今年以来最强沙尘来袭!你的城市在下雨 他的城市在下泥
- 邓紫棋你把我灌醉高音最高是多少?邓紫棋你把我灌醉歌词
- 苏菲日记是什么?苏菲日记的读后感怎么写?
- strict怎么读?strict的反义词是什么?
- 主题班会的开场白有什么要求?主题班会的开场白怎么写?
- 河南洛阳旅游景点排名前十名有哪些?河南洛阳美食排行榜前十名
- 【环球新要闻】害怕开车也不愁 小米汽车新专利:根据驾驶员匹配自动驾驶等级
- 前沿资讯!漫威《美国队长4:新世界秩序》开拍 片场首曝:“猎鹰”美队来了
- 每日热门:一语成谶!网传鬼火少年“三部曲”:片头壮行、片尾撞车
- 俄罗斯伏尔加汽车厂:中国汽车是新款拉达Vesta的主要对手
手机
![iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?](http://tuxianggu.4898.cn/thumb/uploads/2020-07-29/db49b24a344ffac3e19f762856828ea8.jpg)
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
![警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案](http://i2.chinanews.com/simg/cmshd/2021/05/16/657ff48335db44a494ca7580d58c6477.jpg)
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
JavaSE笔记之注解和反射(含案例代码)
一.注解
1. 注解入门
Annotation是从JDK5.0开始引入的新技术
Annotation的作用:
【资料图】
- 不是程序本身,可以对程序做出解释(这一点和注释(comment)没什么区别)
- 可以被其他程序(比如:编译器等)读取
Annotation的格式:
注解是以“@注解名”在代码中存在的,还可以添加一些参数值,例如:
@SuppressWarnings(value="unchecked")
Annotation在哪里使用?
- 可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问
2. 内置注解
@Override
定义在java.lang.Override中,此注解只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。
@Deprecated
定义在java.lang.Deprecated中,此注解可以用于修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。
@SuppressWarnings
定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。
与前两个注解有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性地使用就好了。例如:
@SuppressWarnings("all")@SuppressWarnings("unchecked")@SuppressWarnings(value={"unchecked","deprecation"})
//什么是注解public class Test01 extends Object{ //@Override 重写的注解 @Override public String toString(){ return super.toString(); } //@SuppressWarnings("all") 抑制所有警告信息 @SuppressWarnings("all") public static void main(String[] args) { test(); } //@Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方式 @Deprecated public static void test(){ System.out.println("Deprecated"); }}
3. 元注解
元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,它们被用来提供对其他annotation类型作说明。
这些类型和它们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)
@Target:用于描述注解的使用范围(即被描述的注解可以用在什么地方)
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
(SOURCE < CLASS < RUNTIME)
@Document:说明该注解将包含在javaDoc中
@Inherited:说明子类可以继承父类中的该注解
package ReflectDemo;//测试元注解import java.lang.annotation.*;@MyAnnotation()public class Test02 { public void test(){ }}// 定义一个注解// Target 表示我们的注解可以用在哪些地方@Target(value = {ElementType.METHOD , ElementType.TYPE})// Retention 表示我们的注解在什么地方还有效// runtime > class > sources@Retention(value = RetentionPolicy.RUNTIME)// Documented 表示是否将我们的注解生成在JavaDoc中@Documented// Inherited 子类可以继承父类的注解@Inherited@interface MyAnnotation{}
4. 自定义注解
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。
- @interface 用来声明一个注解,格式:public @interface 注解名
- 其中的每一个方法实际上是声明了一个配置参数
- 方法的名称就是参数的名称
- 返回值的类型就是参数的类型(返回值只能是基本类型,Class,String,enum )
- 可以通过default来声明参数的默认值
- 如果只有一个参数成员,一般参数名为value
- 注解元素必须要有值,我们定义注解元素时,经常使用空字符串、0作为默认值
//自定义注解public class Test03 { //注解可以显式赋值,如果没有默认值,我们就必须给注解赋值 @MyAnnotation2(age = 18, name = "Jack") public void test(){} @MyAnnotation3("John") public void test2(){}}@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation2{ //注解的参数 : 参数类型 + 参数名 (); String name() default ""; int age(); int id() default -1; //如果默认值为-1,代表不存在 String[] schools() default {"北京大学", "清华大学"};}@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface MyAnnotation3{ String value();}
二.反射
1、静态语言 VS 动态语言
动态语言:
- 是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
- 主要动态语言:Object-C、C#、JavaScript、PHP、Python等。
静态语言:
- 与动态语言相对应的,运行时结构不可变的语言就是静态语言,如Java、C、C++。
- Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活。
2、Java Reflection
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
Class c = Class.forName("java.lang.String")
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象地称之为:反射。
正常方式: 引入需要的“包类”名称 --> 通过new实例化 --> 取得实例化对象
反射方式: 实例化对象 --> getClass()方法 --> 得到完整的“包类”名称
3、Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
- ......
4、Java反射优点和缺点
优点:
- 可以实现动态创建对象和编译,体现出很大的灵活性
缺点:
- 对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作。
5、反射相关的主要API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Filed:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造器
- ......
6、 Class类
在Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass(){};
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓的反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
public class Test01 { public static void main(String[] args) throws ClassNotFoundException { //通过反射获取类的Class对象 Class c1 = Class.forName("ReflectDemo.User"); System.out.println(c1); Class c2 =Class.forName("ReflectDemo.User"); Class c3 = Class.forName("ReflectDemo.User"); //一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); }}//实体类 pojoclass User { private int id; private String name; public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name="" + name + "\"" + "}"; }}
对象“照镜子”后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。
对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构( class / interface / enum / annotation / primitive type / void / [] )的有关信息。
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个加载的类在JVM中只会有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成
- 通过Class可以完整地得到一个类中的所有被加载的结构
- Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
6.1、Class类的常用方法
6.2、获取Class类的实例(重要,面试常问)
若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高。
Class clazz = Person.class;
已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass();
已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
Class clazz = Class.forName("demo01.Student");
内置基本数据类型可以直接用 类名.Type
还可以利用ClassLoader(了解)
public class Test02 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("The person is : " + person.name); //方式一:通过对象获得 Class c1 = person.getClass(); System.out.println(c1.hashCode()); //方式二:forName获得 Class c2 = Class.forName("ReflectDemo.Student"); System.out.println(c2.hashCode()); //方式三:通过类名.class获得 Class c3 = Student.class; System.out.println(c3.hashCode()); //方式四:基本内置类型的包装类都有一个Type属性 Class c4 = Integer.TYPE; System.out.println(c4); //获得父类类型 Class c5 = c1.getSuperclass(); System.out.println(c5); }}class Person{ int id; String name; public Person() { } public Person(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "id=" + id + ", name="" + name + "\"" + "}"; }}class Student extends Person{ public Student(){ this.name = "student"; }}class Teacher extends Person{ public Teacher(){ this.name = "teacher"; }}
哪些类型可以有Class对象?
class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
interface:接口
[] :数组
enum:枚举
annotation:注解@interface
primitive type :基本数据类型
void
//所有类型的Classpublic class Test03 { public static void main(String[] args) { Class c1 = Object.class; //类 Class c2 = Comparable.class; //接口 Class c3 = String[].class; //一维数组 Class c4 = int[][].class; //二维数组 Class c5 = Override.class; //注解 Class c6 = ElementType.class; //枚举 Class c7 = Integer.class; //基本数据类型 Class c8 = void.class; //void Class c9 = Class.class; //Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); //只要元素类型与维度一样,就是同一个class int[] a = new int[10] ; int[] b = new int[100]; System.out.println(a.getClass().hashCode()); System.out.println(b.getClass().hashCode()); }}
6.3、类的加载和初始化
Java内存分配
类的加载过程(了解)
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化:
加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象。
链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
- 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
初始化:
执行类构造器
()方法的过程。类构造器 ()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器) 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化
虚拟机会保证一个类的
()方法在多线程环境中被正确加锁和同步
public class Test04 { public static void main(String[] args) { A a = new A(); System.out.println(A.m); }}/* 1.加载到内存,会产生一个类对应Class对象 2.链接,链接结束后 m = 0 3.初始化 (){ System.out.println("A类静态代码块初始化"); m = 300; m = 100; } 最终: m = 100 */class A{ static{ System.out.println("A类静态代码块初始化"); m = 300; } static int m = 100; public A(){ System.out.println("A类的无参构造函数初始化"); }}
什么时候会发生类初始化?(重要)
类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main()方法所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化
- 通过数组定义类引用,不会触发此类的初始化
- 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
public class Test05 { public static void main(String[] args) throws ClassNotFoundException { //1.主动引用 // Son son = new Son(); //2.反射也会产生主动引用 // Class.forName("ReflectDemo.Son"); //不会产生类的引用的方法 //System.out.println(Son.b); //Son[] sons = new Son[5]; //System.out.println(Son.M); }}class Father{ static int b = 2; static { System.out.println("父类被加载..."); }}class Son extends Father{ static { System.out.println("子类被加载..."); m = 300; } static int m = 100; static final int M = 1;}
类加载器
- 类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
- 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象
类加载器作用是用来把类(class)装在进内存的。JVM规范定义了如下类型的类的加载器:
public class Test06 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类的加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //获取系统类加载器的父类加载器 --> 扩展类加载器 ClassLoader parent = systemClassLoader.getParent(); System.out.println(parent); //获取扩展类加载器的父类加载器 --> 根加载器( C/C++ ) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //测试当前类是哪个加载器加载的 System.out.println(Class.forName("ReflectDemo.Test06").getClassLoader()); //测试JDK内置的类是谁加载的 System.out.println(Class.forName("java.lang.Object").getClassLoader()); //如何获得系统类加载器可以加载的路径 System.out.println(System.getProperty("java.class.path")); }}
获取运行时类的完整结构
通过反射可以获取运行时类的完整结构:Filed、Method、Constructor、Superclass、Interface、Annotation
- 实现的全部接口
- 所继承的父类
- 全部的构造器
- 全部的方法
- 全部的Field
- 注解
- ......
//通过反射获得类的信息public class Test07 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Class c1 = Class.forName("ReflectDemo.User"); //获得类的名字 System.out.println(c1.getName()); //获得包名 + 类名 System.out.println(c1.getSimpleName()); //获得类名 //获得类的属性 System.out.println("========"); Field[] fields = c1.getFields(); //只能找到public属性 for (Field field : fields) { System.out.println(field); } fields = c1.getDeclaredFields(); //找到全部的属性,包括私有属性 for (Field field : fields) { System.out.println(field); } //获得类的方法 System.out.println("========"); Method[] methods = c1.getMethods(); //获得本类及其父类的全部public方法 for (Method method : methods) { System.out.println("getMethods : " + method); } methods = c1.getDeclaredMethods(); //获得本类的所有方法 for (Method method : methods) { System.out.println("getDeclaredMethods : " + method); } //获得指定方法 (需要传递参数类型,方便有方法重载时定位方法) Method getName = c1.getMethod("getName",null); Method setName = c1.getMethod("setName",String.class); System.out.println(getName); System.out.println(setName); //获得构造器 System.out.println("========"); Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors) { System.out.println("getConstructors : " + constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println("getDeclaredConstructors : " + constructor); } //获得指定的构造器 Constructor declaredConstructor = c1.getDeclaredConstructor(int.class,String.class ); System.out.println(declaredConstructor); }}
6.4、通过反射创建类的对象
(1)调用Class对象的newInstance()方法,要求如下:
- 类必须有一个无参数的构造器;
- 类的构造器的访问权限需要足够。
(2)如果没有无参构造器或者访问权限不足,则可以通过获取构造器来创建对象。
通过构造器创建对象,步骤如下:
- 通过Class类的getDeclaredConstructor( Class ... parameterTypes )取得本类的指定形参类型的构造器
- 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数
- 通过Constructor实例化对象
调用指定的方法
通过反射,调用类中的方法,通过Method类完成
通过Class类的getMethod(String name, Class ... parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型;
使用Object invoke(Object obj, Object[] args) 进行调用,并向方法中传递要设置的obj对象的参数信息。
Object invoke ( Object obj, Object ... args )
- Object对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法为静态方法,此时形参Object obj 可为null
- 若原方法形参列表为空,则Object[] args 为null
- 若原方法声明为private,则需要在调用此invoke方法前,显示调用方法对象的setAccessible(true)方法,将可访问private的方法。
public class Test08 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("ReflectDemo.User"); //构造一个对象 User user = (User)c1.newInstance(); System.out.println(user); //通过构造器创建对象 System.out.println("========"); Constructor constructor = c1.getDeclaredConstructor(int.class, String.class); System.out.println(constructor.newInstance(3, "Lily")); //通过反射调用普通方法 System.out.println("========"); User user2 = (User)c1.newInstance(); //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); setName.invoke(user2,"May"); System.out.println(user2.getName()); //通过反射操作属性 System.out.println("========"); User user3 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); name.setAccessible(true); //不能直接操作私有属性,我们需要关闭程序的安全监测 属性或者方法的setAccessible(true) name.set(user3,"Jack"); System.out.println(user3.getName()); }}
创建对象的效率创建对象的效率排序如下:类的实例化方式创建 >> 通过反射的方式创建(setAcccessible(true);) > 通过反射的方式创建。
6.5、反射操作泛型(了解即可)
- Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题。但是,一旦编译完成,所有和泛型有关的类型全部擦除
- 为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型
- ParameterizedType:表示一种参数化类型,比如 Collection
- GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
- TypeVariable:是各种类型变量的公共父接口
- WildcardType:代表一种通配符类型表达式
6.6、反射操作注解(重要,框架基础)
//反射操作注解public class Test09 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("ReflectDemo.Stud"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解的value的值 TableAnnotation annotation = (TableAnnotation) c1.getAnnotation(TableAnnotation.class); String value = annotation.value(); System.out.println(value); //获得类指定的注解 Field name = c1.getDeclaredField("name"); FiledAnnotation annotation1 = name.getAnnotation(FiledAnnotation.class); System.out.println(annotation1.columnName()); System.out.println(annotation1.type()); System.out.println(annotation1.length()); }}@TableAnnotation("db_student")class Stud{ @FiledAnnotation(columnName ="db_id",type = "int", length = 10) private int id; @FiledAnnotation(columnName = "db_name",type = "varchar",length = 10) private String name; @FiledAnnotation(columnName = "db_age", type = "int" , length = 3) private int age; public Stud() { } public Stud(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Stud{" + "id=" + id + ", name="" + name + "\"" + ", age=" + age + "}"; }}//类名的注解@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interface TableAnnotation{ String value();}//属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface FiledAnnotation{ String columnName(); String type(); int length();}
(补充)6.7、双亲委派机制
什么是双亲委派机制?双亲委派机制是当类加载器需要加载某一个.class字节码文件时,则首先会把这个任务委托给他的上级类加载器,递归这个操作,如果上级没有加载该.class文件,自己才会去加载这个.class。这是一种任务委派模式。双亲委派机制原理:如果一个类加载器收到了要加载某个类的请求,它要做的首要事情不是加载,而是将这个请求委托给父类的加载器去执行;如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器;如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载;如果最后没有任何加载器能加载,则报错"ClassNotFoundException"。原理图示:
本博客为博主在学习B站up主狂神关于反射和注解相关课程的学习笔记,博客中大部分内容为课上ppt内容的整理和总结。在此附上狂神在b站的视频链接(讲的是真的好,帮忙宣传)关于双亲委派机制的内容,在此附上参考博客地址:双亲委派机制 详解(手画详图)面试高频 你值得拥有!!!
关键词:
-
-
-
环球报道:关于asp.net core filters生命周期的探究
1 背景昨天看了关于一篇api限流的文章,ASP NETCoreWebApi接口限流,作者给出了demo,写的很好,但是...
来源: -
JavaSE笔记之注解和反射(含案例代码)
当前速递!Android BLE 广播定制
环球报道:关于asp.net core filters生命周期的探究
今头条!北方多地迎沙尘!长春直接下“泥雨”:汽车变泥车
环球速讯:OPPO、小米、vivo联盟:跨品牌一键换机新增第三方应用迁移
最新消息:史上最强骁龙7系 真我GT Neo5 SE跑分过百万:16+1TB存储确认
世界今热点:孤立森林(IForest)代码实现及与PyOD对比
最资讯丨three.js加载环境贴图
天天热讯:java中同步和异步的区别
今日关注:Alphaliner:2月底港口停运船比率达6.4% 增至去年同期3倍
4月上映!《长空之王》新预告出炉:王一博驾驶歼20一飞冲天
世界今头条!自嗨锅自热煲仔饭4桶到手价32.8元:15分钟速烹美食
今年以来最强沙尘来袭!你的城市在下雨 他的城市在下泥
邓紫棋你把我灌醉高音最高是多少?邓紫棋你把我灌醉歌词
苏菲日记是什么?苏菲日记的读后感怎么写?
strict怎么读?strict的反义词是什么?
主题班会的开场白有什么要求?主题班会的开场白怎么写?
河南洛阳旅游景点排名前十名有哪些?河南洛阳美食排行榜前十名
当前简讯:一种基于实时大数据的图指标解决方案
【天天报资讯】智能零售柜商品检测软件(Python+YOLOv5深度学习模型+清新界面)
来了解下GNOME 2 的 Linux 文件管理器 Caja
【状压DP】蒙德里安的梦想
【环球新要闻】害怕开车也不愁 小米汽车新专利:根据驾驶员匹配自动驾驶等级
前沿资讯!漫威《美国队长4:新世界秩序》开拍 片场首曝:“猎鹰”美队来了
每日热门:一语成谶!网传鬼火少年“三部曲”:片头壮行、片尾撞车
俄罗斯伏尔加汽车厂:中国汽车是新款拉达Vesta的主要对手
省钱神器!淘宝内测同款比价功能:最快本周上线
全球速看:记一次 rr 和硬件断点解决内存踩踏问题
天天新资讯:生核桃怎么变熟核桃_生核桃怎么弄熟
魅族20 PRO三款配色公布:绝美朝阳金吸睛
天天快消息!25日继续公测 暴雪承诺《暗黑4》会解决排队问题:服务器顶得住
环球精选!沙尘天气席卷!北京再现火星同款“蓝太阳” 专家揭秘
世界即时:开特斯拉回村被乡亲群嘲“大冤种” 30万买BBA不好吗?
今日热门!微信聊天记录不用头疼了:vivo宣布跨品牌换机数据迁移
基于深度学习的安全帽检测系统(YOLOv5清新界面版,Python代码)
MAC 最新中文版 FCPX 10.6.5 及相关插件下载安装教程 亲测有效
大数据计算引擎 EasyMR:拥抱开源,引领技术创新
当前聚焦:Java面试问题
解放生产力:30+实用AI工具汇总
全球今日讯!谷歌版ChatGPT开放测试:不会编程、不支持中文
全球聚焦:微软研究员质疑Bard数据集包括Gmail邮件:谷歌迅速澄清
2999元 小米米家对开门540L冰箱今晚开售:风冷无霜保鲜
120mg原生高钙 特仑苏纯牛奶3元/盒大促
天天最新:破解大难题!苹果新专利:佩戴太阳镜也可看清iPhone屏幕内容
【报资讯】vue3
世界视点!设计模式-index
精彩看点:商铺上月买卖91宗 涉21亿创半年高
热点评!平板电脑屏幕冷知识:高刷比高分辨率重要
焦点热讯:比尔·盖茨:GPT是1980年以来最革命性的技术进步
今日热讯:极氪009平均订单金额达52.7万元 一台订单收入相当于吉利卖5台
谷歌版ChatGPT Bard开启公测!CEO:肯定会出错、欢迎反馈
世界焦点!漫威《美队4》正式开拍 首曝片场路透:猎鹰美队就位
世界热议:Android性能优化-ListView自适应性能问题
读C#代码整洁之道笔记03_切面关注点、异常处理和线程与并发
当前时讯:放假一天不调休!2023清明节假期火车票今日开售
快资讯丨《霍格沃茨》在线人数锐减 “反恐同”人士冷嘲热讽
环球今日讯!《战争机器》电影确定编剧
世界聚焦:刚买1个月的特斯拉掉漆车主质疑非新车 售后:交付时没问题
热消息:公交司机急刹车致乘客死亡获刑 官方判定当时不需刹车:交通肇事罪
全球最资讯丨新车品鉴:2020广州车展探馆:广汽传祺EMPOWER
每日热闻!【看新股】10家拟上市银行“换道”注册制:利润普遍增长、资产质量分化、资本充足率承压
精选!iOS 17将支持第三方应用商店:看齐安卓
读Java性能权威指南(第2版)笔记24_ Java飞行记录器JFR
洗衣机6个月不清洗比马桶还脏?我麻了
时代的眼泪 25年历史的数码相机权威网站Dpreview关停
当前快报:Go 并发编程(二):锁、Select、Context、定时器
焦点报道:智能生活垃圾检测与分类系统(UI界面+YOLOv5+训练数据集)
当前通讯!Servlet的基本使用
每日资讯:中国移动:命苦
天天速看:鹿客发布掌心锁V5:掌静脉+3D结构光刷脸解锁 3399元起
尼泊尔空难20天就查明原因?为什么东航事故还没有结果?
世界微资讯!腾讯四年磨一剑!结果 让大家看笑话了
OPPO Find X6 Pro:表演一场简单的光影魔术
亨迪药业(301211):3月21日北向资金减持66.63万股
世界最资讯丨uni-app云开发入门
当前资讯!WPF学习-布局
世界热文:全明星爆款APP“偶像驾到”正式上线 主播经济和明星经纪开启新时代
小屏手机真凉了!苹果卖最差的iPhone 14 Plus 出货量也远超13 mini
今日快讯:mysql集群搭建docker-compose方案
上海农商银行完成上海市政府柜台债发售
山姆会员店寿司致多人上吐下泻:官方拒绝三倍赔偿
天天新消息丨致敬葫芦娃?保时捷911 Carrera GTS泰国特别版官图发布
环球最资讯丨14.5英寸超大屏+天玑9000!联想Y900平板正式发布:4999元起
天天观点:13代酷睿+RTX 40!联想拯救者Y7000P 2023电竞本发布:屏幕大升级
13900HX+4090顶配20999元!联想拯救者Y9000P 2023价格公布
环球最新:睡眠报告:山东人上床睡觉时间全国最早、广东人最能熬夜
焦点快看:埃安(埃)
数据库系统
世界看点:day08-2-Thymeleaf
世界快看:使用OpenCVSharp和NAudio库在C#中录制带有声音的视频并保存下来的代码
焦点快报!债市日报:3月21日
天天观速讯丨放假5天!大学生已经在为五一做准备了
外出告别“板砖”电源!联想拯救者推出140W氮化镓适配器
4799元 创维推出新款G60 4K显示器:150Hz高刷 96W反向充电
即时焦点:2023载人航天飞行任务标识正式发布:中国神话神兽鲲元素
全国车企疯狂降价!吉利汽车CEO:吉利不打价格战
每日消息!微服务与rpc/grpc
全球观热点:第132篇:npm第一次使用自己的包(package-lock.json、package.json文件作用说明)
精彩看点:【Visual Leak Detector】在 QT 中使用 VLD(方式一)
热讯:华硕发布新款Vivobook Go 14/15 OLED笔记本:高配酷睿i3-N305