反射
好记性不如烂笔头
java 反射
java 反射的基石->Class
-
Class 内存中字节码文件
-
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
-
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
-
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
-
判断类型
- 判断是不是基本类型 isPrimitive()
- 判断是不是数组 int[].class.isArray()
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…
得到字节码的方式
Class cls = 自定义类.class;
Class cls1 = Persion.class;
Class cls2 = Date.class;
- 类名.class,例如 System.class
- 对象.getClass(), 例如:new Date().getClass();
- Class.forName(“类名”),例如:Class.forName(“java.util.Date”);(主要用第三种)
什么是反射
反射就是把java类中的各种成分映射成相应的java类
类中的成分:Field、Method、Contructor、Package
Construtor构造方法的应用
- 获取Construtor (先获取字节码Class,在获取构造)
-
Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
-
Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
-
Construtor 的方法,用来创建对象
T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
代码示例
// new String(new StringBuilder("abc"))
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str2 = (String) constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
- Class.newInstrance() ,创建类的无参对象
- Constructor.newInstrache(),可以创建有参对象,并赋值
Field成员变量的反射
- 获取Field (先获取字节码Class)
-
Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
-
Field [] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
- 获取Filed 的值
public static void main(String[] args){
//成员变量Field
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass().getField("y");
//fieldY的值是多少?是 5,错!fieldY不是对象身上的变量,而且类上,
//要用它去取某个对象上对应的值
System.out.println(fieldY.get(pt1));
//私有变量
Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
}
public class ReflectPoint {
private int x;
public int y;
public ReflectPoint() {}
public ReflectPoint(int x, int y) {
this.x = x;
this.y = y;
}
}
Method成员方法的反射
- 获取Construtor (先获取字节码Class,在获取构造)
-
Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
-
Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
代码示例
public static void main(String[] args){
String str1 = "abc";
//String charAt() 方法
Method methodCharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str1,1));
}
对接收数组参数的成员方法进行反射
代码示例
public static void main(String[] args){
String className = args[0];
Method mainMethod = Class.forName(className).getMethod("main",String[].class);
//mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});
mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
}
class TestArguments{
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
数组与Object的关系及其反射
代码示例
//数组与Object的关系及其反射
int [] a1 = new int[]{1,2,3};
int [] a2 = new int[4];
int[][] a3 = new int[2][3];
String [] a4 = new String[]{"a","b","c"};
System.out.println(a1.getClass() == a2.getClass());
System.out.println(a1.getClass().equals(a4.getClass()));
System.out.println(a1.getClass().equals(a3.getClass()));
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
Object aObj1 = a1;
Object aObj2 = a4;
//Object[] aObj3 = a1;
Object[] aObj4 = a3;
Object[] aObj5 = a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));
true
false
false
[I
java.lang.Object
java.lang.Object
[I@2c7b84de
[Ljava.lang.String;@3fee733d
[[I@2c7b84de]
[a, b, c]
数组的反射应用
代码示例
private static void printObject(Object obj) {
Class clazz = obj.getClass();
if(clazz.isArray()){
int len = Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}