java 反射

1.定义:

  • 在运行状态中对于任意一个类都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

2.应用场景:

  • 编码阶段不知道需要实例化的类名是哪个,需要在runtime从配置文件中加载
  • 在runtime阶段,需要临时访问类的某个私有属性

3.定义People和子类Men

  • public class People {
        private int age;
        private String name;
        public int hight;
    
        public People() {
        }
    
        public People(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        public People(String name) {
            this.name = name;
        }
    
    
        public void eat(String food) {
            System.out.println("人吃饭");
        }
    
    
        private String sleep() {
            System.out.println("人睡觉");
            return "2";
        }
    
        public String grow() {
            return "成长";
        }
    }
    public class Men extends People {
        public int age;
        private String name;
        private Men(){}
        public Men(int age,String name){
            this.age=age;
            this.name=name;
        }
    
    
        public void eat(String food){
            System.out.println("男人吃饭");
        }
    
    
        private String sleep(){
            System.out.println("男人睡觉");
            return "2";
        }
    }

4.获取类对象的三种方式

        Class clazz = Men.class;//根据类名获得class
        Class clazz1 = Class.forName("reflect.Men");//根据类路径获得class
        Men men = new Men(12, "男");
        Class clazz2 = men.getClass();//通过对象获得
        System.out.println(clazz == clazz1);//相等
        System.out.println(clazz == clazz2);//相等        

5.获得构造函数

 //获取构造器
        Constructor[] constructors = clazz.getConstructors();//获取全部构造器(公有)(包括父类)
        Constructor[] constructors1 = clazz.getDeclaredConstructors();//获取全部构造器(无论类型)(不包括父类)
        Constructor constructor = clazz.getConstructor(int.class, String.class);//获取给定参数的构造器(公有)(包括父类)
        Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class);//获取给定参数的(无论类型)(不包括父类)

        System.out.println("参数类型为(int,String)的公有构造器:\n" + constructor);
        System.out.println("参数类型为(int,String)的构造器(无论类型):\n" + constructor1);
        System.out.println("全部公有构造器:");
        for (Constructor c : constructors
                ) {
            System.out.println(c);
        }
        System.out.println("全部构造器(无论类型):");
        for (Constructor c : constructors1
                ) {
            System.out.println(c);
        }
        //用构造器创建对象
        Men o = (Men) constructor.newInstance(1, "男");
        System.out.println("构造器创建的对象:\n" + o);
  • 执行结果

参数类型为(int,String)的公有构造器:
public reflect.Men(int,java.lang.String)
参数类型为(int,String)的构造器(无论类型):
public reflect.Men(int,java.lang.String)
全部公有构造器:
public reflect.Men(int,java.lang.String)
全部构造器(无论类型):
private reflect.Men()
public reflect.Men(int,java.lang.String)
构造器创建的对象:
reflect.Men@27c170f0

6.获得对象的参数

System.out.println("参数名为age的公有字段:\n" + clazz.getField("age"));//得到公有字段(包括父类)
        System.out.println("参数名为age的字段(无论类型):\n" + clazz.getDeclaredField("age"));//得到所有类型字段(不包括父类)
        Field[] fields = clazz.getFields();
        System.out.println("所有公有的字段");
        for (Field f : fields
                ) {
            System.out.println(f);//得到所有公有的字段(包括父类)
        }

        Field[] fields1 = clazz.getDeclaredFields();
        System.out.println("所有字段(无论类型)");
        for (Field f : fields1
                ) {
            System.out.println(f);//得到所有字段无论类型(不包括父类)
        }
        Field f1 = clazz.getField("age");
        f1.set(men, 12);//给对象属性赋值
  • 执行结果

参数名为age的公有字段:
public int reflect.Men.age
参数名为age的字段(无论类型):
public int reflect.Men.age
所有公有的字段
public int reflect.Men.age
public int reflect.People.hight
所有字段(无论类型)
public int reflect.Men.age
private java.lang.String reflect.Men.name

7.获得方法

 

 Method method = clazz.getMethod("eat",String.class);//获取方法名为eat参数类型为String的公有方法(包括父类)
        Method method1 = clazz.getDeclaredMethod("eat",String.class);//获取方法名为eat参数类型为String的方法(无论类型)(不包括父类)
        Method[] methods = clazz.getMethods();//获取全部公有方法(包括父类)
        Method[] methods1 = clazz1.getDeclaredMethods();//获取全部方法(无论类型)(不包括父类)

        System.out.println("方法名为eat,参数类型为String的公有方法:\n"+method);
        System.out.println("方法名为eat,参数类型为String的方法(无论类型):\n"+method);
        System.out.println("全部公有方法:");
        for (Method m:methods
                ) {
            System.out.println(m);
        }
        System.out.println("全部方法(无论类型):");
        for (Method m1:methods1
                ) {
            System.out.println(m1);
        }
        //调用方法
        method.invoke(men,"苹果");
  • 执行结果

方法名为eat,参数类型为String的公有方法:
public void reflect.Men.eat(java.lang.String)
方法名为eat,参数类型为String的方法(无论类型):
public void reflect.Men.eat(java.lang.String)
全部公有方法:
public void reflect.Men.eat(java.lang.String)
public java.lang.String reflect.People.grow()
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 java.lang.String java.lang.Object.toString()
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()
全部方法(无论类型):
private java.lang.String reflect.Men.sleep()
public void reflect.Men.eat(java.lang.String)
男人吃饭

 

 

 

***********注意点***************

带有Declared内容的方法是获取不包含父类的所有访问限制内容,不带Declared的是获取包含父类的public的内容

 

点赞