反射是什么?
能够分析类能力的程序称为反射,利用反射能够编写动态操作Java代码的程序
Class类
每个对象都有一个运行时的类型标识,称为Class,用于跟踪对象所属的类
class Person {
}
可通过Object中getClass方法、Class.forName()或T.class获取一个类对应的Class对象,每个java类型都有匹配的类对象
Person person = new Person();
Class personClass = person.getClass();
try {
Class StringClass = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class voidClass = Void.class;
其保存了描述类的各种属性,如类名(会附带包名)
String className = personClass.getName()
可通过类对象创建新的实例,newInstance()会调用默认无参的构造方法,无则报错
try {
Person person2 = (Person) personClass.newInstance();
} catch (IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
可通过==运算符判断两个类对象是否相等,多用于equals中
if (person.getClass() == person.getClass()) {
}
利用反射还原类
反射中有Field、Constructor和Method描述类的域、构造方法和方法
- 都有getName返回名称,Modifier.toString(getMidifiers())获取修饰符
- Field的getType()获取域的数据类型
- Constructor和Method的getParameterTypes()获取参数类型
- getDeclaredFields()、getDeclaredConstructors()、getDeclaredMethods()返回全部域、构造方法和方法(包括private)
- Method的getReturnType()获取返回值类型
class Reflection {
public static void reflect(String name) {
try {
Class thisClass = Class.forName(name);
Class supClass = thisClass.getSuperclass();
String modifies = Modifier.toString(thisClass.getModifiers());
if (modifies.length() > 0) {
System.out.print(modifies + " ");
}
System.out.print("class " + name);
if (supClass != null && supClass != Object.class) {
System.out.print(" extend " + supClass.getName());
}
System.out.print(" {\n");
printField(thisClass);
System.out.println();
printConstructors(thisClass);
System.out.println();
printMethods(thisClass);
System.out.println("}");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.exit(0);
}
public static void printField(Class thisClass) {
Field[] fields = thisClass.getDeclaredFields();
for (Field f : fields) {
Class type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.println(type.getName() + " " + name + ";");
}
}
public static void printConstructors(Class thisClass) {
Constructor[] constructors = thisClass.getDeclaredConstructors();
for (Constructor c : constructors) {
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.print(name + "(");
Class[] paraTypes = c.getParameterTypes();
for (int i = 0; i < paraTypes.length; i++) {
if (i > 0) {
System.out.println(", ");
}
System.out.print(paraTypes[i].getName());
}
System.out.println(");");
}
}
public static void printMethods(Class thisClass) {
Method[] methods = thisClass.getDeclaredMethods();
for (Method m : methods) {
Class returnType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.print(returnType.getName() + " " + name + "(");
Class[] paraTypes = m.getParameterTypes();
for (int i = 0; i < paraTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(paraTypes[i].getName());
}
System.out.println(");");
}
}
}
对于类Person
public class Person {
}
调用时输入类名
Reflection.reflect(Person.class.getName());
输出为
public class com.example.demo0.Person {
public com.example.demo0.Person();
}
通用toString()
- getComponentType()获取数组类型
- setAccessible(AccessibleObject[] array,boolean flag)设置对象数组的可访问标志,true为可访问私有部分
- Filed的get(Object obj)返回对应域在obj中的值
- Array的get(obj, i)获取obj数组在i中对象
class ObjectAnalyzer {
private ArrayList<Object> visited = new ArrayList<>();
public String toString(Object obj) {
if (obj == null) {
return "null";
}
if (visited.contains(obj)) {
return "...";
}
visited.add(obj);
Class thisClass = obj.getClass();
if (thisClass == String.class) {
return (String) obj;
}
if (thisClass.isArray()) {
String r = thisClass.getComponentType() + "[]{";
for (int i = 0; i < Array.getLength(obj); i++) {
if (i > 0) {
r += ",";
}
Object val = Array.get(obj, i);
if (thisClass.getComponentType().isPrimitive()) {
r += val;
} else {
r += toString(val);
}
return r + "}";
}
}
String r = thisClass.getName();
do {
r += "[";
Field[] fields = thisClass.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
if (r.endsWith("[")) {
r += ",";
}
r += f.getName() + "=";
try {
Class t = f.getType();
Object val = f.get(obj);
if (t.isPrimitive()){
r+=val;
}else {
r+=toString(val);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
r += "]";
thisClass = thisClass.getSuperclass();
}
while (thisClass != null);
return r;
}
}
调用
ArrayList<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
arrayList.add(i * i);
}
System.out.println(new ObjectAnalyzer().toString(arrayList));
通用数组拷贝
现有badCopy利用Object[]进行拷贝
class CopyUtil {
public static Object[] badCopy(Object[] a, int newLength) {
Object[] newArray = new Object[newLength];
System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength));
return newArray;
}
}
以下代码无法执行,在返回时一个Object[]无法转换成Person[],且无法针对基本数据类型转换,因为int[] 无法转换成Object[]
Person[] people = new Person[10];
people = (Person[]) CopyUtil.badCopy(people, 2 % people.length);
//int[] a = new int[10];
//a = CopyUtil.badCopy(a, 2 % a.length);
修改为goodCopy,内部使用反射Array.newInstance创建Object实例,所有对象都可通过Object进行转换
public static Object goodCopy(Object a, int newLength) {
Class thisClass = a.getClass();
if (!thisClass.isArray()) {
return null;
}
Class componentType = thisClass.getComponentType();
int length = Array.getLength(a);
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength));
return newArray;
}