- JVM已经加载过这个类: 给JVM一个类名,可以通过反射得到类的具体信息。
Java Reflection
- 反射被视为动态语言的关键,反射机制允许程序在执行期借助与Reflection API取得任何类的内部信息,并能直接操作人意对象的内部属性及方法。
Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
Class
- 在Object类定义了以下方法,此方法被所有子类继承:
public final Class getClass();
- 以上的方法返回值的类型是一个Class类,此类是Java反射的源头。
- 反射可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象,一个Class对象包含了特定某个类的有关信息。
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个类在JVM中只会有一个Class实例
- 一个Class对象对应的是一个记载到JVM中的一个.class文件
- 每个类的实例都会记得自己是由哪个Class实例所生成的。
- 通过Class可以完整地得到一个类中的完整结构
- 常用方法
- 创建Class对象的几种方法
Person person = new Person();
//通过类名.class创建
Class<Person> c0 = Person.class;
//通过类的实例对象创建
Class<? extends Person> c1 = person.getClass();
//通过forName()方法创建,参数是类的全路径:包名 + 类名
Class<?> c2 = Class.forName("day_14.Person");
//通过ClassLoader获取
ClassLoader classLoader = this.getClass().getClassLoader();
Class<?> c3 = classLoader.loadClass("day_14.Person");
通过反射调用类的完整结构
package day_14;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test1 {
public static void main(String[] args) throws Exception{
Class<?> c1 = Class.forName("day_14.Student");
//获取父类
Class<?> superclass = c1.getSuperclass();
System.out.println(superclass);
//获取当前类实现的所有接口
Class<?>[] interfaces = c1.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
//获取所有public类型的构造方法
Constructor<?>[] constructors = c1.getConstructors();
for (Constructor<?> constructor : constructors) {
//获取方法的修饰符(return value: 1 -> public,2 -> private),以及方法名
System.out.println(constructor.getModifiers()+" "+constructor.getName());
//获取构造方法的参数类型
Class<?>[] parameterTypes = constructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getName());
}
}
System.out.println("------------------------------------------");
//获取所有类型的构造的方法,包括private类型的。
Constructor<?>[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor.getModifiers()+" "+declaredConstructor.getName());
//获取构造方法的参数类型
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType.getName());
}
}
System.out.println("------------------------------------------");
//通过反射创建对象
Object object = c1.newInstance();//调用无参构造
Student stu = (Student) object;
//调用有参数的构造方法
Constructor<?> c = c1.getConstructor(String.class);
Student sdu = (Student) c.newInstance("sdu");
System.out.println(sdu.school);
//调用私有的构造方法
Constructor<?> constructor_private = c1.getDeclaredConstructor(String.class,int.class);
constructor_private.setAccessible(true);
Student stu_1 = (Student) constructor_private.newInstance("yyy", 12);
System.out.println("------------------------------------------");
//获取所有public类型的方法,包含父类的方法
Method[] methods = c1.getMethods();
//获取所有方法,包括private类型的方法,不包含父类的方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("method name :"+method.getName()+",return type:"+method.getReturnType()+",Modifier:"+method.getModifiers());
Class<?>[] parameterTypes = method.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("parameter type: "+parameterType.getName());
}
}
System.out.println("------------------------------------------");
//获取public的属性
Field[] fields = c1.getFields();
//获取所有属性,不包括父类
Field[] declaredFields = c1.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName() + " " + field.getModifiers() + " " + field.getType());
}
//获取类所在的包
Package aPackage = c1.getPackage();
System.out.println(aPackage);
// 调用public类型的方法
Method setInfo = c1.getMethod("setInfo", String.class, String.class);
Constructor<?> constructor = c1.getConstructor();
Object o = constructor.newInstance();
setInfo.invoke(o,"yss","sdu");
//调用私有方法
Method test = c1.getDeclaredMethod("test", String.class);
test.setAccessible(true);
test.invoke(o,"yss");
// 调用有返回值的的方法
Method getSchool = c1.getMethod("getSchool");
String school = (String) getSchool.invoke(o);
System.out.println(school);
//设置并获取public类型的属性
Constructor<?> constructor1 = c1.getConstructor();
Student student = (Student) constructor1.newInstance();
Field school1 = c1.getField("school");
school1.set(student,"sdu");
String s = (String) school1.get(student);
System.out.println(s);
//获取私有属性
Field privateField = c1.getDeclaredField("privateField");
privateField.setAccessible(true);
privateField.set(student,"xxx");
String s1 = (String) privateField.get(student);
System.out.println(s1);
}
}
动态代理
- Proxy:专门完成代理的操作类,是所有动态代理类的父类,通过此类为一个或多个接口动态地生成实现类。
- 首先我们创建一个接口:
public interface ITestDemo {
void test1();
void test2();
}
public class TestDemoImpl implements ITestDemo {
@Override
public void test1() {
System.out.println("执行test1()方法");
}
@Override
public void test2() {
System.out.println("执行test2()方法");
}
}
public class ProxyDemo implements InvocationHandler {
//obj为被代理的对象
Object obj;
public ProxyDemo(Object obj)
{
this.obj = obj;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "开始执行!!");
Object result = method.invoke(this.obj, args);
System.out.println(method.getName() + "方法执行完毕");
return result;
}
}
public class Test2 {
public static void main(String[] args) {
ITestDemo testDemo = new TestDemoImpl();
testDemo.test1();
testDemo.test2();
InvocationHandler handler = new ProxyDemo(testDemo);
/*
* parameter 1 : 代理对象的类加载器
* parameter 2 : 被代理的对象的接口
* parameter 3 : 代理对象
* return type: 返回值就是成功被代理后的对象,返回的是Object类型,需要根据当时的情况进行转换
* */
ITestDemo iTestDemo = (ITestDemo) Proxy.newProxyInstance(testDemo.getClass().getClassLoader(), testDemo.getClass().getInterfaces(), handler);
iTestDemo.test1();
iTestDemo.test2();
}
}
- 如果一个对象想要通过Proxy.newProxyIntance方法被代理,那么这个对象的类一定要有相应的接口,就像被类中的ITestDemo接口和实现类TestDemoImpl。
-