反射
1.概念
反射—解析类,通过字节码对象来获取实例对象的过程(运行时期)
Class类—代表类的类—创建的对象代表具体类(字节码文件对应类—字节码文件—字节码对象)
Field类—代表属性的类—创建对象就是具体属性
Method类—代表方法的类–创建对象就是具体方法
Constructor类—代表构造方法的类–创建对象就是具体的构造方法
2.获取字节码对象的方式
1)通过类型.class返回对应的字节码对象
//String类的字节码对象
Class<String> clz=String.class;//class java.lang.String
//接口的字节码对象
Class<List> clz1=List.class;//interface java.util.List
//基本类型的字节码对象
Class clz2=int.class;//int
System.out.println(clz);
2)通过对象调用gatClass方法返回对应的字节码对象
Class<String> clz=(Class<String>)"abc".getClass();
System.out.println(clz);//class java.lang.String
3)通过Class.forName(“字符串”)来获取对应的字节码对象(保证字符串内容没有问题)
Class<List> clz=(Class<List>)Class.forName("java.util.List");
System.out.println(clz);//interface java.util.List
3.获取实例对象的方式
1)通过字节码对象调用newInstance()执行无参构造
//执行无参构造来创建实例对象
//String str=clz.newInstance();
2)构造方法类的对象调用newInstance有参方法执行有参构造并且赋值
//先获取有参构造---(String original)
//参数类型需要以字节码对象的形式来传入才能找到对应的构造方法
Constructor c=clz.getConstructor(String.class);
//执行有参构造并且赋值返回实例对象
String str= (String) c.newInstance("abc");
//
String str1=new String("abc");
通过反射来获取integer类的实力对象
//获取字节码对象
Class<Integer> clz1=Integer.class;
//获取有参构造---(int)
clz1.getConstructor(int.class);
Constructor<Integer> c=clz1.getConstructor(int.class);
//执行有参构造并且给构造来赋值返回实例对象
Integer in=c.newInstance("123");
System.out.println(in);
package cn.tedu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ClassDemo3 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//
Class<String> clz = String.class;
//获取构造方法
//获取指定构造方法
Constructor<String> c = clz.getDeclaredConstructor
(char[].class, boolean.class);
//暴力破解
c.setAccessible(true);
//执行构造方法并且给构造方法赋值返回实例对象
String str = c.newInstance(new char[]{'1', '2'}, true);
System.out.println(str);
}
}
属性:
package cn.tedu.reflect;
import java.lang.reflect.Field;
public class ClassDemo4 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class<String> clz=String.class;
//获取指定属性---hash
Field field= clz.getDeclaredField("hash");
//提供实例对象
String str="abc";
System.out.println(str.hashCode());
//改变属性值
//暴力破解---进行正常赋值
field.setAccessible(true);
//选择str对象的hashcode属性改值为123
field.set(str,123);
//获取属性值
System.out.println(field.get(str));
System.out.println(str.hashCode());//96354 123
}
}
方法:
package cn.tedu.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ClassDemo5 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<String> clz=String.class;
//获取指定方法
Method m=clz.getDeclaredMethod("charAt", int.class);
//提供实例对象
String str="sjgcdsvc";
//基于对于的实例对象执行方法
//str.charAt(4)
System.out.println(m.invoke(str,4));//d
}
}
反射缺点:1.打破封装原则 2.跳过泛型的类型检测
4.练习:实现clone方法
package cn.tedu.List;
import java.io.FileOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ReflectText {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException {
//创建对象
Person p=new Person();
p.setName("豆豆");
p.setAge(14);
//调用方法返回克隆对象
Person p1=(Person) clone(p);
System.out.println(p1.getName()+","+p1.getAge());
}
//实现clone方法
public static Object clone(Object obj) throws IllegalAccessException, InstantiationException, InvocationTargetException {
//1.获取原对象的字节码对象
Class<Object> clz = (Class<Object>) obj.getClass();
//2.获取实例对象(新对象)
//一定能获取一个构造方法
Constructor c = clz.getDeclaredConstructors()[0];
//获取构造方法上所有的参数类型
Class[] cs = c.getParameterTypes();
//提供数组用于存储有参构造参数初始化值
Object[] os = new Object[cs.length];
//遍历数组
for (int i = 0; i < cs.length; i++) {
//判断是否是基本数据类型
if (cs[i].isPrimitive()) {
//基本类型
if (cs[i] == byte.class || cs[i] == short.class || cs[i] == int.class){
os[i] = 0;
} else if (cs[i] == char.class) {
os[i] = '\u0000';
} else if (cs[i] == long.class) {
os[i] = 0L;
} else if (cs[i] == float.class) {
os[i] = 0.0F;
} else if (cs[i] == double.class) {
os[i] = 0.0;
} else {
os[i] = false;
}
}else{//引用类型
//引用类型的参数初始化值都是null
os[i] = null;
}
}
//执行有参构造并且赋值返回实例对象
Object o=c.newInstance(os);
//执行无参构造来创建实例对象
//Object o=clz.newInstance();
//3.获取原对象所有的指定属性
Field[] fs=clz.getDeclaredFields();
//4.把原对象的属性值赋值给新对象
for (Field f:fs){
//暴力破解
f.setAccessible(true);
//先获取原对象的属性值
Object value=f.get(obj);
//给新对象属性进行赋值
f.set(o,value);
}
return o;
}
}
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}