java反射之获取对象,变量,方法,存取值

  • 2018年12月9日
  • Java

1、本测试共三个类:Type、ExtendType、ReflectTest;ExtendType类继承于Type类,ReflectTest为测试类。

1.1、Type类

/**
 * @文件名称 Type.java  版本号:1.0
 * @创建日期 2018年9月12日 
 * @创建作者 me@longlonggo.com<br/>
 */
package review.reflect;

/**
 * 说明:
 * java反射测试
 * @version 1.0
 * @author me@longlonggo.com
 *
 */
public class Type {

    public int pubIntField;
    public String pubStringField;
    private int prvIntField;

    public Type() {
        Log("父类构造初始化");
    }

    Type(int arg1, String arg2) {
        pubIntField = arg1;
        pubStringField = arg2;

        Log("Constructor with parameters");
    }

    public void setIntField(int val) {
        this.prvIntField = val;
    }

    public int getIntField() {
        return prvIntField;
    }

    private void Log(String msg) {
        System.out.println("Type:" + msg);
    }
}

1.2、ExtendType类

/**
 * @文件名称 ExtendType.java  版本号:1.0
 * @创建日期 2018年9月12日 
 * @创建作者 me@longlonggo.com<br/>
 *
 */
package review.reflect;

/**
 * 说明: java反射测试
 * 
 * @version 1.0
 * @author me@longlonggo.com
 *
 */
public class ExtendType extends Type {
    public int pubIntExtendField;
    public String pubStringExtendField;
    private int prvIntExtendField;
    protected int proIntExtendTestField;

    public ExtendType() {
        Log("子类构造初始化");
    }

    ExtendType(int arg1, String arg2) {
        pubIntExtendField = arg1;
        pubStringExtendField = arg2;

        Log("子类带参构造初始化");
    }
    

    private ExtendType(int arg1, int arg2) {
        pubIntExtendField = arg1;
        proIntExtendTestField = arg2;

        Log("带参构造初始化");
    }


    private void Log(String msg) {
        System.out.println("ExtendType:" + msg);
    }
    
    public void say(String msg) {
        Log(msg);
    }

    public int getPrvIntExtendField() {
        return prvIntExtendField;
    }
    

    public void setPrvIntExtendField(int prvIntExtendField) {
        this.prvIntExtendField = prvIntExtendField;
    }
    

}

1.3、ReflectTest类

/**
 * @文件名称 ReflectTest.java  版本号:1.0
 * @创建日期 2018年9月12日 
 * @创建作者 me@longlonggo.com<br/>
 *
 */
package review.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 说明:
 * java反射实例
 * @version 1.0
 * @author me@longlonggo.com
 *
 */
public class ReflectTest {

    public static void main(String[] args) {
        /************************【1】获取类的Class对象**********************/
        System.out.println("************************【1】获取类的Class对象**********************");
        //1、使用对象的getClass方法,获取类型
        Boolean var1 = true;
        Class<?> classType1 = var1.getClass();
        System.out.println(classType1);  //class java.lang.Boolean
        
        //2、直接运用.class 语法
        Class<?> classType2 = Boolean.class;
        System.out.println(classType2); //class java.lang.Boolean
        
        //3、运用static method Class.forName()
        //该方法执行需进行异常处理
        try {
            Class<?> classType3 = Class.forName("java.lang.Boolean");
            System.out.println(classType3); //class java.lang.Boolean
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        //4、运用primitive wrapper classes的TYPE 语法
        //这里返回的是原生类型,和Boolean.class返回的不同
        Class<?> classType4 = Boolean.TYPE;
        System.out.println(classType4);     //boolean
        
        
        /************************【2】获取类的Fields变量名**********************/
        System.out.println("nn************************【2】获取类的Fields变量名**********************");
        Class<?> classExtendType = ExtendType.class;
        
        //1、使用getFields()方法获取类属性
        //只能输出public修饰的变量,包括父类
        Field[] fields = classExtendType.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        
        System.out.println("------------------------");
        
        //2、使用getDeclaredFields()方法获取属性
        //会输出所有类型变量,不含父类中定义的变量
        fields = classExtendType.getDeclaredFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        

        /************************【3】获取类的Method方法**********************/
        System.out.println("nn************************【3】获取类的Method方法**********************");
        //1、使用getMethods()方法获取类方法
        //只能输出public修饰的方法,包括父类
        Method[] methods = classExtendType.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        System.out.println("------------------------");
        
        //2、使用getDeclaredMethods()方法获取
        //会输出所有方法,但不含父类中的方法,也不包含构造方法
        methods = classExtendType.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        

        /********************【4】获取类的Constructor构造方法******************/
        System.out.println("nn********************【4】获取类的Constructor构造方法******************");
        Constructor<?>[] constructors = classExtendType.getConstructors();
        //1、getConstructors()获取公共构造方法
        //只能输出public修饰的方法,不能输出private,protected级别的构造方法,「且不包括父类构造方法」
        for (Constructor<?> c : constructors) {
            System.out.println(c);
        }
        
        System.out.println("------------------------");
        
        //2、getDeclaredConstructors()获取构造方法
        //将输出所有构造方法,包括private修饰的构造方法,但不包括父类构造方法
        constructors = classExtendType.getDeclaredConstructors();
        for (Constructor<?> c : constructors) {
            System.out.println(c);
        }
        
        
        /************************【5】通过反射创建新对象**********************/
        System.out.println("nn************************【5】通过反射创建新对象**********************");
        //1、使用无参构造器,创建对象
        //1.1、调用类Class对象的newInstance()方法,该方法会调用对象的默认构造器,没有默认构造则调用失败
        try {
            Object obj = classExtendType.newInstance();
            System.out.println(obj);
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        
        System.out.println("------------------------");
        
        //1.2、调用构造器Constructor对象的newInstance()方法
        try {
            Constructor<?> constructor1 = classExtendType.getConstructor();
            Object obj = constructor1.newInstance();
            System.out.println(obj);
        } catch (NoSuchMethodException | SecurityException e) {
            // 无法找到方法或安全管理器验证不合法时抛出
            e.printStackTrace();
        } catch (InstantiationException e) {
            // 当应用程序试图使用类中的newInstance方法创建类的实例,但无法实例化指定的类对象时抛出
            // 出现原因:抽象类、接口、数组类、原始类型或void;或者类没有空构造函数时出现
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // 当应用程序试图反射性地创建实例(数组除外)、设置或获取字段或调用方法时抛出
            // 出现原因:调用了对象的私有private方法或变量
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // 参数传入非法异常
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // 检查性异常,Method.invoke(obj, args...)方法抛出。
            // 当被调用的方法的内部抛出了异常而没有被捕获时
            e.printStackTrace();
        }
        
        //2、使用有参构造器,创建对象
        try {
            //该处调用错误,应该使用getDeclaredConstructor()
            //因为ExtendType类的构造方法:ExtendType(int arg1, String arg2)没有定义为public,所以在执行实例化时将报异常
            //java.lang.NoSuchMethodException: review.reflect.ExtendType.<init>(int, java.lang.String)
//!            Constructor<?> constructor = classExtendType.getConstructor(int.class, String.class);
//!            Object obj = constructor.newInstance(1, "input String");
//!            System.out.println(obj);
            
            //以下为正确构造方式
            Constructor<?> constructor = classExtendType.getDeclaredConstructor(int.class, String.class);
            Object obj = constructor.newInstance(1, "input String");
            System.out.println(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
        /********************【6】使用反射调用类的方法******************/
        System.out.println("nn********************【6】使用反射调用类的方法******************");
        try {
            //1、用【5】创造的对象,直接调用自身方法,但是不能调用该对象的私有方法
            Constructor<?> constructor = classExtendType.getConstructor();
            Object obj = constructor.newInstance();
            ExtendType type = (ExtendType) obj;
            type.say("i'm longlonggo!!");
            
            //2、用【3】中获取类方法的形式,调用Field的Invoke方法调用函数
            //如果不设置setAccessible(true),会报没有权限调用private的错误,如下:
            //java.lang.IllegalAccessException: Class review.reflect.ReflectTest can not access a member of class review.reflect.ExtendType with modifiers "private"
            Method logMethod = classExtendType.getDeclaredMethod("Log", String.class);
            logMethod.setAccessible(true);
            logMethod.invoke(obj, "i'm longlonggo!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        

        /********************【7】使用反射设置/获取类的属性值******************/
        System.out.println("nn********************【7】使用反射设置/获取类的属性值******************");
        try {
            //1、用【5】创造的对象,直接进行get/set值,但是不能调用私有变量
            Constructor<?> constructor = classExtendType.getConstructor();
            Object obj = constructor.newInstance();
            ExtendType type = (ExtendType) obj;
            type.setPrvIntExtendField(888);
            System.out.println(type.getPrvIntExtendField());
            
            //2、用【2】中获取Field的形式
            // 注意因为set的变量为私有变量,必须用getDeclaredField(),否则会报找不到该字段异常
            // 同时,如果不设置setAccessible(true),会报没有权限调用private的错误,如下:
            Field field = classExtendType.getDeclaredField("prvIntExtendField");
            field.setAccessible(true);
            field.setInt(obj, 1024);
            System.out.println(field.getInt(obj));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

2、main方法输出结果

************************【1】获取类的Class对象**********************
class java.lang.Boolean
class java.lang.Boolean
class java.lang.Boolean
boolean


************************【2】获取类的Fields变量名**********************
public int review.reflect.ExtendType.pubIntExtendField
public java.lang.String review.reflect.ExtendType.pubStringExtendField
public int review.reflect.Type.pubIntField
public java.lang.String review.reflect.Type.pubStringField
------------------------
public int review.reflect.ExtendType.pubIntExtendField
public java.lang.String review.reflect.ExtendType.pubStringExtendField
private int review.reflect.ExtendType.prvIntExtendField
protected int review.reflect.ExtendType.proIntExtendTestField


************************【3】获取类的Method方法**********************
public void review.reflect.ExtendType.setPrvIntExtendField(int)
public int review.reflect.ExtendType.getPrvIntExtendField()
public void review.reflect.ExtendType.say(java.lang.String)
public void review.reflect.Type.setIntField(int)
public int review.reflect.Type.getIntField()
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()
------------------------
public void review.reflect.ExtendType.setPrvIntExtendField(int)
public int review.reflect.ExtendType.getPrvIntExtendField()
public void review.reflect.ExtendType.say(java.lang.String)
private void review.reflect.ExtendType.Log(java.lang.String)


********************【4】获取类的Constructor构造方法******************
public review.reflect.ExtendType()
------------------------
private review.reflect.ExtendType(int,int)
review.reflect.ExtendType(int,java.lang.String)
public review.reflect.ExtendType()


************************【5】通过反射创建新对象**********************
Type:父类构造初始化
ExtendType:子类构造初始化
review.reflect.ExtendType@5c647e05
------------------------
Type:父类构造初始化
ExtendType:子类构造初始化
review.reflect.ExtendType@33909752
Type:父类构造初始化
ExtendType:子类带参构造初始化
review.reflect.ExtendType@55f96302


********************【6】使用反射调用类的方法******************
Type:父类构造初始化
ExtendType:子类构造初始化
ExtendType:i'm longlonggo!!
ExtendType:i'm longlonggo!!


********************【7】使用反射设置/获取类的属性值******************
Type:父类构造初始化
ExtendType:子类构造初始化
888
1024

3、总结

1、Java反射获取值,方法,变量等时,都会类似有classType.getFields()和classType.getDeclaredFields()的用法;
    1)getFields()形式的方法,可用于获取子类和父类中,public修饰的方法或变量(除了获取构造方法时,父类的构造方法是不可以被子类获取的);
    2)getDeclaredFields()形式的方法,通常可以获取所有修饰类型的方法和变量,包括private,protected,public(但是一般不能获取父类的对象和方法);
2、通过反射获取private修饰的变量或方法时,都需要解除java语言访问限制的检查,需要设置setAccessible(true);否则会报权限访问错误;
3、本文主要参考:https://blog.csdn.net/yongjian1092/article/details/7364451

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注