Java反射机制介绍与应用
1.对象创建的几种方法(显式)
- 用new语句创建对象,这是最常用的创建对象的方式。
- 调用对象的clone()方法。
- 运用反序列化手段,调用java.ioObjectinputStream对象的readObject()方法。
- 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
2.反射概念
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的作用:动态获取类的信息,进一步实现需要的功能。
原理:
3.反射相关API
注意以下API除了Class类外,其他类都位于java.lag.reflect包中。
1.Class类型
一旦class文件被加载到内存,就会为其创建一个Class对象。任何类被使用时都会创建一个Class对象。
Class类是java反射机制的基础,通过Class类,可以得到一个类的基本信息。
获得Class类实例的常用方法:
- 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
- 类名.class方式:通过类名获得Class实例。
Class uclass1 = Users.class;
System.out.println(uclass1);//class com.ff.webpro.reflect.Users
- 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) :创建实例
- 获得无参构造方法(public)
String className = "com.ff.webpro.reflect.Users";
Class uclass = Class.forName(className);
Constructor constructor = uclass.getConstructor();//默认获得的是无参构造方法(public)
Users users = (Users) constructor.newInstance();//创建对象
- 获得有参构造方法(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, "张三");
- 获得有参构造方法(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);
//具体操作
}