Reflection(反射)是指被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息,并直接操作任意对象的内部属性及方法。
框架=反射+注解+设计模式
// 创建一个指定类的对象,classpath:指定类的全类名
public Object getInstance(String classpath) throws Exception {
Class clazz = Class.forName(classpath);
return clazz.newInstance();
}
@Test
public void test2() {
Random random = new Random();
String classpath="";
for (int i = 0; i < 100; i++) {
int number = random.nextInt(3);
switch (number) {
case 0:
classpath = "java.util.Date";
break;
case 1:
classpath = "java.lang.Object";
break;
case 2:
classpath = "com.cn.test.Person";
break;
}
try {
Object obj=getInstance(classpath);
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
》在运行时判断任意一个对象所属的类
》在运行时构造任意一个类的对象
》在运行时判断任意一个类所具有的成员变量和方法
》在运行时获取泛型信息
》在运行时调用任意一个对象的成员变量和方法
》在运行时处理注解
》生成动态代理
java.lang.Class :反射的源头
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor
1.类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。
接着我们使用java.exe 命令 对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,在此过程就称为类的加载。加载到内存中的类,我们称为运行时类,此运行时类,就作为Class 的一个实例。
2.换句话说,Class的实例 对应着 一个运行时类。
3.加载到内存中的运行时类会缓存一定的时间,在此时间之内,我们可以通过不同方式来获取此运行时类。
4.获取Class实例的几种方式:
@Test
public void test3() throws ClassNotFoundException {
//1.调用类.class 属性,获取Class实例
Class class1= Person.class;
System.out.println(class1);
Person p =new Person();
//2.调用getClass(),获取Class实例
Class class2= p.getClass();
System.out.println(class2);
//3.Class.forName,获取Class实例
Class class3 = Class.forName("com.cn.test.Person");
System.out.println(class3);
//4.调用类的加载器getClassLoader(),获取Class实例
ClassLoader classLoader = Reflection1Test.class.getClassLoader();
Class class4= classLoader.loadClass("com.cn.test.Person");
System.out.println(class4);
//System.out.println(class1==class2);
5. 总结:创建类的对象的方式
方式一: new + 构造器
方式二:要创建Xxx类的对象,可以考虑:Xxx/Xxxs 类是否有静态方法存在,可以调用其静态方法,创建Xxx对象。
方式三:通过反射
6.Class实例可以是哪些结构的说明
1)class:外部类,成员(成员内部类,静态内部类)局部内部类,匿名内部类
2)interface:接口
3) []:数组
4)enum:枚举
5)annotation:注解@interface
6)primitive type:基本数据类型
7)void
7.类的加载器,加载配置文件
@Test public void test3() throws IOException { //方式一 Properties pro =new Properties(); FileInputStream fis =new FileInputStream("jdbc.propertities"); pro.load(fis); String name = pro.getProperty("name"); String age = pro.getProperty("age"); System.out.println(name+":"+age); } @Test public void test4() throws IOException { //方式二,该方式文件放在src目录下 ClassLoader classLoader = Reflection2Test.class.getClassLoader(); InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc2.propertities"); Properties pro =new Properties(); pro.load(resourceAsStream); String name = pro.getProperty("name"); String age = pro.getProperty("age"); System.out.println(name+":"+age); }
1.获取所有的属性,方法,构造器
@Test public void test2() { Class clazz = Person.class; //获取运行时类及其所有父类的public方法 Method[] methods = clazz.getMethods(); for (Method m : methods) { System.out.print(m + "\t"); System.out.println(m.getName()); } System.out.println(); //获取运行时类所有方法 Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method m : declaredMethods) { System.out.print(m + "\t"); System.out.println(m.getName()); } } @Test public void test3() { Class clazz = Person.class; //获取运行时类所有public的构造器 Constructor[] constructors = clazz.getConstructors(); for(Constructor c:constructors){ System.out.println(c); } System.out.println(); //获取运行时类所有构造器 Constructor[] constructors2 = clazz.getDeclaredConstructors(); for(Constructor c:constructors2){ System.out.println(c); } } @Test public void test4() throws Exception { //获取当前运行时类父类的对象 Class superclass = Person.class.getSuperclass(); System.out.println(superclass);
}
2.获取指定的属性,方法,构造器
@Test
public void filedTest() throws Exception {
Class clazz=Person.class;
Object obj = clazz.newInstance();
Person per= (Person) obj;
//获取指定属性
Field name = clazz.getDeclaredField("name");
//给指定对象属性复制
name.set(per,"tom");
System.out.println(name.get(per));
//给静态属性赋值,并获取
Field hobbies = clazz.getDeclaredField("hobbies");
hobbies.set(clazz,"baskball");
System.out.println(hobbies.get(clazz));
}
@Test
public void methodTest() throws Exception {
Class clazz=Person.class;
Object obj = clazz.newInstance();
Person per= (Person) obj;
//获取public 无参方法 并调用
Method info = clazz.getDeclaredMethod("info");
info.invoke(per);
//获取public 有参方法 并调用
Method getNation = clazz.getDeclaredMethod("getNation",String.class);
getNation.invoke(per,"china");
//获取静态方法并调用
Method study = clazz.getDeclaredMethod("study");
study.invoke(clazz);
//获取私有方法并调用
Method getAge = clazz.getDeclaredMethod("getAge", int.class);
//设置为可访问
getAge.setAccessible(true);
System.out.println(getAge.invoke(per, 20));
}
@Test
public void ConstructTest() throws Exception {
Class clazz= Person.class;
//该方法为常用用法,具有通用性
Object o = clazz.newInstance();
System.out.println(o);
//获取带有参数的构造器,不常用
Constructor constructor = clazz.getDeclaredConstructor(int.class, String.class);
constructor.setAccessible(true);
Object jerry = constructor.newInstance(15, "jerry");
System.out.println(jerry);
}
七:反射的应用:动态代理
1.静态代理:
interface ColthFactory{ void produceColth(); } //代理类 class ProxyColthFactory implements ColthFactory{ private ColthFactory factory; public ProxyColthFactory(ColthFactory factory){ this.factory=factory; } @Override public void produceColth() { System.out.println("生产衣服之前的准备工作"); factory.produceColth(); System.out.println("生产衣服之后的收尾工作"); } } //被代理类 class NIkeColthFactory implements ColthFactory{ @Override public void produceColth() { System.out.println("NIKE生产衣服"); } } public class StaticProxyTest { public static void main(String[] args) { //创建被代理类对象 NIkeColthFactory nike =new NIkeColthFactory(); //创建代理类对象 ProxyColthFactory proxy =new ProxyColthFactory(nike); //调用方法 proxy.produceColth(); } }
2.动态代理:
class ProxyFactory{ public static Object getInstance(Object obj){ MyInvocationHandler hander= new MyInvocationHandler(); hander.blind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), hander); } } class MyInvocationHandler implements InvocationHandler{ private Object obj; //赋值时必须传被代理类实例 public void blind(Object obj){ this.obj=obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(obj, args);// method为代理类调用的方法,此方法也作为被代理类对象要调用的方法 return invoke; } } public class ProxyTest { public static void main(String[] args) { NIkeColthFactory nike = new NIkeColthFactory(); ColthFactory colthFactory= (ColthFactory) ProxyFactory.getInstance(nike); colthFactory.produceColth(); } }