Java反射简单使用

参考:https://www.cnblogs.com/ysocean/p/6516248.html

Java反射是什么?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。(来自 https://www.jianshu.com/p/9be58ee20dee)

示例类Person

class Person{
    private int age = 11;
    public String name = "csc";

    public Person(){

    }

    private void doSomething(){
        System.out.println("do some thing");
    }

    public String getName(){
        return name;
    }

    @Override
    public String toString() {
        return "toString() : Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

获取Class的方式

		/*方式1*/
        Person person = new Person();
        Class class1 = person.getClass();

        /*方式2*/
        Class class2 = Person.class; //该方法最为安全可靠,程序性能更高

        /*方式3*/
        Class class3 = null;
        try {
            class3 = Class.forName("test.testReflex.Person");  //通过 Class 对象的 forName() 静态方法来获取,用的最多.但可能抛出 ClassNotFoundException 异常
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        /*一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1,c2,c3进行 equals 比较,发现都是true*/
        System.out.println(class1 == class2);       //true
        System.out.println(class2 == class3);       //true
        System.out.println(class1 == class3);       //true

Class的方法

getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

测试代码演示 ReflexDemo.java

部分参考 https://www.jianshu.com/p/9be58ee20dee

public class ReflexDemo1 {

    public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, InstantiationException {
        getClass3Method();
        testReflexMethod();
    }

    /*三种获取class的方法*/
    private static void getClass3Method(){
        /*方式1*/
        Person person = new Person();
        Class class1 = person.getClass();

        /*方式2*/
        Class class2 = Person.class; //该方法最为安全可靠,程序性能更高

        /*方式3*/
        Class class3 = null;
        try {
            class3 = Class.forName("test.testReflex.Person");  //通过 Class 对象的 forName() 静态方法来获取,用的最多.但可能抛出 ClassNotFoundException 异常
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        /*一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1,c2,c3进行 equals 比较,发现都是true*/
        System.out.println(class1 == class2);       //true
        System.out.println(class2 == class3);       //true
        System.out.println(class1 == class3);       //true

    }

    private static void testReflexMethod() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class personClass = Person.class;
        System.out.println("1.类名称~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        String className = personClass.getName();
        System.out.println("className : "+className);
        System.out.println();

        System.out.println("2.类的public类型的属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获得public类型的属性*/
        Field[] fields = personClass.getFields();
        for(Field field : fields){
            System.out.println(field.getName());
        }
        System.out.println();

        System.out.println("3.类的所有属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获得类的所有属性,包括private*/
        Field[] allFields = personClass.getDeclaredFields();
        for(Field field : allFields){
            System.out.println(field.getName());
        }
        System.out.println();

        System.out.println("4.public类型的方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获得public类型的方法*/
        Method[] methods = personClass.getMethods();
        for(Method method : methods){
            System.out.println(method.getName());
        }
        System.out.println();

        System.out.println("5.类中的所有方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获得类中的所有方法*/
        Method[] allMethods = personClass.getDeclaredMethods();
        for(Method method : allMethods){
            System.out.println(method.getName());
        }
        System.out.println();

        System.out.println("6.获取指定的属性name~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获取指定的属性*/
        Field name = personClass.getField("name");
        System.out.println(name.getClass()+" | "+name);
        System.out.println();

        System.out.println("7.获取指定的私有属性age~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        /*获取指定的私有属性*/
        Field age = personClass.getDeclaredField("age");
        //启用和禁用访问安全检查的开关,值为 true,则表示反射的对象在使用时应该取消 java 语言的访问检查;反之不取消
        age.setAccessible(true);
        System.out.println(age.getClass()+" | "+age);
        System.out.println();


        /*创建一个对象*/
        Object person = personClass.newInstance();

        /*将person对象的age属性设置成 12*/
        age.set(person,12);

        System.out.println("8.person对象的age属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        //使用反射机制可以打破封装性,导致了java对象的属性不安全。
        System.out.println(age.get(person));
        System.out.println();

        System.out.println("9.获取构造方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        Constructor[] constructors = personClass.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println(constructor.toString());
        }
        System.out.println();

    }
}

class Person{
    private int age = 11;
    public String name = "csc";

    public Person(){

    }

    private void doSomething(){
        System.out.println("do some thing");
    }

    public String getName(){
        return name;
    }

    @Override
    public String toString() {
        return "toString() : Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

输出:

true
true
true
1.类名称~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
className : test.testReflex.Person

2.类的public类型的属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
name

3.类的所有属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
age
name

4.public类型的方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
toString
getName
wait
wait
wait
equals
hashCode
getClass
notify
notifyAll

5.类中的所有方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
toString
getName
doSomething

6.获取指定的属性name~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class java.lang.reflect.Field | public java.lang.String test.testReflex.Person.name

7.获取指定的私有属性age~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class java.lang.reflect.Field | private int test.testReflex.Person.age

8.person对象的age属性~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12

9.获取构造方法~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public test.testReflex.Person()

子类通过反射获取父类属性

示例代码:

public class ReflexDemo2 {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        Class sonClass = Class.forName("test.testReflex.Son");

        Object son = sonClass.newInstance();

        /*son 获取privateField变量的值*/
        Field field = getFieldValue(son,"privateField");

        System.out.println(field.get(son));

    }

    public static Field getFieldValue(Object son , String fieldName){
        /*1.获取fieldName对应的Field*/
        Field field = null;
        Class c = son.getClass();
        while(c != Object.class){
            try {
                field = c.getDeclaredField(fieldName);
                field.setAccessible(true);
                System.out.println(c.getName()+"中有"+fieldName+"字段");
                return field;
            } catch (NoSuchFieldException e) {
                System.out.println(c.getName()+"中没有"+fieldName+"字段");
            }finally {
                c = c.getSuperclass();
                if(c != Object.class){
                    continue;
                }
            }

        }
        return null;

    }
}

class Father{
    public String publicField = "parent_publicField";

    protected String protectedField = "parent_protectedField";

    String defaultField = "parent_defaultField";

    private String privateField = "parent_privateField";
}

class Son extends Father{

}

输出

test.testReflex.Son中没有privateField字段
test.testReflex.Father中有privateField字段
parent_privateField

综合代码练习

实体类

public class Entity {

    private static String TEST = "TEST";
    private String name;
    
    private int id;

    public Entity(){

    }

    private Entity(String name, int id) {
        this.name = name;
        this.id = id;
    }

    private String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }

    private int MethodA(Integer index){
        return index;
    }
}

测试反射类

public class ReflexDemo3 {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

        createEntity();
        reflexConstructor();
        reflexPrivateAttr();
        reflexPrivateMethod();
    }

    /*创建对象*/
    public static void createEntity() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        System.out.println("创建对象示例 : ");
        Class entityClass = Class.forName("test.testReflex.Entity");
        /*要使用entityClass.newInstance(),那么Entity中就要参数列表是空的构造方法*/
        Object object = entityClass.newInstance();
        Entity entity = (Entity)object;
        entity.setId(1);
        entity.setName("me");
        System.out.println(entity.toString());
    }

    /*反射私有构造方法*/
    public static void reflexConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        System.out.println("反射私有构造方法 : ");
        Class entityClass = Class.forName("test.testReflex.Entity");
        Constructor constructor = entityClass.getDeclaredConstructor(String.class,int.class);
        /*注意这里是要设置accessible*/
        constructor.setAccessible(true);
        /*这里使用的newInstance方法*/
        Object object = constructor.newInstance("two",11);
        System.out.println(((Entity)object).toString());

    }

    /*反射私有属性*/
    public static void reflexPrivateAttr() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        System.out.println("反射私有属性:");
        Class entityClass = Class.forName("test.testReflex.Entity");
        Field field = entityClass.getDeclaredField("TEST");
        field.setAccessible(true);
        /*要使用entityClass.newInstance(),那么Entity中就要参数列表是空的构造方法*/
        Object object = entityClass.newInstance();
        System.out.println(field.get(object));

    }

    /*反射私有方法*/
    public static void reflexPrivateMethod() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        System.out.println("反射私有方法:");
        Class entityClass = Class.forName("test.testReflex.Entity");
        Method method = entityClass.getDeclaredMethod("MethodA", Integer.class);
        method.setAccessible(true);
        /*要使用entityClass.newInstance(),那么Entity中就要参数列表是空的构造方法*/
        Object object = entityClass.newInstance();
        /*invoke参数第一个表示对象,后面是参数列表*/
        int result = (int) method.invoke(object,1);
        System.out.println(result);


    }

}

输出

创建对象示例 : 
Entity{name='me', id=1}
反射私有构造方法 : 
Entity{name='two', id=11}
反射私有属性:
TEST
反射私有方法:
1

猜你喜欢

转载自blog.csdn.net/changshuchao/article/details/88973911