1.反射概述
- 反射机制是在运行状态中,被视为动态语言的关键
- 对于任意类或对象,都能够获取他们的内部成员
- 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
- 通过class文件对象,去使用该文件中的属性 构造器 方法等一切成员变量
1.1创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| Class file = ReData.class;
Constructor gzq = file.getConstructor(String.class, int.class); Object obj = gzq.newInstance("Haryy", 28); ReData rfd = (ReData)obj; System.out.println(rfd);
Field age = file.getDeclaredField("age");
age.set(rfd,10); System.out.println(rfd);
Method info = file.getDeclaredMethod("info"); info.invoke(rfd);
Method secretInfo = file.getDeclaredMethod("secretInfo", String.class); secretInfo.setAccessible(true); secretInfo.invoke(rfd,"中国人中国魂儿.");
|
1.2反射与封装
正常情况下new对象的方式即可当不确定new哪个对象的时候,就使用反射
一个类若私有了某个成员,说明这个成员是封装写好的直接调用即可
但若需要必须使用反射来进行更改,故反射和封装不存在冲突
1.3类的加载机制
- 程序经过javac.exe后 会生产一或多个.class文件
- 使用java.exe进行对其中某一个解释运行,相当于
- 把某个字节码文件加载到内存中,这个过程就为类的加载机制
- 加载到内存中的类,称为运行时类,此时它就作为Class的一个实例
- Class的实例就对应着一个运行时类
- 加载到内存中的运行时类,会缓存一定时间
- 此时就可以通过不同方式来获取此运行时类
1.4四种创建方式
方式一 调用运行时类的属性.class
1 2
| Class c1 = ReData.class; System.out.println(c1);
|
方式二 通过运行时类对象,调用getClass()
1 2 3
| ReData reData = new ReData(); Class<? extends ReData> c2 = reData.getClass(); System.out.println(c2);
|
方式三 使用Class类的forName()
1 2 3 4 5
| Class<?> c3 = Class.forName("ReData"); System.out.println(c3);
System.out.println(c1 == c2); System.out.println(c1 == c3);
|
方式四 使用类的加载器
1 2 3 4
| ClassLoader cloader = 此类类名称.class.getClassLoader(); Class<?> c4 = cloader.loadClass("ReData"); System.out.println("系统加载器"+cloader); System.out.println(c1 == c4);
|
1.5动态性理解
- 有时候我们造对象是不确定的
- 此时就可以通过反射的动态性在运行时候可以根据某些条件改变自身结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public void DyTest() throws Exception { for (int i = 0 ;i<100;i++) { int num = new Random().nextInt(3); String locate = ""; switch (num){ case 0: locate ="java.util.Date"; break; case 1: locate ="java.lang.Object"; break; case 2: locate ="Test.Calculator"; break; } Object obj = getInstance(locate); System.out.println(obj); } }
public Object getInstance(String classpath) throws Exception{ Class<?> cls = Class.forName(classpath); return cls.newInstance(); }
|
2.成员获取
2.1构造器
1 2 3 4 5 6 7 8 9 10 11 12
| Class clz = ReData.class;
Constructor[] cons = clz.getConstructors(); for (Constructor constructor : cons){ System.out.println(constructor); }
Constructor[] dcs = clz.getDeclaredConstructors(); for (Constructor constructor1 : dcs){ System.out.println(constructor1); }
|
2.2属性方法
属性
1 2 3 4 5 6 7 8 9 10 11
| Class<ReData> dt = ReData.class; Field[] fields = dt.getFields(); for (Field f : fields){ System.out.println(f); }
Field[] dfs = dt.getDeclaredFields(); for (Field f1 : dfs){ System.out.println(f1); }
|
方法
1 2 3 4 5 6 7 8 9 10 11 12
| Class ct = ReData.class; Method[] methods = ct.getMethods(); for (Method m : methods){ System.out.println(m); }
Method[] methods1 = ct.getDeclaredMethods(); for (Method m1 : methods1){ System.out.println(m1); }
|
2.3接口泛型(重点)
1.获取运行时类的父类
1 2 3 4 5 6 7
| Class clz = ReData.class; Class scs = clz.getSuperclass(); System.out.println(scs);
Type gsc = clz.getGenericSuperclass(); System.out.println(gsc);
|
2.获取运行时类带泛型的父类的泛型
1 2 3 4 5
| ParameterizedType paramType = (ParameterizedType)gsc; Type[] type = paramType.getActualTypeArguments(); System.out.println(type[0].getTypeName());
System.out.println(((Class)type[0]).getName());
|
3.获取运行时类的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void InterfaceTest() throws Exception{ Class clz = Class.forName("re_basic.ReData"); Class[] interfaces = clz.getInterfaces(); System.out.println(interfaces[0].getName());
Type[] gifs = clz.getGenericInterfaces(); System.out.println(gifs[0].getTypeName());
Class[] fathers = clz.getSuperclass().getInterfaces(); for (Class c : fathers){ System.out.println(c); } }
|
2.4动态代理
- 动态代理是在程序运行时根据需要动态的去创建目标类的代理对象
- 主要用于调试,远程方法调用
- 相对于静态代理,抽象类或接口中所声明的方法,都被转移到调用处理器一个集中的方法进行处理,可以更灵活的管理多个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class DynimProxy { public static void main(String[] args) { SuperMan superMan = new SuperMan(); Human human = (Human)ProxyFactory.getProxyInstance(superMan); System.out.println(human.getBelief()); human.eat("美国M9牛排"); } }
interface Human{ String getBelief(); void eat(String food); }
class SuperMan implements Human{
@Override public String getBelief() { return "相信世界"; }
@Override public void eat(String food) { System.out.println("我喜欢吃"+food); } }
class ProxyFactory{ public static Object getProxyInstance(Object obj){ MyIHR ihr = new MyIHR(); ihr.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), ihr); } } class MyIHR implements InvocationHandler{ private Object obj; public void bind(Object obj){ this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = method.invoke(obj, args); return returnValue; } }
|