1. 什么是反射?
当程序在运行时,我们可以获取任意类的构造器、方法、属性等,可以调用其方法、属性等,这种动态获取类信息与动态调用对象方法的方式可以称作反射机制。
2. Class 类
- Class类也是类的一种,与class关键字是不一样的。
- 手动编写的类被编译后会产生一个Class对象,其表示的是创建的类的类型信息,而且这个Class对象保存在同名.class的文件中(字节码文件)
- 每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个Class对象。
- Class类只存私有构造函数,因此对应Class对象只能由JVM创建和加载
- Class类的对象作用是运行时提供或获得某个对象的类型信息
3. Class对象的获取
public class GetClass {
public static void main(String[] args) {
try {
Class<User> userClass = User.class;
System.out.println("根据类名: \t" + User.class);
System.out.println("根据对象: \t" + new User().getClass());
System.out.println("根据全限定类名:\t" + Class.forName("bean.User"));
// 常用的方法
System.out.println("获取全限定类名:\t" + userClass.getName());
System.out.println("获取类名:\t" + userClass.getSimpleName());
System.out.println("实例化:\t" + userClass.newInstance());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
根据类名: class bean.User
根据对象: class bean.User
根据全限定类名: class bean.User
获取全限定类名: bean.User
获取类名: User
实例化: User [name=initName, age=0]
4. Fields的获取
获取fields的方法
方法返回值 | 方法名称 | 方法说明 |
---|---|---|
Field | getDeclaredField(String name) | 获取指定name名称的(包含private修饰的)字段,不包括继承的字段 |
Field[] | getDeclaredFields() | 获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段 |
Field | getField(String name) | 获取指定name名称、具有public修饰的字段,包含继承字段 |
Field[] | getFields() | 获取修饰符为public的字段,包含继承字段 |
public class GetFields {
public static void main(String[] args) {
try{
Class<?> aClass = Class.forName("bean.User");
Field[] fields = aClass.getFields();
System.out.println("获取公有字段");
for (Field field : fields) {
System.out.println(field.getName());
}
Field[] declaredFields = aClass.getDeclaredFields();
System.out.println("获取所有字段");
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);
System.out.println(declaredField.getName());
}
System.out.println("获取指定字段");
System.out.println(aClass.getDeclaredField("age"));
}catch (Exception e){
e.printStackTrace();
}
}
}
获取公有字段
sex
获取所有字段
name
age
sex
获取指定字段
private int bean.User.age
5. Constructor的获取
方法返回值 | 方法名称 | 方法说明 |
---|---|---|
static Class<?> | forName(String className) | 返回与带有给定字符串名的类或接口相关联的 Class 对象。 |
Constructor | getConstructor(Class<?>… parameterTypes) | 返回指定参数类型、具有public访问权限的构造函数对象 |
Constructor<?>[] | getConstructors() | 返回所有具有public访问权限的构造函数的Constructor对象数组 |
Constructor | getDeclaredConstructor(Class<?>… parameterTypes) | 返回指定参数类型、所有声明的(包括private)构造函数对象 |
Constructor<?>[] | getDeclaredConstructor() | 返回所有声明的(包括private)构造函数对象 |
T | newInstance() | 调用无参构造器创建此 Class 对象所表示的类的一个新实例,可传递参数。 |
package bean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class GetConstructor {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> clazz = Class.forName("bean.User");
//第一种方法,实例化默认构造方法,User必须无参构造函数,否则将抛异常
User user = (User) clazz.newInstance();
user.setAge(20);
user.setName("Jack");
user.setSex("男");
System.out.println(user);
System.out.println("--------------------------------------------");
//获取带String参数的public构造函数
Constructor cs1 =clazz.getConstructor(String.class);
//创建User
User user1= (User) cs1.newInstance("hiway");
user1.setAge(22);
System.out.println("user1:"+user1.toString());
System.out.println("--------------------------------------------");
//取得指定带int和String参数构造函数,该方法是私有构造private
Constructor cs2=clazz.getDeclaredConstructor(String.class,int.class);
//由于是private必须设置可访问
cs2.setAccessible(true);
//创建user对象
User user2= (User) cs2.newInstance("dawdawd",25);
System.out.println("user2:"+user2.toString());
System.out.println("--------------------------------------------");
//获取所有构造包含private
Constructor<?> cons[] = clazz.getDeclaredConstructors();
// 查看每个构造方法需要的参数
for (int i = 0; i < cons.length; i++) {
//获取构造函数参数类型
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.println("构造函数["+i+"]:"+cons[i].toString() );
System.out.print("参数类型["+i+"]:(");
for (int j = 0; j < clazzs.length; j++) {
if (j == clazzs.length - 1)
System.out.print(clazzs[j].getName());
else
System.out.print(clazzs[j].getName() + ",");
}
System.out.println(")");
}
}
}
User{name='Jack', age=20, sex='男'}
--------------------------------------------
user1:User{name='hiway', age=22, sex='null'}
--------------------------------------------
user2:User{name='dawdawd', age=25, sex='null'}
--------------------------------------------
构造函数[0]:public bean.User(java.lang.String,int,java.lang.String)
参数类型[0]:(java.lang.String,int,java.lang.String)
构造函数[1]:private bean.User(java.lang.String,int)
参数类型[1]:(java.lang.String,int)
构造函数[2]:public bean.User(java.lang.String)
参数类型[2]:(java.lang.String)
构造函数[3]:public bean.User()
参数类型[3]:()
6. method的获取
import java.lang.reflect.Method;
public class GetMethod {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("testMethod");
Method[] methods = clazz.getDeclaredMethods();
Object o = clazz.newInstance();
System.out.println("获取自己声明的方法");
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取指定的方法");
Method sum = clazz.getMethod("sum", int.class, int.class);
System.out.println(sum);
System.out.println("调用该方法");
int invoke = (int) sum.invoke(o, 1,2);
System.out.println(invoke);
}catch (Exception e){
e.printStackTrace();
}
}
}
class testMethod{
public int sum(int a, int b) {
return a + b;
}
private int d(int a, int b) {
return a * b;
}
}
获取自己声明的方法
public int testMethod.sum(int,int)
private int testMethod.d(int,int)
获取指定的方法
public int testMethod.sum(int,int)
调用该方法
3