「Java」反射

567 阅读4分钟

1. 获取Class对象的方式

public static void main(String[] args)  throws ClassNotFoundException {
    /*
     * 1.
     * Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
     * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
     **/
    Class cls1 = Class.forName("com.afuo.learntools.pojo.User");   //User自定义实体类
    System.out.println("cls1 = " + cls1);

    /*
     * 2.
     * 类名.class:通过类名的属性class获取
     * 多用于参数的传递
     **/
    Class cls2 = User.class;
    System.out.println("cls2 = " + cls2);

    /*
     * 3.
     * 对象.getClass():getClass()方法在Object类中定义着。
     * 多用于对象的获取字节码的方式
     **/
    User user = new User();
    Class cls3 = user.getClass();
    System.out.println("cls3 = " + cls3);

    // == 比较三个对象
    System.out.println("cls1 == cls2 : " + (cls1 == cls2));
    System.out.println("cls1 == cls3 : " + (cls1 == cls3));
    
    
    /*
    	结果是:
        cls1 = class com.afuo.learntools.pojo.User
        cls2 = class com.afuo.learntools.pojo.User
        cls3 = class com.afuo.learntools.pojo.User
        cls1 == cls2 : true
        cls1 == cls3 : true
        
        结论:
        同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次。
        不论通过哪一种方式获取的Class对象都是同一个。
    */
}

2. 获取成员变量

public static void main(String[] args) throws Exception {
    //0. 获取FourModifier的Class对象
    Class fourModifierClass = FourModifier.class;

    //1. 获取所有public修饰的成员变量
    Field[] fields = fourModifierClass.getFields();
    System.out.println("以下是所有public修饰的成员变量=====");
    for (Field field : fields) {
        System.out.println(field);
    }
    System.out.println();

    //2. 获取指定public修饰的成员变量
    Field testPublicField = fourModifierClass.getField("testPublic");
    FourModifier fourModifier = new FourModifier();
    //修改指定成员变量 testPublic 的值
    testPublicField.set(fourModifier,"get!!!");
    System.out.println("以下是修改指定成员变量testPublic的值=====");
    System.out.println(fourModifier);
    System.out.println();

    //3. 获取所有的成员变量,不考虑修饰符
    Field[] declaredFields = fourModifierClass.getDeclaredFields();
    System.out.println("以下是所有的成员变量,不考虑修饰符=====");
    for (Field declaredField : declaredFields) {
        System.out.println(declaredField);
    }
    System.out.println();

    //4. 获取指定修饰的成员变量
    //除public外,其余get都会报错,这时可以加上暴力反射
    //以private为例
    Field testPrivateDeclaredField = fourModifierClass.getDeclaredField("testPrivate");

    testPrivateDeclaredField.setAccessible(true);//暴力反射,忽略访问权限修饰符的安全检查

    Object object = testPrivateDeclaredField.get(fourModifier);
    System.out.println("以下为通过private变量获取对象=====");
    System.out.println(object);
    
    
    /*
    	结果是:
        以下是所有public修饰的成员变量=====
        public java.lang.String com.afuo.learntools.pojo.FourModifier.testPublic

        以下是修改指定成员变量testPublic的值=====
        FourModifier(testPublic=get!!!, testProtected=null, testDefault=null, testPrivate=null)

        以下是所有的成员变量,不考虑修饰符=====
        public java.lang.String com.afuo.learntools.pojo.FourModifier.testPublic
        protected java.lang.String com.afuo.learntools.pojo.FourModifier.testProtected
        java.lang.String com.afuo.learntools.pojo.FourModifier.testDefault
        private java.lang.String com.afuo.learntools.pojo.FourModifier.testPrivate

        以下为通过private变量获取对象=====
        null
    */
}

3. 获取构造方法

public static void main(String[] args) throws Exception {
    //0. 获取FourModifier的Class对象
    Class userClass = User.class;

    //1. 获取无参构造方法
    Constructor noConstructor = userClass.getConstructor();
    System.out.println("无参:" + noConstructor);
    //1.1 无参构造方法创建对象
    Object noObject1 = noConstructor.newInstance();
    System.out.println("无参构造方法创建对象:" + noObject1);
    //1.2 用类创建对象
    Object noObject2 = userClass.newInstance();
    System.out.println("用类创建对象:" + noObject2);

    //2.获取有参构造方法(这里以全参为例)
    Constructor allConstructor = userClass.getConstructor(int.class,String.class,String.class);
    System.out.println("有参:" + allConstructor);
    //2.1 有参构造方法创建对象
    Object allObject1 = allConstructor.newInstance(1001,"张三", "123456");
    System.out.println("有参构造方法创建对象:" + allObject1);
    
    //3. getDeclaredConstructor()(加上Declared 不考虑修饰符)
    // 例如 privateConstructor.setAccessible(true);暴力反射
    
    /*
    	结果是:
        无参:public com.afuo.learntools.pojo.User()
        无参构造方法创建对象:User(id=0, username=null, password=null)
        用类创建对象:User(id=0, username=null, password=null)
        有参:public com.afuo.learntools.pojo.User(int,java.lang.String,java.lang.String)
        有参构造方法创建对象:User(id=1001, username=张三, password=123456)
    */
}

4. 获取成员方法

public class User {

    private int id;
    private String username;
    private String password;
    
    public void eat() {
        System.out.println("eat!!!");
    }

    public void eat(String food) {
        System.out.println("eat!!!" + food);
    }

    public void drink() {
        System.out.println("drink!!!");
    }
}
public static void main(String[] args) throws Exception {
    //0. 获取FourModifier的Class对象
    Class userClass = User.class;

    //1. 获取该类所有public方法
    // getDeclaredMethods()获取所有修饰符类型的方法
    Method[] methods = userClass.getMethods();
    for (Method method : methods) {
        String name = method.getName();
        System.out.println("方法:" + method + ",  方法名:" + name);
        //method.setAccessible(true);
    }

    //2. 获取指定名称的无参方法
    Method noEatMethod = userClass.getMethod("eat");
    User user = new User();
    noEatMethod.invoke(user);

    //3. 获取指定名称的有参方法
    Method allEatMethod = userClass.getMethod("eat", String.class);
    allEatMethod.invoke(user,"orange");
    
    
    
    /*
    	结果是:
        方法:public boolean com.afuo.learntools.pojo.User.equals(java.lang.Object),  方法名:equals
        方法:public java.lang.String com.afuo.learntools.pojo.User.toString(),  方法名:toString
        方法:public int com.afuo.learntools.pojo.User.hashCode(),  方法名:hashCode
        方法:public int com.afuo.learntools.pojo.User.getId(),  方法名:getId
        方法:public java.lang.String com.afuo.learntools.pojo.User.getPassword(),  方法名:getPassword
        方法:public void com.afuo.learntools.pojo.User.setId(int),  方法名:setId
        方法:public void com.afuo.learntools.pojo.User.eat(),  方法名:eat
        方法:public void com.afuo.learntools.pojo.User.eat(java.lang.String),  方法名:eat
        方法:public void com.afuo.learntools.pojo.User.setPassword(java.lang.String),  方法名:setPassword
        方法:public static com.afuo.learntools.pojo.User$UserBuilder com.afuo.learntools.pojo.User.builder(),  方法名:builder
        方法:public void com.afuo.learntools.pojo.User.setUsername(java.lang.String),  方法名:setUsername
        方法:public void com.afuo.learntools.pojo.User.drink(),  方法名:drink
        方法:public java.lang.String com.afuo.learntools.pojo.User.getUsername(),  方法名:getUsername
        方法:public final void java.lang.Object.wait() throws java.lang.InterruptedException,  方法名:wait
        方法:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException,  方法名:wait
        方法:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException,  方法名:wait
        方法:public final native java.lang.Class java.lang.Object.getClass(),  方法名:getClass
        方法:public final native void java.lang.Object.notify(),  方法名:notify
        方法:public final native void java.lang.Object.notifyAll(),  方法名:notifyAll
        eat!!!
        eat!!!orange
    */
}

5. 获取类名

public static void main(String[] args) throws Exception {
    //0. 获取FourModifier的Class对象
    Class userClass = User.class;

    //1. 获取类名
    String className = userClass.getName();
    System.out.println("类名:" + className);
    
    /*
    	结果是:
    	类名:com.afuo.learntools.pojo.User
    */
}