【四月更文打卡】浅谈Java的反射机制

85 阅读2分钟

万事万物皆对象。类本身也是对象,类是 Java.Long.class的对象

class foo{}
​
//foo是类,该类的实例对象
foo f = new foo();
//foo是类,本身也是java.long.Class的对象
//任何一个类都是Class的实例对象,(构造函数是私有的)不可以实例化,只有JVM可以进行实例化。这个对象有三种表示方法:
//第一种:->任何一个类都有一个隐含的静态成员变量class
Class c1 = foo.class;
//第二种:已知该类的对象,通过getClass方法获得该类
Class c2 = f.getClass();
​
//c1 c2 分别表示foo类的类类型。类也是对象,是Class类的实例对象,称该对象为该类的类类型
​
System.out.println(c1 == c2);//true
//c1 or c2 都表示foo类的类类型。都是Class类的实例对象,一个Class只能有一个实例对象,所以c1==c2
​
//第三种:Class.forName("")
Class c3 = null;
try{
    c3 = Class.forName("com.test.foo");
}catch(Exception e){
    e.printStackTrace();
}
​
System.out.println(c2==c3); //true

允许通过类类型创建该类的对象实例 -> 通过c1/c2/c3的newInstance方法创建foo的实例,此处需要强制转换并注意异常

foo f2 = (foo)c1.newInstance();//前提需要有无参数的构造方法

动态加载类 Class.forName("")

  • 静态加载类:编译时刻加载类是静态加载类。new出来的都是 静态加载类

  • 动态加载类:运行时刻加载类是动态加载类。Class.forName("") 生成类类型,之后用newInstance创建对象 强制转型——接口编程

    //动态加载类 Class c = Class.forName(args[0]); //通过类类型,加载类对象,Able为接口 Able a = (Able)c.newInstance(); a.start();

    interface Able{
        public abstract void start();
    }
    ​
    class A implements Able{
        public void start(){
            System.out.println();
        }
    }
    

Method类,方法对象

一个成员方法就是一个Method对象,

  • getMethods()方法获取的是所有的public的函数,包括父类继承而来的

  • getDeclaredMethods()获取的是所有该类自己声明的方法,不管权限,但是不包括父类继承的

  • 返回都是数组

    Method[] ms = c.getMethods();

利用反射方法操作对象

foo f = new foo();
//获得类类型
Class c = f.getClass();
//获取方法 print(String,int)
Method m1 = c.getMethod("print",String.class,int.class);//方法名,参数(可变参数 可以直接写 也可以用数组)
//或者
m1 = c.getMethod("print",new class[]{String.class,int.class});
//用反射操作对象
Object o = m1.invoke(f,"Hello",0);//对象,参数,返回值o是函数的返回值

Field类,成员变量对象

一个成员变量是一个Field对象

  • getFields()方法获取的是所有的public的成员变量信息,包括父类继承的
  • getDeclareFields()

Constructor类,构造函数对象

一个构造函数也是一个Constructor对象

  • getConstructors() 所有public 的构造方法。肯定是自己生命的
  • getDeclareConstructors() 所有自己声明的构造方法。