java反射
一、理论
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
二、案例演示
/**
* 演示类
*/
public static class Person {
static {
System.out.println("静态代码块执行");
}
private Integer id;
private String name;
public Person(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public Person() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + "]";
}
}
1、获取class对象的三个方式
/**
* 类.class
* 对象.getClass
* Class.forName
*/
@Test
public void test1() throws Exception {
String className = "d18_reflect.review.ReflectDemo.Person";
Class<?> clazz = Class.forName(className); // 方式1
clazz = Person.class; // 方式2
clazz = new Person().getClass(); // 方式3
}
2、class.forName() 三个参数以及自设类加载器候补顺序
* 自设定类加载器数组的顺序一般是:自设,Thread,本类,system。
* forName第二个参数如果为false,那么静态代码块不执行。
*/
@Test
public void test2() throws Exception {
String className = "d18_reflect.review.ReflectDemo$Person";
ClassLoader cl = new ClassLoader[]{Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(),
ClassLoader.getSystemClassLoader()}[1];
Class<?> clazz = Class.forName(className, true, cl);
// 为false,静态代码块不执行
}
3、Method的反射
* getDeclaredMethods : 本类的所有方法
* getMethods:本类的公开方法含父类
*/
@Test
public void test3() throws Exception {
Class<?> clazz = Person.class;
Person person = (Person)clazz.newInstance();
Method[] methods = clazz.getDeclaredMethods(); // 所有本类声明的方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("_______________");
Method[] methods2 = clazz.getMethods(); //本类所有公开的方法
for (Method method : methods2) {
System.out.println(method);
}
Method method = clazz.getMethod("setName",new Class[]{String.class});
System.out.println(method);
Object object = method.invoke(person, "哈哈"); //方法执行
}
4、Field的反射
* getDeclaredFields : 本类的声明字段
* getFields:全部公开字段
* setAccessible(true) 可访问公开字段
*/
@Test
public void test4() throws Exception{
Person demo = new Person();
Class<?> clazz1 = Person.class;
Field[] fields = clazz1.getFields();
for (Field field : fields) {
System.out.println("全部公开字段"+field.getName());
}
Field[] fields2 = clazz1.getDeclaredFields();
for (Field field : fields2) {
System.out.println("本类声明字段:"+field.getName());
}
//测试如何调用一个字段?
Field declaredField = clazz1.getDeclaredField("name");
declaredField.setAccessible(true); //暴力反射,私有字段采用
declaredField.set(demo,"5");
Object object = declaredField.get(demo);
System.out.println(object.toString());
}
5、数组的反射
/**
* 5、数组的反射
* clazz.isArray() : 判断是数组
* Array.getLength : 数组长度
* Array.get(arr, 3):数组角标3的元素
*/
@Test
public void test5() throws Exception{
Object[] arr = new String[5];
for (int i = 0; i < arr.length; i++) {
arr[i] = i +"";
}
Class<?> class2 = arr.getClass();
if(class2.isArray()){
System.out.println(Array.getLength(arr));
System.out.println(Array.get(arr, 3));
}
}
6、泛型反射
class Parent<T>{}
class Student extends Parent<Object> {}
class StudentExt extends Student{}
/**
* 6、泛型反射
* getGenericSuperclass : 带泛型参数的父类
* ParameterizedType : type的子接口
* ParameterizedType.getActualTypeArguments : 真实类型参数的数组
*/
@Test
public void test6() {
// System.out.println(Object.class.getSuperclass()); //null
// System.out.println(Student.class.getSuperclass());//class d18_reflect.review.ReflectDemo$Parent
// System.out.println(Student.class.getGenericSuperclass());//d18_reflect.review.ReflectDemo$Parent<java.lang.Object>
Class<?> clazz = findTtype(Person.class);
System.out.println(clazz);
}
/**
* 父级泛型参数的类型查询-只支持2级查询
*/
public static Class<?> findTtype(Class<?> entity){
Type type = entity.getGenericSuperclass(); // 带泛型参数的类型,class父接口
if (!(type instanceof ParameterizedType)) {
type = entity.getSuperclass().getGenericSuperclass();
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Class entityClass = (Class) parameterizedType.getActualTypeArguments()[0];
return entityClass;
}
/**
* 通过继承方式TypeReference类方式,获取子类传递的实际泛型参数
*/
abstract class TypeReference<T> {
private final Type rawType;
protected TypeReference() {
rawType = getSuperclassTypeParameter(getClass());
}
Type getSuperclassTypeParameter(Class<?> clazz) {
Type genericSuperclass = clazz.getGenericSuperclass();
if (genericSuperclass instanceof Class) {
if (TypeReference.class != genericSuperclass) {
return getSuperclassTypeParameter(clazz.getSuperclass());
}
}
Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
if (rawType instanceof ParameterizedType) {
rawType = ((ParameterizedType) rawType).getRawType();
}
return rawType;
}
public final Type getRawType() {
return rawType;
}
}