Java反射机制:通过反射机制获取类的成员(构造方法,成员变量,成员方法);通过反射越过泛型检查;通过反射运行配置文件内容

Java反射机制

一、反射机制概述

反射概述:
	JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
	对于任意一个对象,都能够调用它的任意一个方法和属性;
	这种动态获取类的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
	要想解剖一个类,必须先要获取到该类的字节码文件对应的Class类型的对象,因为解剖使用的是Class类中的方法。
类的成员:
	 成员变量		Field
	 构造方法		Constructor
	 成员方法		Method

二、获取class文件对象的三种方式

	a:Object类的getClass()方法
	b:静态属性class
	c:Class类中静态方法forName()
public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //Object类的getClass()方法
        Class<? extends MyTest> aClass = new MyTest().getClass();
        // 静态属性class
        Class<MyTest> myTestClass = MyTest.class;
        //Class类中静态方法forName(),参数为全类名
        Class<?> aClass1 = Class.forName("mydemo.MyTest");
        //class文件对象只有一个,所以无论通过何种方式获取的class文件对象都是同一个
        System.out.println(myTestClass==aClass&&aClass==aClass1);//true
    }
}

三、通过反射获取构造方法并使用

//获取所有公共的构造方法的对象数组
	public Constructor<?>[] getConstructors() 
//获取所有的构造方法(包括私有的)的对象数组
	public Constructor<?>[] getDeclaredConstructors() 
//获取单个公共构造方法的对象
	public Constructor<T> getConstructor(Class<?>... parameterTypes)
//获取单个构造方法的对象,包含私有的            
	public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
T newInstance() //创建此 Class 对象所表示的类的一个新实例     
public void setAccessible(boolean flag)//AccessibleObject的方法
   //将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。    
import java.lang.reflect.Constructor;

public class MyTest {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("mydemo1.Student");
        //获取所有公共的构造方法的对象数组
        Constructor<?>[] constructors = aClass.getConstructors();
        //获取所有的构造方法(包括私有的)的对象数组
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        //获取单个私有构造方法的对象
        Constructor<?> constructor = aClass.getDeclaredConstructor();
        //取消访问检查
        constructor.setAccessible(true);
        //通过私有构造方法对象创建Student对象
        Student student = (Student) constructor.newInstance();
        System.out.println(student);
        System.out.println("--------------------------------");
        //获取公共有参构造方法对象
        Constructor<?> constructor1 = aClass.getConstructor(String.class, int.class);
        Student student1 = (Student) constructor1.newInstance("张三", 23);
        System.out.println(student1);
    }
}

class Student {
    private Student() {
        System.out.println("私有空参构造执行了");
    }

    public Student(String name,int age) {
        System.out.println("有参构造执行了,"+name+"=="+age);
    }
}

运行结果:

私有空参构造执行了
mydemo1.Student@4554617c
--------------------------------
有参构造执行了,张三==23
mydemo1.Student@74a14482

Process finished with exit code 0

四、通过反射获取成员变量并使用

//获取所有公共成员变量的对象,包含从父类继承过来的
public Field[] getFields() 
//获取所有成员变量的对象,包含私有的,也包含从父类继承过来的
public Field[] getDeclaredFields() 
public Field getField(String name)//获取单个公共成员变量的对象
public Field getDeclaredField(String name)//获取单个成员变量的对象
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class MyTest {
    public static void main(String[] args) throws Exception{
        //创建Student对象
        Class<?> aClass = Class.forName("mydemo2.Student");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        Object stu = declaredConstructor.newInstance();

        //获取成员变量对象,并给成员变量赋值
        Field name = aClass.getField("name");//参数为字段名称
        name.set(stu,"张三");//参1为字段所属对象,参2为要赋的值
        Field age = aClass.getDeclaredField("age");
        age.set(stu,23);
        Field x = aClass.getDeclaredField("x");
        x.setAccessible(true);//取消访问检查
        x.set(stu,3.323);
        System.out.println(name.get(stu)+"=="+age.get(stu)+"=="+x.get(stu));
        //张三==23==3.323
    }
}
class Student{
    public String name;
    int age;
    private double x;
    private Student(){}
}

五、通过反射获取成员方法并使用

//获取所有公共成员方法的对象数组,包含从父类继承过来的公共方法
public Method[] getMethods() 
public Method[] getDeclaredMethods()//获取自己所有成员方法的对象数组
//获取单个公共成员方法的对象 
public Method getMethod(String name,Class<?>... parameterTypes) 
//获取单个成员方法的对象,包括私有的
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
    //参数1: 方法名称  参数2:方法行参的class 对象
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class MyTest {
    public static void main(String[] args)throws Exception{
        //创建MyClass对象
        Class<?> aClass = Class.forName("mydemo3.MyClass");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        Object o = declaredConstructor.newInstance();

        //获取单个公共成员方法的对象
        Method show = aClass.getMethod("show");
        show.invoke(o);//执行此方法,参数为此方法所属对象

        //获取私有的成员方法对象
        Method show1 = aClass.getDeclaredMethod("show", int.class);
        show1.setAccessible(true);//取消权限检查
        Object invoke = show1.invoke(o, 22);
        System.out.println(invoke);//返回值

        Method haha = aClass.getDeclaredMethod("test", String.class, int.class);
        haha.setAccessible(true);
        Object invoke1 = haha.invoke(o, "我是", 777);
        System.out.println(invoke1);
    }
}
class MyClass{
    private MyClass() {
        System.out.println("私有构造方法执行了");
    }
    public void show(){
        System.out.println("无参公共的show方法执行了");
    }
    private String show(int num){
        System.out.println("有参私有的show方法执行了");
        return "show:"+num;
    }
    private String test(String str,int num){
        System.out.println("有参私有的test方法执行了");
        return "test:"+str+num;
    }
}

运行结果:

私有构造方法执行了
无参公共的show方法执行了
有参私有的show方法执行了
show:22
有参私有的test方法执行了
test:我是777

Process finished with exit code 0

六、通过反射越过泛型检查

//往ArrayList<Integer>里添加String类型元素
//原理:泛型只在编译期有效,运行期就会擦除,而反射机制是在运行状态中
import java.lang.reflect.Method;
import java.util.ArrayList;

public class MyTest {
    public static void main(String[] args) throws Exception{
        ArrayList<Integer> list = new ArrayList<>();
        list.add(100);
        Class<? extends ArrayList> aClass = list.getClass();
        Method add = aClass.getDeclaredMethod("add", Object.class);
        add.setAccessible(true);
        add.invoke(list,"abc");
        System.out.println(list);//[100, abc]
    }
}

七、通过反射运行配置文件内容

import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;

public class MyTest1 {
    public static void main(String[] args) throws Exception {
        //要使用某个类的某个方法,只需要修改配置文件即可
        Properties properties = new Properties();
        //关联配置文件
        properties.load(new FileReader("configurationFile.properties"));
        //获取配置文件中指定类的Class对象
        Class<?> aClass = Class.forName((String) properties.get("className"));
        //获取构造方法对象
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);//取消安全检查
        //创建配置文件中指定类的对象
        Object o = declaredConstructor.newInstance();
        //获取配置文件中指定方法的对象
        Method mathod = aClass.getDeclaredMethod((String) properties.get("mathodName"));
        //取消安全检查
        mathod.setAccessible(true);
        mathod.invoke(o);//执行方法
    }
}

class Dog {
    private Dog() {
    }

    public void eat() {
        System.out.println("狗吃骨头");
    }

    public void sleep() {
        System.out.println("狗晚上睡觉");
    }
}

class Cat {
    private Cat() {
    }

    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void sleep() {
        System.out.println("猫白天睡觉");
    }
}
配置文件内容:								
className=mydemo4.Dog					
mathodName=sleep					
对应运行结果:					
狗晚上睡觉					

配置文件内容:
className=mydemo4.Cat
mathodName=eat
对应运行结果:
猫吃鱼
发布了55 篇原创文章 · 获赞 23 · 访问量 4343

猜你喜欢

转载自blog.csdn.net/y_Engineer/article/details/98399226