JAVA学习笔记-反射
一、什么是反射
反射允许对封装类的字段、方法和构造函数的信息进行编程访问。
二、获取class对象的三种方式
Class.forName(“全类名”);
源代码阶段。
类名.class
加载阶段。
对象.getClass();
运行阶段。
//最为常用
Class clazz = Class.forName("com.myreflect.Student");
//一般更多的是当作参数进行传递
Class clazz1 = Student.class;
System.out.println(clazz1);
//当有了一个对象后,才使用
Student stu = new Student();
System.out.println(stu.getClass());
三、反射获取构造方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 获取字节码文件对象
Class clazz = Class.forName("com.myreflect.Student");
// 获取构造方法
Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
int modifoers = constructor.getModifiers();
Parameter[] parameters = constructor.getParameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }
constructor.setAccessible(true); //暴力创建
Student stu = (Student) constructor.newInstance("张三", 19);
System.out.println(stu);
}
四、反射获取成员变量
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 获取字节码文件对象
Class clazz = Class.forName("com.myreflect.Student");
// 获取成员变量
// Field[] declaredFields = clazz.getDeclaredFields();
// 获取单个变量 获取私有的变量
Field field = clazz.getDeclaredField("name");
System.out.println(field);
// 获取数据类型
Class<?> type = field.getType();
System.out.println(type);
// 获取成员变量记录的值
field.setAccessible(true); //不进行校验修饰符,因为name是private的
Student student = new Student("张三", 12);
System.out.println(field.get(student));
}
五、反射获取成员方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 获取字节码文件对象
Class clazz = Class.forName("com.myreflect.Student");
// 获取成员方法
Method method = clazz.getDeclaredMethod("sleep");
int modifiers = method.getModifiers();
// 方法的异常
Class<?>[] exceptionTypes = method.getExceptionTypes();
method.setAccessible(true);
Student stu = new Student("张三", 18);
method.invoke(stu);
}
六、综合练习
1.对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException {
Student student = new Student("张三", 29);
saveObject(student);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
Class clazz = obj.getClass();
Field[] declaredFields = clazz.getDeclaredFields();
BufferedWriter bw = new BufferedWriter(new FileWriter("two/a.txt"));
for (Field field : declaredFields) {
field.setAccessible(true);
String fieldName = field.getName();
Object o = field.get(obj);
bw.write(fieldName + ":" + o);
bw.newLine();
}
bw.close();
}
2.反射与配置文件结合,动态创建对象,并调用方法
配置文件
classname=com.myreflect.Student
method=sleep
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("two/prop.properties");
prop.load(fis);
fis.close();
Class clasz = Class.forName(prop.get("classname").toString());
Constructor declaredConstructor = clasz.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Student stu = (Student) declaredConstructor.newInstance();
Method method = clasz.getDeclaredMethod(prop.get("method").toString());
method.setAccessible(true);
method.invoke(stu);
}
七、动态代理
特点:无侵入式的给代码增加额外的功能
通过接口保证,后面的对象和代理需要实现同一个接口。
public interface Star {
// 所有被代理的方法写到接口中
public abstract String sing(String name);
public abstract void dance();
}
public class BigStar implements Star{
private String name;
public String getName() {
return name;
}
@Override
public String sing(String name) {
System.out.println(this.name + "正在唱" + name);
return "谢谢";
}
@Override
public void dance() {
System.out.println(this.name + "正在跳舞");
}
public void setName(String name) {
this.name = name;
}
public BigStar(String name) {
this.name = name;
}
public BigStar() {
}
}
// 代理类
public class ProxyUtil {
/*
* 创建一个代理
*
*
*
* */
public static Star creatProxy(BigStar bigStar) {
Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), // 指定哪个加载器去加载生成的代理类
new Class[]{Star.class}, // 指定接口,代理长什么样
new InvocationHandler() { // 代理对象干什么
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理的对象, 方法, 参数数组
if("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
} else if ("dance".equals(method.getName())) {
System.out.println("准备场地,收钱");
}
return method.invoke(bigStar, args); //反射
}
});
return star;
}
}
//test
public class Test {
public static void main(String[] args) {
BigStar bigStar = new BigStar("鸡哥");
Star star = ProxyUtil.creatProxy(bigStar);
System.out.println(star.sing("只因你太美!"));
}
}