记录学习的点滴(Java反射机制)
2017-03-25 22:29
429 查看
Java反射机制
1、定义
在运行状态,对于一个类,能够知道这个类的所有属性和方法。对于一个对象,能够调用它的任意一个属性和方法。
2、作用
.生成动态代理
3、内容
.获取完整的包名类名
.实例化Class对象
.获取父类和接口
.调用类的方法
.调用类的属性
TestReflect.java
TestReflectParent.java
TestReflectImpl.java
操作类的属性的时候,私有属性必须加上field.setAccessible(true),才可以获取私有属性。
TestReflectOther.java
运行结果:
.动态代理
TestReflectProxyImpl.java
运行结果:
GoodMorning-100
优点:
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能
缺点:
(1)使用反射的性能较低
(2)使用反射相对来说不安全
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性 (如上面例子,private属性就可以修改。)
1、定义
在运行状态,对于一个类,能够知道这个类的所有属性和方法。对于一个对象,能够调用它的任意一个属性和方法。
2、作用
.生成动态代理
3、内容
.获取完整的包名类名
.实例化Class对象
.获取父类和接口
.调用类的方法
.调用类的属性
TestReflect.java
package com.test.reflect; public interface TestReflect { void sayHello(); }
TestReflectParent.java
package com.test.reflect; public class TestReflectParent { public void sayHello(){ System.out.println("Hello World."); } }
TestReflectImpl.java
package com.test.reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; public class TestReflectImpl extends TestReflectParent implements TestReflect { public static void main(String[] args) throws Exception { // 获取对象完整的包名和类名 TestReflectImpl reflect = new TestReflectImpl(); String packageName = reflect.getClass().getName(); System.out.println("获取类名包名:" + packageName); // 实例化Class对象 Class<?> clazz1 = null; // 常用的方法 clazz1 = Class.forName("com.test.reflect.TestReflectImpl"); Class<?> clazz2 = null; clazz2 = TestReflectImpl.class; Class<?> clazz3 = null; clazz3 = new TestReflectImpl().getClass(); System.out.println("实例化Class对象方法1:" + clazz1); System.out.println("实例化Class对象方法1:" + clazz2); System.out.println("实例化Class对象方法1:" + clazz3); // 获取对象的父类和接口 Class<?> clazz = Class.forName("com.test.reflect.TestReflectImpl"); Class<?> parentClass = clazz.getSuperclass(); System.out.println("获取对象的父类的名称:" + parentClass.getName()); Class<?> intes[] = clazz.getInterfaces(); for (int i = 0; i < intes.length; i++) { System.out.println("获取对象的接口的名称:" + intes[i].getName()); } // 实例化默认方法 Class<?> clazzUser = Class.forName("com.test.reflect.TestReflectUser"); TestReflectUser user = (TestReflectUser)clazzUser.newInstance(); user.setUserCode("1000"); user.setUserName("abcd"); System.out.println(user); // 调用类的方法 Class<?> clazzMethod1 = Class.forName("com.test.reflect.TestReflectImpl"); Method method1 = clazzMethod1.getMethod("TestReflectMethod1"); method1.invoke(clazzMethod1.newInstance()); Class<?> clazzMethod2 = Class.forName("com.test.reflect.TestReflectImpl"); Method method2 = clazzMethod2.getMethod("TestReflectMethod2", String.class, int.class); method2.invoke(clazzMethod2.newInstance(), "反射机制:方法", 2); // 操作类的属性 Class<?> clazzProperty = Class.forName("com.test.reflect.TestReflectOther"); Object obj = clazzProperty.newInstance(); // 直接对private属性进行操作 Field field = clazzProperty.getDeclaredField("privateProperty"); field.setAccessible(true); field.set(obj, 4000 "属性由私有变为公开。"); Method methodPrivateProperty = clazzProperty.getMethod("printPrivateProperty"); methodPrivateProperty.invoke(obj); } public void TestReflectMethod1(){ System.out.println("反射机制:方法1"); } public void TestReflectMethod2(String string, int i){ System.out.println(string + String.valueOf(i)); } }
操作类的属性的时候,私有属性必须加上field.setAccessible(true),才可以获取私有属性。
TestReflectOther.java
package com.test.reflect; public class TestReflectOther { private String privateProperty = "私有属性。"; public void printPrivateProperty(){ System.out.println(privateProperty); } }
运行结果:
.动态代理
package com.test.reflect; public interface TestReflectProxy { void sayMorning(String param1, String param2, int param3); }
TestReflectProxyImpl.java
package com.test.reflect; public class TestReflectProxyImpl implements TestReflectProxy { @Override public void sayMorning(String param1, String param2, int param3) { System.out.println(param1 + param2 + String.valueOf(param3)); } }
package com.test.reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyInvocationHandler implements InvocationHandler { private Object obj = null; public Object bind(Object paramObj) { this.obj = paramObj; return Proxy.newProxyInstance( paramObj.getClass().getClassLoader(), paramObj.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke(this.obj, args); return temp; } }
// 动态代理 MyInvocationHandler handler = new MyInvocationHandler(); TestReflectProxy proxy = (TestReflectProxy)handler.bind(new TestReflectProxyImpl()); proxy.sayMorning("Good", "Morning-", 100);
运行结果:
GoodMorning-100
优点:
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能
缺点:
(1)使用反射的性能较低
(2)使用反射相对来说不安全
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性 (如上面例子,private属性就可以修改。)
相关文章推荐
- 记录一些平时学习的点滴
- 记录自己学习C++的点滴,(高手请指点) 偶能承受打击
- Windows内核学习点滴记录
- 从今天起,用文字在51cto上记录学习点滴
- Python模块学习 ---- logging 日志记录(一) - 成长的点滴,记录与分享 - 博客频道 - CSDN.NET
- .net学习点滴记录
- C++ 学习拾遗 —— 点滴记录C++学习过程中遇到的问题以及整理
- Mysql学习点滴记录(1)--》数据库和表的操作
- 记录java学习的点滴
- CSDN博客,记录生活学习科研点滴
- JavaScript 学习点滴记录
- 我的新浪博客--记录点滴 Linux 学习过程
- 从今天起开始涉足java的学习,记录学习的点滴
- Mysql学习点滴记录(2)--》数据的操作
- 开博,从今天开始记录IT生活的点滴和学习积累
- MFC OnFileNew OnFileOpen过程分析代码(以记录MFC学习点滴)
- 汇编学习点滴记录
- 记录java学习的点滴
- Python模块学习 ---- fileinput - 成长的点滴,记录与分享 - 博客频道 - CSDN.NET
- fedora 学习点滴记录