反射: 框架设计的灵魂。
将类的各个组成部分封装成其他对象 就是反射机制。
java代码在计算机中经理的三个阶段
Source源代码阶段 Person.java -- (javac)--> Person.class
Class 类对象阶段 Person.class --(ClassLoader)--> 加载到内存中
Runtime 运行时阶段 new Person()
Class类对象
Class类中一般包含 成员变量(Field[ ] fields),构造方法(Constructor[ ] cons),成员方法(Method[ ] methods)分别将他们封装成括弧里面的对象
Class本身也是一个类
Class对象只能有系统建立对象
一个类在JVM中只会有一个Class实例,一个Class对象对应的是一个加载到JVM中的一个.class文件
每个类的实例都会记得自己是有哪个Class实例所生成
通过Class 可以正的得到一个类中的完整结构。
好处:
1,可以在程序运行过程中,操作这些对象
2,可以解耦,提高程序的可扩展性。
获取Class 对象的方式(对应三个阶段 )
1, 基本用这个
Class.forName("全类名"): 手动的将字节码文件加载进内存,返回Class对象 (多用于配置文件,将雷鸣定义在配置文件中,读取文件,加载类)
2,类名.class : 通过类名.class 获取 (多用于参数的传递)
3, 对象.getClass(), Object类中定义的。(多用于对象的获取字节码的方式)
4, 还有一个通过ClassLoader
ClassLoader cl = this.getClass().getClassLoader();
Class clazz =cl.loadClass("全类名");
- 同一个字节码文件再一次程序运行过程中,只会被加载一次,上面三种方式获取到的Class 对象都是同一个。
Class对象功能:
获取功能
1,获取成员变量们

private static void method3() {
try {
Class clazz = Class.forName("com.bg.collections.fanshe.Student");
// 拿到所有共有的属性, 包括父类的属性
Field[] fields = clazz.getFields();
// 拿到所有属性,但是不包括父类的属性
// Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("属性的名字:" + field.getName());
System.out.println("属性的类型:" + field.getType());
System.out.println("=================");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
getFiled() 获取所有public 修饰的成员变量
getFiled(String name) 获取指定的public 修饰的成员变量
获取到Field 可做的操作 就是 获取值 和 设置值

3, 获取成员方法们

private static void method2() {
try {
Class clazz = Class.forName("com.bg.collections.fanshe.Student");
// 拿到全部的共有方法
Method[] methods = clazz.getMethods();
// 拿到全部的方法,包括私有方法;
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("方法名:" + method.getName());
System.out.println("返回值类型:" + method.getReturnType());
Class[] pes = method.getParameterTypes();
if (pes != null && pes.length > 0) {
for (Class pe : pes) {
System.out.println("参数类型:" + pe.getName());
}
}
System.out.println("=============================");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
4, 获取类名
cls.getName()
5,获取接口
cls.getInterfaces()
通过反射的方法来创建对象
private static void method1() {
try {
Class cls = Class.forName("com.bg.collections.fanshe.Student");
//调用的无参构造方法
Constructor c1 = cls.getConstructor();
Student stu1 = (Student) c1.newInstance();
System.out.println();
// 这是拿到 Student(String school) 的构造方法。
Constructor c2 = cls.getConstructor(String.class, int.class);
Student stu2 = (Student) c2.newInstance("我的奋斗", 20);
System.out.println("执行的是公有构造方法Student(String name,int age)");
//强制调用私有构造方法;
Constructor c3 = cls.getDeclaredConstructor(String.class);
// 破除私有封装,下面就可以强制调用私有构造方法。
c3.setAccessible(true);
Student stu3 = (Student) c3.newInstance("我的学校");
System.out.println("调用的是私有的构造方法 Student(String school)");
} catch (Exception e) {
e.printStackTrace();
}
}
通过反射调用指定方法:
/**
* 通过反射调用指定的方法
*/
private static void method4() {
try {
Class clazz = Class.forName("com.bg.collections.fanshe.Student");
Constructor c = clazz.getConstructor();
Object obj = c.newInstance();
//调用public指定方法
Method setInfo = clazz.getMethod("setInfo", String.class, String.class);
setInfo.invoke(obj, "小明", "高中");
// 调用有返回值的public 指定方法;
Method getSchool = clazz.getMethod("getSchool");
String school = (String) getSchool.invoke(obj);
System.out.println("school = " + school);
// 调用 private 指定方法
Method setX = clazz.getDeclaredMethod("setX");
setX.setAccessible(true);
setX.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
通过反射调用指定属性:
/**
* 通过反射调用指定的属性 ;
*/
private static void method5() {
try {
Class clazz = Class.forName("com.bg.collections.fanshe.Student");
Constructor con = clazz.getConstructor();
Student student = (Student) con.newInstance();
//调用公有属性 clas
Field field = clazz.getField("clas");
field.set(student, 23);
System.out.println("调用公有属性 clas = " + field.get(student));
//调用私有属性 school;
Field f = clazz.getDeclaredField("school");
f.setAccessible(true);
f.set(student, "高中");
System.out.println("调用私有属性 school = " + f.get(student));
} catch (Exception e) {
e.printStackTrace();
}
}
Java 的动态代理
Proxy: 专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态的生成实现类。
创建一个动态代理类所对应的Class对象
场景
一个java项目,其中有100个java类,没个java类有10个方法,现在有个需求,需要在没个java方法上加两句话,在方法执行前 System.out.print("方法开始执行"); 在方法执行后 System.out.print("方法执行完毕");
.................太难了.................
网友评论