19_反射与标注

百知教育 - 孙帅 - 19_反射与标注

01_类对象的概念

  • 类的对象
    基于某个类new出来的对象,也称为实例对象
  • 类对象
    类加载的产物封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)。
  • 获取类对象的方法:
    1. 类名.class: 如:int.class、double.class
      Class c1 = ArrayList.class;
    2. 类的对象.getClass()
      ArrayList l1 = new ArrayList();
      ArrayList l2 = new ArrayList();
      Class c2 = l1.getClass();
      Class c3 = l2.getClass();
    3. Class.forName(“类的全名”): 通过类名获得类对象
      Class c4 = Class.forName("java.util.ArrayList");

02_利用反射获取类的信息

  • java.lang.reflect中的类:
    1. Field 属性
      • 获取此类对象的方法:
        • getFields(): 获得 公开属性包括父类
        • getDeclaredFields() 获得 所有属性只包括本类
    2. Method 方法
      • 获取此类对象的方法:
        • getMethods() 获取公开方法(包括父类
        • getDeclaredMethods() 获取所有方法(只包括本类
    3. Constructor 构造方法
      • 获取此类对象的方法:
        • getConstructors() 获取公开构造方法(包括父类
        • getDeclaredConstructors() 获取所有构造方法(只包括本类
  • 代码:
    package day25;
    import java.util.ArrayList;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Constructor;
    public class TestClass{
     public static void main(String[] args){  
      Class c1 = ArrayList.class;
      
      /*
      ArrayList l1 = new ArrayList();
      ArrayList l2 = new ArrayList();
      Class c2 = l1.getClass();
      Class c3 = l2.getClass();
      
      try{
       Class c4 = Class.forName("java.util.ArrayList");
      }catch(ClassNotFoundException e){
       e.printStackTrace();
      }
      
      System.out.println(c1.getName());
      System.out.println(c1.getPackage().getName());
      System.out.println(c2.getSuperclass().getName());
      
      Class[] cs = c1.getInterfaces();
      for(Class c : cs){
       System.out.println(c.getName());
      }
      */
      
      /*
      Field[] fs = c1.getDeclaredFields();
      for(Field f : fs){
       System.out.println(f);
      }
      */
      
      /*
      Method[] ms = c1.getDeclaredMethods();
      for(Method m : ms){
       System.out.println(m);
      }
      */
      
      Constructor[] cs = c1.getDeclaredConstructors();
      for(Constructor c : cs){
       System.out.println(c);
      }
     }
    }
  • 运行结果:
    在这里插入图片描述

03_利用反射实现常规操作

  • 代码:
    package day25;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    public class TestReflection{
     public static void main(String[] args) throws Exception{
      //Object o = new Student();
      Class c = Class.forName("day25.Student");
      Object o = c.newInstance();
      
      //Object o2 = new Student("YKY" , 20);
      Constructor con = c.getConstructor(String.class , int.class);
      Object o2 = con.newInstance("YKY" , 20);
      
      //o2.study();
      Method m = c.getMethod("study");
      m.invoke(o2);
      m.invoke(o);  //o.study();
      
      //int result = o2.study("CoreJava");
      Method m2 = c.getMethod("study" , String.class);
      Object result = m2.invoke(o2 , "CoreJava");
      System.out.println(result);
     }
    }
    class Student{
     private String name;
     private int age;
     
     
     public Student(){
      super();
      System.out.println("Student()");
     }
     public Student(String name , int age){
      super();
      this.name = name;
      this.age = age;
      System.out.println("Student(String , int)");
     }
     
     public void study(){
      System.out.println("Student "+name+" study");
     }
     public int study(String course){
      System.out.println("Student "+name+" study "+course);
      return 100;
     }
    }
  • 运行结果:
    在这里插入图片描述

04_利用反射访问私有成员

  • 代码:
    package day25;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    import java.lang.reflect.Field;
    public class TestReflection{
     public static void main(String[] args) throws Exception{
      //Object o = new Student();
      Class c = Class.forName("day25.Student");
      Object o = c.newInstance();
      
      //Object o2 = new Student("YKY" , 20);
      Constructor con = c.getConstructor(String.class , int.class);
      Object o2 = con.newInstance("YKY" , 20);
      
      //o2.study();
      Method m = c.getDeclaredMethod("study");
      m.setAccessible(true);
      m.invoke(o2);
      m.invoke(o);  //o.study();
      
      //int result = o2.study("CoreJava");
      Method m2 = c.getMethod("study" , String.class);
      Object result = m2.invoke(o2 , "CoreJava");
      System.out.println(result);
      
      Field f = c.getDeclaredField("name");
      f.setAccessible(true);
      System.out.println(f.get(o));
      f.set(o , "YKY");
      System.out.println(f.get(o));
     }
    }
    class Student{
     private String name;
     private int age;
     
     
     public Student(){
      super();
      System.out.println("Student()");
     }
     public Student(String name , int age){
      super();
      this.name = name;
      this.age = age;
      System.out.println("Student(String , int)");
     }
     
     private void study(){
      System.out.println("Student "+name+" study");
     }
     public int study(String course){
      System.out.println("Student "+name+" study "+course);
      return 100;
     }
    }
  • 运行结果:
    在这里插入图片描述

05_枚举的概念

  • 概念:
    可看做一个类,拥有的对象特定的几个值,默认无参构造方法为私有
  • 语法:
    enum  枚举名{
    	枚举值,
    	枚举值,
    	枚举值
    }
  • 访问:
    枚举名.枚举值
  • 枚举值:
    是枚举类中的 公开静态常量,类型为枚举类型
  • 代码(编译通过):
    package day25;
    public class TestEnum{
     public static void main(String[] args){
      Order o = new Order();
      o.status = State.PAYED;
     }
    }
    class Order{
     public State status = State.UNPAY;
    }
    enum State{  //等价于类State2
     UNPAY,
     PAYED,
     SENT,
     RECEIVED
    }
    class State2{
     public static final State2 UNPAY = new State2();
     public static final State2 PAYED = new State2();
     public static final State2 SENT = new State2();
     public static final State2 RECEIVED = new State2();
    }

06_枚举的语法

  • Enum
    默认是所有枚举的父类
  • 代码:
    package day25;
    import static day25.State.*;  //引入静态属性、方法
    import static java.lang.System.*;
    public class TestEnum{
     public static void main(String[] args){
      Order o = new Order();
      o.status = PAYED;
      
      State[] states = values();
      for(State state : states){
       out.println(state.name()+"   "+state.getComment()+"   "+state.ordinal());
      }
      
      out.println("nanoTime:  "+nanoTime());
     }
    }
    class Order{
     public State status = UNPAY;
    }
    enum State{  //具有有参构造方法的枚举,等价于类State2
     UNPAY("未支付"),
     PAYED("已支付"),
     SENT("已发货"),
     RECEIVED("已收货");
     
     private String comment;
     private State(String s){
      comment = s;
     }
     public String getComment(){
      return comment;
     }
    }
    class State2{  
     public static final State2 UNPAY = new State2("未支付");
     public static final State2 PAYED = new State2("已支付");
     public static final State2 SENT = new State2("已发货");
     public static final State2 RECEIVED = new State2("已收货");
     
     private String comment;
     private State2(String s){
      comment = s;
     }
     public String getComment(){
      return comment;
     }
    }
    enum EnumA{  //枚举中含有抽象方法时,枚举值定义时要实现抽象方法
     A1(){
      public void print(){}
     },
     A2(){
      public void print(){}
     };
     
     public abstract void print();
    }
    abstract class B{
     public static final B B1 = new B(){
      public void print(){}
     };
     public static final B B2 = new B(){
      public void print(){}
     };
     
     public abstract void print();
     private B(){}
    }
  • 运行结果:
    在这里插入图片描述

07_自定义标注

  • 概念:
    表述代码的代码
  • 分类:
    1. 标记标注 没有属性。写法: @标注名
    2. 单值标注 一个属性。写法: @标注名(属性名 = 属性值) ,如果 属性名为value,可以简写为: @标注名(属性值)
    3. 多值标注 多个属性。写法: @标注名(属性名1 = 属性值1 , 属性名2 = 属性值2 …)
  • 标注属性类型
    必须是具有字面值的类型(8中基本类型、String、Enum、Class以及它们的数组
  • 元标注
    1. Target 描述可以为哪些程序组件添加此标注(程序组件:类、属性、构造方法、方法 …
    2. Retention 描述标注信息保留到什么时候(取值:SOURCE、CLASS、RUNTIME
  • 代码:
    package day25;
    import java.lang.annotation.Target;
    import java.lang.annotation.Retention;
    import static java.lang.annotation.RetentionPolicy.*;
    import static java.lang.annotation.ElementType.*;
    import java.lang.reflect.Method;
    public class TestAnnotation{
     public static void main(String[] args){
      Class c = MyClass.class;
      
      Method[] ms = c.getMethods();
      for(Method m : ms){
       if(m.isAnnotationPresent(Test.class)){
        Test t = m.getAnnotation(Test.class);
        String v1 = t.value();
        int v2 = t.value2();
        System.out.println(m.getName()+" value = "+v1+" value2 = "+v2);
       } 
      }
     }
    }
    class MyClass{
     @Test
     public void method1(){
      
     }
     @Test("HHH")
     public void method2(){
      
     }
     @Test(value = "HHH" , value2 = 19)
     public void method3(){
      
     }
     public void method4(){
      
     }
    }
    @Target(METHOD)
    @Retention(RUNTIME)
    @interface Test{
     String value() default "YKY";
     int value2() default 20;
    }
  • 运行结果:
    在这里插入图片描述

08_自定义标注的案例

  • (对一个类自动测试)代码:
    package day26;
    import java.lang.annotation.Target;
    import java.lang.annotation.Retention;
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.RetentionPolicy.*;
    import java.util.TreeMap;
    import java.lang.reflect.Method;
    import java.util.Collection;
    public class TestAutoTestEngine{
     public static void main(String[] args){
      autoTest("day26.ClassA");
     }
     
     //根据className,自动创建对象,并按照Test标注,按顺序,用相应的参数,执行每个需要测试的方法
     public static void autoTest(String className){  //此函数功能相当于以下代码
      /*
      ClassA o = new ClassA();
      System.out.println(o.mb("YKY"));
      System.out.println(o.ma("HHH"));
      System.out.println(o.md("LYH"));
      System.out.println(o.mc("YXM"));
      */
      
      try{
       Class c = Class.forName(className);
       Object o = c.newInstance();
      
       TreeMap<Integer , Method> map = new TreeMap<>();
       //拿到c类中所有公开方法
       Method[] ms = c.getMethods();
       for(Method m : ms){
        //拿到添加了Test标注的方法中的Order
        if(m.isAnnotationPresent(Test.class)){
         Test t = m.getAnnotation(Test.class);
         int order = t.order();
         //利用TreeMap key:order  value:Method
         map.put(order , m);
        }
       }
       //遍历TreeMap的值,依次调用每个方法
       Collection<Method> values = map.values();
       for(Method m : values){
        Test t = m.getAnnotation(Test.class);
        String parameter = t.parameter();
        Object result = m.invoke(o , parameter);
        System.out.println(result);
       }
      }catch(Exception e){
       e.printStackTrace();
      }
     }
    }
    class ClassA{
     @Test(order = 2 , parameter = "HHH")
     public String ma(String s){
      return "ma "+s;
     }
     @Test(order = 1 , parameter = "YKY")
     public String mb(String s){
      return "mb "+s;
     }
     @Test(order = 4 , parameter = "YXM")
     public String mc(String s){
      return "mc "+s;
     }
     @Test(order = 3 , parameter = "LYH")
     public String md(String s){
      return "md "+s;
     }
    }
    @Target(METHOD)
    @Retention(RUNTIME)
    @interface Test{
     int order();
     String parameter();
    }
  • 运行结果:
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值