案例
import java.lang.annotation.*; public class annotion01 { public void test(){ } } //自定义注解 //@Target、@Retention是在自定义注解时必须使用的两个注解 //@Retention表示注解的生命周期、@Target表示注解可以声明在什么地方 //ElementType.TYPE表示注解可以声明在类上 //ElementType.METHOD表示注解可以声明在方法上 @Target(value = {ElementType.METHOD/*方法*/}) @Retention(RetentionPolicy.RUNTIME) @Documented //表示把注解生成在Javadoc中 @Inherited //表示可以被继承 @interface MyAnnotation{ }ElementType 取值及含义
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }如果自定义注解中参数是value,则使用注解时可以省略‘value=‘,当且仅当是value时才可以省略。如果是其他参数名,则不可以省略,见下:
package com.huang.annotion_reflection; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class annotation02 { //注解可以显示赋值,也可以使用默认赋值 @MyAnnotation2(name = "xxx") public void test01(){} @MyAnnotation3("xxx") public void test02(){} } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2{ //注解的参数:参数类型+参数名(); String name() default ""; int id() default -1;//默认值为-1代表不存在 } @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation3{ //注解的参数:参数类型+参数名(); String value(); }
运行结果:
class com.huang.annotation_reflection.User class com.huang.annotation_reflection.User class com.huang.annotation_reflection.User class com.huang.annotation_reflection.User案例
package com.huang.annotation_reflection; public class reflection02 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); //方式一:通过对象获得 Class c1 = person.getClass(); System.out.println(c1.hashCode()); //方式二: forName 获得 Class c2 = Class.forName("com.huang.annotation_reflection.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 { String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person { public Student() { this.name = "学生"; } } class Teacher extends Person { public Teacher() { this.name = "老师"; } }运行截图
1163157884 1163157884 1163157884 int class com.huang.annotation_reflection.Person案例
package com.huang.annotation_reflection; import java.lang.annotation.ElementType; public class reflection03 { 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()); } }运行结果
class java.lang.Object interface java.lang.Comparable class [Ljava.lang.String; class [[I interface java.lang.Override class java.lang.annotation.ElementType class java.lang.Integer void class java.lang.Class 1163157884 1163157884执行结果
静态代码块初始化 无参构造初始化 100 首先是准备阶段,静态代码块并没有执行,m给予了默认值0,然后初始化的时候从上到下执行,m被赋予=300,然后又=100代码
package com.huang.annotation_reflection; //类什么时候会被初始化 public class reflection05 { static{ System.out.println("Main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { //1、主动引用:new一个对象(会发生类的初始化) Son son = new Son(); //2、主动引用:反射 (会发生类的初始化) Class c1 = Class.forName("com.huang.annotation_reflection"); //不会产生类的引用的方法,因为是子类调用父类的static常量 //在这里父类会被初始化,但是子类不会被初始化 System.out.println(Son.b); //数组只开辟了空间,也被命名了,但是没有加载任何类,不会发生类的初始化 Son[] array = 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; }代码
package com.huang.annotation_reflection; public class reflection06 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类加载器 ClassLoader classLoader = ClassLoader.getSystemClassLoader(); System.out.println(classLoader); //获取系统类加载器的父类加载器 --> 扩展类加载器 ClassLoader parent = classLoader.getParent(); System.out.println(parent); //无法扩展类加载器的父类 --> 引导类加载器 //测试当前类是哪个加载器加载的(系统类加载器,也就是App加载器) ClassLoader classLoader1 = Class.forName("com.huang.annotation_reflection.reflection06").getClassLoader(); System.out.println(classLoader1); //测试Object类是哪个加载器加载的(引导类加载器) classLoader = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader); //如何获得系统类加载器可以加载的路径 System.out.println(System.getProperty("java.class.path").replace(";",";\n")); //双亲委派机制 //自定义一个包java.lang.string --> 先推系统类加载器是否有这个包,再往上推扩展加载器有没有这个包,最后是引导类加载器— //如果发现了同样名字的包,就不会使用自定义的包 } }运行结果
sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$ExtClassLoader@4554617c sun.misc.Launcher$AppClassLoader@18b4aac2 null C:\Program Files\Java\jdk1.8.0_91\jre\lib\charsets.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\deploy.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\access-bridge-64.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\cldrdata.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\dnsns.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\jaccess.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\jfxrt.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\localedata.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\nashorn.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunec.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunjce_provider.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunmscapi.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\sunpkcs11.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\ext\zipfs.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\javaws.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\jce.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\jfr.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\jfxswt.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\jsse.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\management-agent.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\plugin.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\resources.jar; C:\Program Files\Java\jdk1.8.0_91\jre\lib\rt.jar; F:\IdeaProjects\JVM_MSB\jvm_01\target\classes; F:\IDEA\set_in\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar运行结果
获取类的名字(包名 + 类名) com.huang.annotation_reflection.User 获得简单名字 (类名) User 获得类的属性,只能找到public 属性 ================ 可以找到全部的属性 private java.lang.String com.huang.annotation_reflection.User.name private int com.huang.annotation_reflection.User.id private int com.huang.annotation_reflection.User.age 获得指定属性的值 private java.lang.String com.huang.annotation_reflection.User.name 获得类的方法,可以获得本类和父类的全部方法(不包括私有方法) ================ 正常的 public java.lang.String com.huang.annotation_reflection.User.toString() 正常的 public java.lang.String com.huang.annotation_reflection.User.getName() 正常的 public int com.huang.annotation_reflection.User.getId() 正常的 public void com.huang.annotation_reflection.User.setName(java.lang.String) 正常的 public void com.huang.annotation_reflection.User.setId(int) 正常的 public void com.huang.annotation_reflection.User.setAge(int) 正常的 public int com.huang.annotation_reflection.User.getAge() 正常的 public final void java.lang.Object.wait() throws java.lang.InterruptedException 正常的 public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException 正常的 public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException 正常的 public boolean java.lang.Object.equals(java.lang.Object) 正常的 public native int java.lang.Object.hashCode() 正常的 public final native java.lang.Class java.lang.Object.getClass() 正常的 public final native void java.lang.Object.notify() 正常的 public final native void java.lang.Object.notifyAll() 获得本类的所有方法(包括私有方法) declaredMethods public java.lang.String com.huang.annotation_reflection.User.toString() declaredMethods public java.lang.String com.huang.annotation_reflection.User.getName() declaredMethods public int com.huang.annotation_reflection.User.getId() declaredMethods public void com.huang.annotation_reflection.User.setName(java.lang.String) declaredMethods public void com.huang.annotation_reflection.User.setId(int) declaredMethods public void com.huang.annotation_reflection.User.setAge(int) declaredMethods public int com.huang.annotation_reflection.User.getAge() 获得指定方法,第一个为想要获取的方法名,后面为参数类型 ================ public java.lang.String com.huang.annotation_reflection.User.getName() public void com.huang.annotation_reflection.User.setName(java.lang.String) 获得的构造器(public构造器) ================ public com.huang.annotation_reflection.User() public com.huang.annotation_reflection.User(java.lang.String,int,int) 获得全部的构造器 public com.huang.annotation_reflection.User() public com.huang.annotation_reflection.User(java.lang.String,int,int) 获得指定构造器 public com.huang.annotation_reflection.User(java.lang.String,int,int) Process finished with exit code 0
代码
package com.huang.annotation_reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class reflection08 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("com.huang.annotation_reflection.User"); //构造一个对象(无参构造) Constructor declaredConstructor = c1.getDeclaredConstructor(); User user = (User) declaredConstructor.newInstance(); user= (User) c1.getDeclaredConstructor().newInstance(); System.out.println(user); //通过构造器创建对象 Constructor declaredConstructor1 = c1.getDeclaredConstructor(String.class, int.class, int.class); User user2 = (User) declaredConstructor1.newInstance("有参构造", 20, 21); System.out.println(user2); //通过反射调用普通方法 User user3 = (User) c1.newInstance(); Method setName = c1.getDeclaredMethod("setName", String.class); //invoke()激活这个方法,第一个参数为调用的实例,第二个为想调用方法传入的参数 setName.invoke(user3,"反射调用方法"); System.out.println(user3.getName()); //通过反射操作属性(不可直接操作私有属性) User user4 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); //由于权限不够(name属性为private),需要设置安全检测改为可以访问 //关闭权限检查可以提高程序性能 name.setAccessible(true); name.set(user4,"反射操作属性"); System.out.println(user4.getName()); } }运行结果
User{name='null', id=0, age=0} User{name='有参构造', id=20, age=21} 反射调用方法 反射操作属性代码
package com.huang.annotation_reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; //通过反射获取泛型 public class reflection09 { public void test01(Map<String,User> map, List<User> list){ System.out.println("test01"); } public Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = reflection09.class.getMethod("test01", Map.class, List.class); //获得参数重泛型信息 Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println(genericParameterType); System.out.println("============="); //获得真实的泛型信息 if(genericParameterType instanceof ParameterizedType){ for (Type actualTypeArgument : ((ParameterizedType) genericParameterType).getActualTypeArguments()) { System.out.println(actualTypeArgument); } } } //获得返回值泛型信息 System.out.println("--------------------------" ); Method method2 = reflection09.class.getMethod("test02"); Type genericReturnType = method2.getGenericReturnType(); if(genericReturnType instanceof ParameterizedType){ for (Type actualTypeArgument : ((ParameterizedType) genericReturnType).getActualTypeArguments()) { System.out.println(actualTypeArgument); } } } }运行结果
java.util.Map<java.lang.String, com.huang.annotation_reflection.User> ============= class java.lang.String class com.huang.annotation_reflection.User java.util.List<com.huang.annotation_reflection.User> ============= class com.huang.annotation_reflection.User -------------------------- class java.lang.String class com.huang.annotation_reflection.User Process finished with exit code 0 .getGenericParameterTypes()获得泛型的参数类型思路
先获取方法获取方法的泛型参数化类型获取泛型返回类型代码
package com.huang.annotation_reflection; import java.lang.annotation.*; public class reflection10 { public static void main(String[] args) throws NoSuchFieldException { Class c1 = Student2.class; //获得注解 System.out.println("获得注解"); Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); } //获得注解Value值 System.out.println("获得注解Value值"); MyTable myTable = (MyTable) c1.getAnnotation(MyTable.class); System.out.println(myTable.value()); //获得类指定的注解和值 System.out.println("获得类指定的注解和值"); MyFiled myFiled = c1.getDeclaredField("name").getAnnotation(MyFiled.class); System.out.println(myFiled.colName()); System.out.println(myFiled.type()); System.out.println(myFiled.length()); } } @MyTable("db_student2") class Student2 { @MyFiled(colName = "db_name",type = "varchar",length = 10) String name; @MyFiled(colName = "db_id",type = "int",length = 20) int id; @MyFiled(colName = "db_age",type = "int",length = 3) int age; public Student2() { } public Student2(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student2{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } } //类名的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface MyTable { String value(); } //属性的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface MyFiled { String colName(); String type(); int length(); }运行结果
获得注解 @com.huang.annotation_reflection.MyTable(value=db_student2) 获得注解Value值 db_student2 获得类指定的注解和值 db_name varchar 10双亲委派机制,的确是防止同名包、类与 jdk 中的相冲突,实际上加载类的时候,先通知 appLoader,看 appLoader 是否已经缓存,没有的话,appLoader 又委派给他的父类加载器(extLoader)询问,看他是不是能已经缓存加载,没有的话,extLoader 又委派他的父类加载器(bootstrapLoader)询问,BootstrapLoader看是不是自己已缓存或者能加载的,有就加载,没有再返回 extLoader,extLoader 能加载就加载,不能的话再返回给 appLoader 加载,再返回的路中,谁能加载,加载的同时也加缓存里。正是由于不停的找自己父级,所以才有 Parents 加载机制,翻译过来叫 双亲委派机制。