Java反射机制介绍与应用

1.对象创建的几种方法(显式)

  1. 用new语句创建对象,这是最常用的创建对象的方式。
  2. 调用对象的clone()方法。
  3. 运用反序列化手段,调用java.ioObjectinputStream对象的readObject()方法。
  4. 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

2.反射概念

(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制

反射的作用动态获取类的信息,进一步实现需要的功能。

原理:

java对象的映射 java对象反射_java对象的映射

3.反射相关API

注意以下API除了Class类外,其他类都位于java.lag.reflect包中。

1.Class类型

一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。

Class类是java反射机制的基础,通过Class类,可以得到一个类的基本信息。

获得Class类实例的常用方法

  1. getClass方法:通过对象向获得Class实例。
Users users1 = new Users();
        Users users2 = new Users();
        Class uclass1 = users1.getClass();
        Class uclass2 = users2.getClass();
        System.out.println(uclass1);//class com.ff.webpro.reflect.Users
        System.out.println(uclass2);//class com.ff.webpro.reflect.Users
        System.out.println(uclass1 == uclass2);//true
  1. 类名.class方式:通过类名获得Class实例。
Class uclass1 = Users.class;
        System.out.println(uclass1);//class com.ff.webpro.reflect.Users
  1. Class类的静态方法 forName(String name):通过类型获得Class实例
String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        System.out.println(uclass);//class com.ff.webpro.reflect.Users
2.Constructor构造方法

通过getXXX方法获得构造方法的基本信息。

newInstance(Object… initargs) :创建实例

  1. 获得无参构造方法(public)
String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);        
        Constructor constructor = uclass.getConstructor();//默认获得的是无参构造方法(public)
        Users users = (Users) constructor.newInstance();//创建对象
  1. 获得有参构造方法(public)
String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        Constructor constructor = uclass.getConstructor(int.class, String.class);
        Users users = (Users) constructor.newInstance(23, "张三");
  1. 获得有参构造方法(private)
String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        Constructor constructor = uclass.getDeclaredConstructor(String.class,int.class);
        constructor.setAccessible(true);//设置访问权限,可以访问private,
        Users users = (Users) constructor.newInstance("张三",23);

注意:getDeclaredConstructor方法和getConstructor方法的区别

getDeclaredConstructor(Class<?>… parameterTypes)这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。getDeclaredConstructors()的返回结果就没有参数类型的过滤了。

getConstructor(Class<?>… parameterTypes)这个方法返回的是上面那个方法返回结果的子集,只返回制定参数类型访问权限是public的构造器。getConstructors()的返回结果同样也没有参数类型的过滤。

Constructor[]数组遍历

Constructor[] declaredConstructors = uclass.getDeclaredConstructors();
        for (Constructor con:declaredConstructors){
            con.setAccessible(true);
            //具体操作
        }
3.Method方法

Method类将类中的方法进行封装,可以动态获得方法的信息,动态调用某一个对象的具体方法invoke

getName:获得方法名字
getParameterTypes:获得方法参数类型

invoke(Object obj, Object… args) :使用obj调用该方法,参数为args

Method实例都是通过Class类的方法获得
Method getMethod(String name, Class… parameterTypes) :通过指定方法名,参数类型,返回一个Method实例

String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        Users users = (Users) uclass.newInstance();

        /*
          获得public方法
        */
        Method eatm = uclass.getMethod("eat");
        eatm.invoke(users);//使用users对象调用方法
        /*
          获得public方法,并传参
        */
        Method eatm = uclass.getMethod("eat",String.class);
        eatm.invoke(users,"aaa");
        /*
          获得private方法,并传参
        */
        Method eatm = uclass.getDeclaredMethod("eat",int.class,String.class);
        eatm.setAccessible(true);
        eatm.invoke(users,100,"jim");

Method方法遍历

String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        Users users = (Users) uclass.newInstance();

        Field[] fs = uclass.getDeclaredFields();
        for (Field f : fs
        ) {
            String name = f.getName();
            Method declaredMethod = uclass.getDeclaredMethod("get"+String.valueOf(name.charAt(0)).toUpperCase()+name.substring(1));//getName方法
            System.out.println(declaredMethod.invoke(users));
            
        }
4.Field属性

Field类将类的属性进行封装,可以获得属性的基本信息、属性的值,也可以对属性进行赋值。

getName:返回属性的名字
Set:设置属性值

String className = "com.ff.webpro.reflect.Users";
        Class uclass = Class.forName(className);
        Users users = (Users) uclass.newInstance();
        Field numf =uclass.getField("num");//获得指定的公共的成员变量
              numf.set(users,100);
        Field namef = uclass.getDeclaredField("name");//获得指定的私有成员变量
        namef.setAccessible(true);
        namef.set(users,"jim");

Field[]数组遍历

Field[] fs = uclass.getDeclaredFields();
        for (Field f : fs
        ) {
            f.setAccessible(true);
            //具体操作
        }