记录反射技术的知识点
2013-12-06 13:22
239 查看
反射这个词在平常中我们并不常见,但是对于进阶java技术我们是不的不学习的.
java反射就是将类中的各个成分(构造函数,字段,方法)映射成一一对应的类.
反射的步骤:
1.获取到类的Class对象
2.通过Class对象获取构造函数对象(Constructor),字段对象(Field),方法对象(Method).
3.通过这些类某部分所映射出来的对象,结合某个具体的对象来获取对应对象该部分的值.
注意:
得到的Class对象(字节码)在内存中没个类有且只有一份(类只会加载一次),所以上面会输出两个true.
注:
第一句,首先获取到String对应的Class对象 之后通过getConstructor的方法获取到String类参数列表为StringBuffer的构造函数。
第二句,调用这个构造函数对象中的newInstance来实例化一个Sring对象。
第三句,利用我们刚创建的string对象来获取abc串中中的b
补充:
如果是想通过无参数的构造方法来创建string对象那么有更简便的方法:String.class.newInstance();类直接创建。
为了方便我创建AAA这个类放到com.ydcun包下
注:第二是获取AAA这个类中所有对象的共有的x字段,第三行是制定获取AAA类中具体哪个对象中的x的值。
第四和第五行同样的获取,只不过是获取的私有字段
注:
Constructor、Field、Method都是继承于AccessibleObject,对应实例调用setAccessible(true)就关闭私有保护
获取上述参数的方法有两种,一种是获取声明了的,一种是获取公开的对应的方法:
<Class>.getDeclaredConstructor();
<CLass>.getConstructor();
<Class>.getDeclaredField();
<Class>.getField();
<Class>.getDeclaredMethod();
<Class>.getMethod();
这样好像java安全性就大大降低.如果你非常注重应用的安全性,java当然考虑到这方面,你可以在JVM启动参数增加
-Djava.security.manager 启用安全管理器,如果有该参数,它将检测正在关闭接入检测的代码是否许可了这样做,上述代码执行时会抛出java.security.AccessControlException异常。
这个config.properties配置文件我是直接放到项目的根目录下(eclipse中和src目录同级)
config2.properties 放在com.ydcun包下
上面的反射是很基础的反射的应用。我们可以灵活运用设计出我们想设计的框架。
ydcun厚积薄发:
http://blog.csdn.net/ydcun/
java反射就是将类中的各个成分(构造函数,字段,方法)映射成一一对应的类.
反射的步骤:
1.获取到类的Class对象
2.通过Class对象获取构造函数对象(Constructor),字段对象(Field),方法对象(Method).
3.通过这些类某部分所映射出来的对象,结合某个具体的对象来获取对应对象该部分的值.
1)获取Class的方法用String类为例在(java.lang.String)包中
//获取class方法 Class a1 = Class.forName("java.lang.String"); Class a2 = String.class; Class a3 = new String().getClass(); System.out.println(a1==a2);//true System.out.println(a1==a3);//true
注意:
得到的Class对象(字节码)在内存中没个类有且只有一份(类只会加载一次),所以上面会输出两个true.
2)通过反射获取构造方法以 String(StringBuffer sb);这个构造方法为例
Constructor<String> c = String.class.getConstructor(StringBuffer.class); String sb = c.newInstance(new StringBuffer("abc")); System.out.println(sb.charAt(1));//b
注:
第一句,首先获取到String对应的Class对象 之后通过getConstructor的方法获取到String类参数列表为StringBuffer的构造函数。
第二句,调用这个构造函数对象中的newInstance来实例化一个Sring对象。
第三句,利用我们刚创建的string对象来获取abc串中中的b
补充:
如果是想通过无参数的构造方法来创建string对象那么有更简便的方法:String.class.newInstance();类直接创建。
为了方便我创建AAA这个类放到com.ydcun包下
class AAA{ public int x; private int y; public String s1; public String s2; public String s3; public AAA(){} public AAA(int x, int y) { super(); this.x = x; this.y = y; } public AAA(String s1,String s2,String s3){ this.s1 = s1; this.s2 = s2; this.s3 = s3; } public static void main(String[] args) { for(String s:args){ System.out.println(s); } } }
3)通过反射获取AAA类的字段值
//反射方法获取变量 AAA a11 = new AAA(1,2); Field fx = a11.getClass().getField("x");//获取AAA类所有对象的公共字段的值 System.out.println(fx.get(a11));//1 Field fy = a11.getClass().getDeclaredField("y");//获取私有的字段 fy.setAccessible(true);//强制访问 System.out.println(fy.get(a11));//2
注:第二是获取AAA这个类中所有对象的共有的x字段,第三行是制定获取AAA类中具体哪个对象中的x的值。
第四和第五行同样的获取,只不过是获取的私有字段
4)通过反射修改该类对象中字段中的值
//修改对象中的字段值 AAA al2 = new AAA("ydcun123","hello123","abcde123"); Field[] fs = al2.getClass().getFields(); for(Field f: fs){ //因为是比较获取的这个字段是什么类型,string字节码在内存中有且只有一份 if(f.getType()==String.class){ String oldString = (String) f.get(al2); String newString = oldString.replace('1', 'a'); f.set(al2, newString); } } System.out.println(al2.s1+":"+al2.s2+":"+al2.s3);//ydcuna23:helloa23:abcdea23
5)通过反射获取到类中的方法以String类中的charAt方法为例:
String s2 = new String("abcde"); Method meth = s2.getClass().getMethod("charAt", int.class);//找charAt的方法参数是int型 System.out.println(meth.invoke(s2, 4));//e//第一个参数指定用那个对象执行,要是为null代表这个方法是静态的,第二个就是具体参数
6)调用AAA类中的main方法
String classp = "com.ydcun.AAA";//AAA类的完整路径 Class cp = Class.forName(classp); Method methP = cp.getMethod("main", String[].class); //为了兼容1.4版本中的new Object[]{} 来传递多个参数,他会吧我们要整体传入的参数给拆包 //methP.invoke(null,new Object[]{new String[]{"ydcun","abcdef","ggg"}}); methP.invoke(null, (Object)new String[]{"ydcun","abcdef","ggggg"});
7)数组反射
int[] arr1 = new int[]{1,2,3}; int[] arr2 = new int[4]; int[][] arr3 = new int[2][3]; String[] arr4 = new String[]{"123","abc","mnh","ggg"}; System.out.println(arr1.getClass() == arr2.getClass()); //下面两个直接不行 //System.out.println(arr1.getClass() == arr3.getClass()); //System.out.println(arr1.getClass() == arr3.getClass()); System.out.println(arr1.getClass().getName());//[I 整形的数组 System.out.println(arr1.getClass().getSuperclass().getName());//java.lang.Object System.out.println(arr2.getClass().getName());//[I 整数数组 System.out.println(arr2.getClass().getSuperclass().getName());//java.lang.Object System.out.println(arr3.getClass().getName());//[[I 二维数组int类型 System.out.println(arr3.getClass().getSuperclass().getName());//java.lang.Object System.out.println(arr4.getClass().getName());//[Ljava.lang.String;string类 System.out.println(arr4.getClass().getSuperclass().getName());//java.lang.Object Object aObj1 = arr1; Object aObj2 = arr2; //Object[] aObj3 = arr1; Object[] aObj4 = arr3; Object[] aObj5 = arr4; System.out.println(arr1);//[I@1f33675 System.out.println(arr2);//[I@7c6768 //int[] System.out.println(Arrays.asList(arr1));//[[I@1f33675] System.out.println(Arrays.asList(arr4));//[123, abc, mnh, ggg] Object obj = null; //打印一个对象,可能是对象, printObject(arr1);//1\n2\n3 printObject(arr4);//123\nabc\nmnh\nggg
注:
Constructor、Field、Method都是继承于AccessibleObject,对应实例调用setAccessible(true)就关闭私有保护
获取上述参数的方法有两种,一种是获取声明了的,一种是获取公开的对应的方法:
<Class>.getDeclaredConstructor();
<CLass>.getConstructor();
<Class>.getDeclaredField();
<Class>.getField();
<Class>.getDeclaredMethod();
<Class>.getMethod();
这样好像java安全性就大大降低.如果你非常注重应用的安全性,java当然考虑到这方面,你可以在JVM启动参数增加
-Djava.security.manager 启用安全管理器,如果有该参数,它将检测正在关闭接入检测的代码是否许可了这样做,上述代码执行时会抛出java.security.AccessControlException异常。
8)反射机制大量的应用在框架的使用上。框架的方便是可以调用我们还没有定义的类,还有一些信息是我们通过配置文件来获得,从而提高了框架的灵活性。
下面就说下怎么读取配置文件以properties这个config.properties配置文件我是直接放到项目的根目录下(eclipse中和src目录同级)
config2.properties 放在com.ydcun包下
//读取properties文件 从根目录读取 //InputStream inp = new FileInputStream("config.properties"); //通过类加载器来加载properties文件 在具体的包中 //InputStream inp = test.class.getClassLoader().getResourceAsStream("com/ydcun/config2.properties"); //直接通过class类来获取配置文件路径 相对于test这个类相对路径 //InputStream inp = test.class.getResourceAsStream("config2.properties"); //用绝对 和test类没太大关系 InputStream inp = test.class.getResourceAsStream("/com/ydcun/config2.properties"); Properties pro = new Properties(); pro.load(inp); inp.close();//关闭流 //根据key读取value String v = pro.getProperty("className"); System.out.println(v);
上面的反射是很基础的反射的应用。我们可以灵活运用设计出我们想设计的框架。
ydcun厚积薄发:
http://blog.csdn.net/ydcun/
相关文章推荐
- 添加用户操作历史记录时,纪录用户修改内容用反射技术实现
- Java之反射知识点记录
- 记录知识点或技术方案信息
- Java反射技术一:基本知识点
- Java中反射技术点记录
- 开始记录技术知识
- JDBC 利用反射技术将查询结果封装为对象(简单ORM实现)
- 记录知识点与技巧(一)
- 生产数据迁移EXPDP/IMPDP全过程技术步骤记录(转)
- Android 中利用反射技术实现加减乘除
- (原创)利用扩展方法,给 IEnumerable<T> 增加一个生成 Html 的 select 标签的方法,不用 C# 中的反射技术
- android---利用反射实现的屏幕录制技术
- C++ RTTI及“反射”技术
- 做个记录,一些认识大神的技术博客
- 使用反射技术动态创建类对象(实例代码)
- .Net中通过反射技术的应用----插件程序的开发入门
- JavaWeb学习记录(二)——防盗链技术
- 记录REST分格的web请求服务知识点
- 计算机体系结构几个常用的知识点记录
- Python 学习中,特别知识点记录