一、什么是反射
反射就是程序可以访问,检测和修改它本身状态或行为的一种能力,也就是在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
二、反射的原理:
下图是类的正常加载过程、反射原理与class对象:
Class对象的由来是将.class文件读入内存,并为之创建一个Class对象。
三、哪里用到反射机制?
1.JDBC中,利用反射动态加载了数据库驱动程序。 2.Web服务器中利用反射调用了Sevlet的服务方法。 3.Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。 4.很多框架都用到反射机制,注入属性,调用方法,如Spring。
四、反射机制的优缺点?
优点:可以动态执行,在运行期间根据业务功能动态执行方法、访问属性,最大限度发挥了java的灵活性。 缺点:对性能有影响,这类操作总是慢于直接执行java代码。
五、动态代理是什么?有哪些应用?
动态代理是运行时动态生成代理类。 动态代理的应用有 Spring AOP数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。
六、怎么实现动态代理?
JDK 原生动态代理和 cglib 动态代理。 JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。
七、反射具体使用及方法介绍
获取Class类对象的三种方式
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
示例代码:
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("--------");
Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c1 == c3);
System.out.println("--------");
Class<?> c4 = Class.forName("com.itheima_02.Student");
System.out.println(c1 == c4);
}
}
获取构造方法
- Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
- Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
- Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
- Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象
案例需求
public class Student {
private String name;
int age;
public String address;
public Student() {
}
private Student(String name) {
this.name = name;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
private void function() {
System.out.println("function");
}
public void method1() {
System.out.println("method");
}
public void method2(String s) {
System.out.println("method:" + s);
}
public String method3(String s, int i) {
return s + "," + i;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
public class ReflectDemo02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> c = Class.forName("com.itheima_02.Student");
Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
Object obj = con.newInstance("林青霞", 30, "西安");
System.out.println(obj);
}
}
Constructor类创建对象方法
- T newInstance(Object…initargs)根据指定的构造方法创建对象 获取类的成员方法
- Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
- Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
- Method getMethod(String name, Class<?>… parameterTypes)返回单个公共成员方法对象
- Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象
Method执行方法的方法
- Objectinvoke(Object obj,Object… args)调用obj对象的成员方法,参数是args,返回值是Object类型
案例需求
- 通过反射获取成员方法并调用
- 代码实现
- 学生类:参见上方学生类
public class ReflectDemo02 {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("com.itheima_02.Student");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method m1 = c.getMethod("method1");
m1.invoke(obj);
Method m2 = c.getMethod("method2", String.class);
m2.invoke(obj,"林青霞");
Method m3 = c.getMethod("method3", String.class, int.class);
Object o = m3.invoke(obj, "林青霞", 30);
System.out.println(o);
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
}
获取类的成员变量
- Field[] getFields()返回所有公共成员变量对象的数组
- Field[] getDeclaredFields()返回所有成员变量对象的数组
- Field getField(Stringname)返回单个公共成员变量对象
- Field getDeclaredField(String name)返回单个成员变量对象
给成员变量赋值的方法
- voidset(Object obj,Object value)给obj对象的成员变量赋值为value
案例需求
- 通过反射获取成员变量并赋值
- 代码实现
- 学生类:参见上方学生类
public class ReflectDemo02 {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("com.itheima_02.Student");
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj, "林青霞");
System.out.println(obj);
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj,30);
System.out.println(obj);
Field addressField = c.getDeclaredField("address");
addressField.setAccessible(true);
addressField.set(obj,"西安");
System.out.println(obj);
}
}
|