Java反射机制

反射的概念

  • Java反射机制是在运行状态时,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。

  • 通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。

  • 要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

    image-20220106100421016

获取class对象方式(3种方式)

  • Class.forName("全类名"):将字节码文件加载进内存,返回Class对象

    多用于配制文件,将类名定义在配置文件中。读取文件,加载类。

  • 类名.class: 通过类名的属性class获取

    多用于参数的传递

  • 对象.getClass():getClass()方法在Object类中定义着。

    多用于对象的获取字节码的方式

    结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。

定义一个Person类,利用三种反射方式获取class对象

//定义Person类
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

/*利用三种反射方式获取class对象
	1、Class.forName("全类名")
	2、类名.class
	3、对象.getClass()
*/
public class reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        //Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
        Class cls1 = Class.forName("Person");
        System.out.println(cls1);//class Person

        //类名.class: 通过类名的属性class获取
        Class cls2 = Person.class;
        System.out.println(cls2);//class Person

        //对象.getClass():getClass()方法在Object类中定义着。
        Person person = new Person();
        Class cls3 = person.getClass();
        System.out.println(cls3);//class Person

        // == 比较3个对象
        System.out.println(cls1==cls2);//true
        System.out.println(cls2==cls3);//true

    }
}

反射对象的使用

获取成员变量们

Field [] getFields()		// 获取所有public修饰的成员变量 
Field [] getField(String name)		//	获取指定名称的public修饰的成员变量
 
Field [] getDeclaredFields() //获取所有的成员变量,不考虑修饰符
Field [] getDeclaredFields(String name)  //获取指定的成员变量,不考虑修饰符
  
//Demo 获取成员变量们,定义Person类,利用反射获取成员变量们
  public class Person {
    public int a;
    public String b;
    protected String c;
    private String name;
    private int age;
    private String d;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

    public void eat() {
        System.out.println("eat....");

    }

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


//利用反射获取成员变量们
import java.lang.reflect.Field;

public class reflect {
    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class<Person> personClass = Person.class;

        //1.Field[] getFields()获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);  //public int Person.a
                                        //public java.lang.String Person.b
        }

        System.out.println("=====================");
        //2.Field getField(String name)
        Field b = personClass.getField("b");
        //获取成员变量a的值
        Person p = new Person();
        Object value = b.get(p);
        System.out.println(value); // null
        //设置a的值
        b.set(p,"张三");
        System.out.println(p);//Person{name='null', age=0, a=0, b='张三', c='null', d='null'}

        System.out.println("================");

        //Field [] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        /*
        private java.lang.String Person.name
        private int Person.age
        public int Person.a
        public java.lang.String Person.b
        protected java.lang.String Person.c
        private java.lang.String Person.d
         */


        //Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("d");
        //忽略访问权限修饰符的安全检测
        d.setAccessible(true); //暴力反射
        Object value2 = d.get(p);
        System.out.println(value2); //null
        //Field [] getDeclaredFields(String name)
    }
}

获取构造方法们

Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)
  
Constructor<?>[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class reflect2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //0.获取Person的Class对象
        Class<Person> personClass = Person.class;
        //Constructor<T> getConstructor(类<?>... parameterTypes)
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        //创建对象
        Person p = constructor.newInstance("张三", 28);
        System.out.println(p);//Person{name='张三', age=28, a=0, b='null', c='null', d='null'}



        Constructor<Person> constructor2 = personClass.getConstructor();
        Person p2 = constructor2.newInstance();
        System.out.println(p2);//Person{name='null', age=0, a=0, b='null', c='null', d='null'}

        Person p3 = personClass.newInstance();
        System.out.println(p3);
    }
}

获取成员方法们

Method[] getMethods()
Method getMethod(String name,类<?>... parameterTypes)
  
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name,类<?>... parameterTypes)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class reflect3 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //0.获取Person的Class对象
        Class<Person> personClass = Person.class;

        //获取指定名称的方法
        Method eat_method = personClass.getMethod("eat");

        //执行方法
        Person p = new Person();
        eat_method.invoke(p);//eat....


        Method eat_method2 = personClass.getMethod("eat",String.class);
        eat_method2.invoke(p,"饭");//eat...饭

        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            //System.out.println(method);
            String name = method.getName();
            System.out.println(name);
        }

        //获取类名
        String className = personClass.getName();
        System.out.println(className);
    }
}

获取类名

String getName()

成员变量&构造方法&方法对象的应用

Field:成员变量
  *操作:
  1.设置值
  	* void set(Object obj,Object value)
  2.获取值
  	* get(Object obj)
  3.忽略访问权限修饰符的安全检查
  	* setAccessible(true) 暴力反射
  
 Constructor:构造方法
   创建对象:
   	* T newInstance(Object... initargs)
   	* 如果使用空参数构造方法创建对象,操作可简化:Class对象的newInstance方法
   
   
 Method:方法对象:
   执行方法:
   	* 执行方法:
				*	Object invoke(Object obj,Object... args)
        
     * 获取方法名称:
				*	String getName:获取方法名
   		
  

我们欠生活一个努力!
原文地址:https://www.cnblogs.com/lalalaxiaoyuren/p/15769912.html