反射

1.Class类

  • Class本身也是一个类

  • Class对象只能由系统建立对象

  • 一个加载的类在JVM中只会有一个Class实例

  • 一个Class对象对应的是一个加载到JVM中的一个class文件

  • 每个类的实例都会记得自己是由哪个Class实例所生成

  • 通过Class可以完整的得到一个类中的所有被加载的结构

 @Test
 public void test1() throws ClassNotFoundException {
     //通过反射获取类的class对象
     Class c1 = Class.forName("com.yl.pojo.User");
     System.out.println(c1);
 
     //一个类在内存中只有一个Class对象
     //一个类被加载后,类的整个结构都会被封装在Class对象中
     Class c2 = Class.forName("com.yl.pojo.User");
     System.out.println(c1==c2);
 }

 

2.获取Class类的实例

 //测试Class类的创建方法
 @Test
 public void test2() throws ClassNotFoundException{
     User user = new Student();
     System.out.println("这个人是:"+user.name);
 
     //方式一:通过对象获得
     Class c1 = user.getClass();
     System.out.println(c1);
 
     //方式二:forName获得
     Class c2 = Class.forName("com.yl.pojo.Student");
 
     //方式三:通过类名.class获得
     Class<Student> c3 = Student.class;//c1 c2 c3是同一个对象
 
     //方式四:基本内置类型的包装类都有一个Type属性
     Class<Integer> c4 = Integer.TYPE;
     System.out.println(c4);//int
 
     //获得父类类型
     Class c5 = c1.getSuperclass();
     System.out.println(c5);
 }

 

3.哪些类型可以有Class对象

class、interface、数组、enum、annotation、基本数据类型、void

只要元素类型和维度一样,就是同一个Class对象

 

4.类的加载

 

 

什么时候发生类的初始化:(new一个类和通过反射调用才发生)

 

 

 

5.获取运行时类的完整结构

 @Test
 public void test4() throws NoSuchFieldException, NoSuchMethodException {
     User student = new Student();
     Class c1 = student.getClass();
     //获得类的名字
     System.out.println(c1.getName());//获得类名+包名
     System.out.println(c1.getSimpleName());//获得类名
 
     //获得类的属性
     Field[] fields = c1.getFields();//获得public属性,包括父类中的字段
     for (Field field : fields) {
         System.out.println(field);
    }
     Field[] declaredFields = c1.getDeclaredFields();//获得某个类的所有声明的字段,但不包括父类中的字段
     for (Field declaredField : declaredFields) {
         System.out.println(declaredField);
    }
     System.out.println(c1.getField("name"));
 
     //获得类的方法
     Method[] methods = c1.getMethods();
     for (Method method : methods) {
         System.out.println(method);
    }
 
     Method[] declaredMethods = c1.getDeclaredMethods();
     for (Field declaredField : declaredFields) {
         System.out.println(declaredField);
    }
 
     Method getName = c1.getMethod("getName", null);
     Method setName = c1.getMethod("setName", String.class);
 
     //获得构造器,同样可以指定
     System.out.println(c1.getConstructors());
     System.out.println(c1.getDeclaredConstructors());
 }

 

6.动态创建对象执行方法

 @Test
 public void test5() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
     Class c1 = Class.forName("com.yl.pojo.User");
 
     User user = (User)c1.newInstance();//本质上是调用类的无参构造器
     System.out.println(user);
 
     //通过构造器创建对象
     Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class,String.class);
     User user2 = (User) constructor.newInstance("lulu", 1, 18,"女");
     System.out.println(user2);
 
     //通过反射调用普通方法
     Method setGender = c1.getDeclaredMethod("setGender", String.class);
     User user3 = (User) c1.newInstance();
     setGender.invoke(user3,"男");//invoke:激活
     System.out.println(user3.getGender());
 
     //通过反射操作属性,不能直接操作私有属性,需要关闭安全检测
     Field gender = c1.getDeclaredField("gender");//gender是私有字段
     gender.setAccessible(true);//关闭安全检测
     User user4 = (User) c1.newInstance();
     gender.set(user4,"女");
     System.out.println(user4.getGender());
 }

 

7.通过反射获取泛型信息

 public void test6(Map<String,User> map, List<User> list){
     System.out.println("test6");
 }
 
 @Test
 public void test7() throws NoSuchMethodException {
     Method test6 = myTest.class.getMethod("test6", Map.class, List.class);
     //获得泛型参数
     Type[] genericParameterTypes = test6.getGenericParameterTypes();
     for (Type genericParameterType : genericParameterTypes) {
         System.out.println("获得类型"+genericParameterType);
         //强转
         if(genericParameterType instanceof ParameterizedType) {
             Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
             for (Type actualTypeArgument : actualTypeArguments) {
                 System.out.println("真实类型:"+actualTypeArgument);
            }
        }
    }
 }

 

8.反射操作注解

类注解:

 package com.yl.annotation;
 
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 //类名的注解
 //target:作用域,retention:获取级别
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface MyTable{
     String value();
 }

属性注解:

 package com.yl.annotation;
 
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 //属性的注解
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface MyField{
     String columnName();
     String type();
     int length();
 }

pojo:

 @MyTable("db_User")
 public class User {
     @MyField(columnName = "id",type = "int",length = 10)
     private int id;
     @MyField(columnName = "name",type = "varchar",length = 15)
     private String name;
     @MyField(columnName = "age",type = "int",length = 3)
     private int age;
 }

测试:

 @Test
 public void test() throws ClassNotFoundException, NoSuchFieldException {
     Class c1 = Class.forName("com.yl.pojo.User");
     //通过反射获得注解
     Annotation[] annotations = c1.getAnnotations();
     for (Annotation annotation : annotations) {
         System.out.println(annotation);
    }
 
     //获得注解的value的值
     MyTable myTable = (MyTable)c1.getAnnotation(MyTable.class);
     System.out.println(myTable.value());
 
     Field name = c1.getDeclaredField("name");
     MyField annotation = name.getAnnotation(MyField.class);
     System.out.println(annotation.columnName());
     System.out.println(annotation.type());
     System.out.println(annotation.length());
 }

 

posted @ 2020-09-06 16:49  Fabulo  阅读(371)  评论(0)    收藏  举报