Java反射机制详解——框架的灵魂所在
反射作为框架的核心,在Java中处于一个极为重要的地位,而且反射在Java中属于比较高级的技术,需要有对Java一定的理解才可以掌握好。反射可以在程序运行过程中修改程序的行为。但是与此同时反射也是极其危险的,需要谨慎使用。
Class
Class不同于创建类的关键字class,Class本质上也是一个类,Class对象用来表示为在虚拟机上运行的类和接口。
Class的获取
在反射当中获取Class的方法有三种
- 通过Object.getClass()
- 通过类名.class
- 通过Class.forName(“类的全限定类名”)
Class的名字
-
Class.getName()
- 当Class代表一个引用时:其返回全限定类名:“com.clander.MyClander”
- 当Class代表一个基本数据类型时:其返回它本身。例如:
int.class int
- 当Class代表是数组时:返回[[[I这样类型的名字,例如:
int []
的名字为[I
String[].getClass().getName() = [L java.lang.String
- Class.getSimpleName()
simpleName用于获取内部类的简单类名
当获取类数组的SimpleName时不是在前面加[,而是在后面加[]。
- Class.getCanonicalName()
- getCanonicalName() 返回的也是全限定类名,但是对于内部类不用$,而用.
- getCanonicalName() 对于数组类型同simpleName一样,也是在后面加[]
- getCanonicalName() 不同与simpleName的是,不存在的时候返回null,而不是空字符串。
- 局部类和匿名内部类不存在CanonicalNameClass获取修饰符
获取修饰符
我们可以通过Class.getModifiers();
来获取修饰符的值它打印出来是一个数字的形式;我们还可以使用Modifier 类内置的toString() 方法,来将修饰符打印出来。
获取Class的成员
获取Field
- Class.getField(String name) 获取的是非私有属性,并且当在当前Class中找不到时会向祖先类获取。
- Class.getDeclaredField(String name) 获取的是Class中呗private修饰的属性。
- Field[] getDeclaredFields() 获取自身所有的属性但不包含从父类继承下来的属性。
- Field[] getFields() 获取自身所有public属性,包括从父类继承下来的。
获取Method
-
Class.getMethod(String name,Class<?>…parameterTypes) 获取的是非私有方法,并且当在当前Class中找不到时会向祖先类获取。
-
Class.getDeclaredMethod(String name,Class<?>…parameterTypes) 获取的是Class中呗private修饰的方法。
-
Method[] getDeclaredMethods() 获取自身所有的方法但不包含从父类继承下来的方法。
-
Method[] getMethods() 获取自身所有public方法,包括从父类继承下来的。
获取Constructor构造器
与Method和Field基本一致这里不再赘述
Field
Field类型获取
- Type getGenericType() 可以返回泛型的类型
- Class<?> getType() 返回类型与Class.getName()返回基本相同
获取修饰符
与Class获取修饰符方法一致。
Field的读取和赋值
读取:
- Object get(Object o)
- byte getByte(Object o)
- int getInt(Object o)
- long getLong(Object o)
- float getFloat(Object o)
- double getDouble(Object o)
- boolean getBoolean(Object o)
- char getChar(Object o)
赋值:
- void set(Object o,Object value)
- void setByte(Object o,byte value)
- void setInt(Object o,int value)
- void setLong(Object o,long value)
- void setFloat(Object o,float value)
- void setDouble(Object o,double value)
- void setBoolean(Object o,boolean value)
- void setChar(Object o,char value)
Method
获取方法名
**Method.getName()**放回方法名
获取方法参数
Class<?>[] getParameterTypes() 获取所有的参数类型
Type[] getGenericParameterTypes() 获取所有的参数类型包括泛型
获取返回值类型
**Class<?> getReturnType()**获取返回值类型
**Type getGenericReturnType()**获取返回值类型包括泛型
方法的执行(重点!!!)
**public Object invoke(Object obj,Object…args)**invoke方法中的第一个参数表示方法所属类的实例对象,如果这个方法属于静态方法那么这个值为null,后面的可变参数列表为对应参数,返回值为Object。
如果在Method被invoke的过程中本身抛出了异常那么这个异常会被包装在InvocationTargetException中,而通过**InvocationTargetException.getCause()**可以获取真正的异常。在一个private方法被执行之前一定要提前setAccessible(true)
Constructor
Constructor表示为构造方法,主要用于创建类对象。它的方法大体与Method一致,主要重要的方法为创建类对象的方法newInstance()
实验
使用反射解析某个你创建的类,把类中所有的属性、方法、接口都提取出来。要求:通过三种不同的方式获取 Class 对象;
修改解析出来的类的属性值,然后再给类添加新的属性;
调用类方法(包括私有方法、静态方法和构造方法),执行后打印结果;
解析出该类的父类对象,并同样修改其父类的属性值并调用父类的方法。
package T08reflection;
/**
* @Author: Administrator
* Date: 2021/12/10 15:41
* @Version:
* @Description:
*/
public interface Impl {
void showMe();
}
package T08reflection;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: Administrator
* Date: 2021/12/10 15:33
* @Version:
* @Description:
*/
public class A implements Impl {
public int a = 10;
private List<String> list = new ArrayList<>();
public A() {
}
public A(int a) {
this.a = a;
}
private void hello() {
System.out.println("hello");
}
private static void a() {
System.out.println("A!");
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public void showMe() {
System.out.println("showMe");
}
}
package T08reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @Author: Administrator
* Date: 2021/12/10 15:59
* @Version:
* @Description:
*/
public class Exemple {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
A a = new A();
Class<? extends A> aClass = a.getClass();
Class<A> aClass1 = A.class;
Class<?> aClass2 = Class.forName("T08reflection.A");
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName());
System.out.println(Modifier.toString(field.getModifiers()));
System.out.println("--------------------");
}
Field a1 = aClass1.getField("a");
int a2 = a1.getInt(a);
System.out.println(a2);
a1.set(a, 15);
a2 = a1.getInt(a);
System.out.println(a2);
System.out.println("-----------------------------------");
Method[] declaredMethods = aClass2.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method.getName());
System.out.println(Modifier.toString(method.getModifiers()));
System.out.println("----------------------------");
}
Method hello = aClass2.getDeclaredMethod("hello");
hello.setAccessible(true);
hello.invoke(a);
Method a3 = aClass.getDeclaredMethod("a");
a3.setAccessible(true);
a3.invoke(null);
Class<?>[] interfaces = aClass1.getInterfaces();
for (Class<?> tClass:interfaces){
System.out.println(tClass.getName());
}
}
}
感谢您的阅读,如果本篇文章对您有帮助,欢迎点赞,关注,您的阅读是我莫大的鼓励!