为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

java反射机制

2017-09-20 13页 doc 33KB 12阅读

用户头像

is_624976

暂无简介

举报
java反射机制java反射机制 忙里偷闲,做了一些反射机制中的测试。。。。 问题一: 即使在非并发的情况下,单例模式能保证单例么, 先来一个最简单的单例模式: Java代码 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; } } public clas...
java反射机制
java反射机制 忙里偷闲,做了一些反射机制中的测试。。。。 问题一: 即使在非并发的情况下,单例模式能保证单例么, 先来一个最简单的单例模式: Java代码 public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; } } public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; } } 测试类: Java代码 import java.lang.reflect.Constructor; public class TestSingleton { public static void main(String[] args) { try { Constructor con = Class.forName(Singleton.class.getName()).getDeclaredConstructor(); con.setAccessible(true); Singleton single1 = (Singleton)con.newInstance(); Singleton single2 = (Singleton)con.newInstance(); System.out.println("single1.equals(single2):"+single1.equals(single2)); } catch (Exception e) { e.printStackTrace(); } } } import java.lang.reflect.Constructor; public class TestSingleton { public static void main(String[] args) { try { Constructor con = Class.forName(Singleton.class.getName()).getDeclaredConstructor(); con.setAccessible(true); Singleton single1 = (Singleton)con.newInstance(); Singleton single2 = (Singleton)con.newInstance(); System.out.println("single1.equals(single2):"+single1.equals(single2)); } catch (Exception e) { e.printStackTrace(); } } } 结果: Java代码 single1.equals(single2):false single1.equals(single2):false 结论:在反射的情况下,单例模式失效,这是因为通过反射可以获取私有属性,通过调用相应的setAccessible()方法,可以使private属性失效。那么如何能保证的确只能有一个实例呢,在我认为,如果某一程序故意通过反射来绕过单例的限制,则它要么是恶意程序,要么是一个逻辑错误,可以直接抛runtimeException,来让程序终止,否则一旦生成多个实例,后果是不可控的。个人改进如下: Java代码 public class Singleton { private static Singleton instance = new Singleton(); private static boolean flag = true; private Singleton() { if(flag){ //other code here..... flag = !flag; return; }else{ throw new RuntimeException("dulpicated instance of "+ Singleton.class.getName()); } } public static Singleton getInstance(){ return instance; } } public class Singleton { private static Singleton instance = new Singleton(); private static boolean flag = true; private Singleton() { if(flag){ //other code here..... flag = !flag; return; }else{ throw new RuntimeException("dulpicated instance of "+ Singleton.class.getName()); } } public static Singleton getInstance(){ return instance; } } 再次运行test程序,结果如下: Java代码 Exception in thread "main" java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at test1.TestSingleton.main(TestSingleton.java:8) Caused by: java.lang.RuntimeException: dulpicated instance of test1.Singleton at test1.Singleton.(Singleton.java:13) at test1.Singleton.(Singleton.java:5) ... 3 more Exception in thread "main" java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at test1.TestSingleton.main(TestSingleton.java:8) Caused by: java.lang.RuntimeException: dulpicated instance of test1.Singleton at test1.Singleton.(Singleton.java:13) at test1.Singleton.(Singleton.java:5) ... 3 more 这样就可以保证只有一个实例,当然如果有更好的,欢迎提出,,, 问题二:在反射时,如果我直接调用私有方法,会出现什么情况, 代码: Java代码 public class Reflection { private void test(){ System.out.println("test1 private private method"); } public void test2(){ System.out.println("test2 public sssssssssssssss"); } public static void test3(){ System.out.println("test333333 sttic sssssssssssssss"); } } 测试代码一: public class TestReflection { public static void main(String[] args) { try { Class clazz = Class.forName(Reflection.class.getName()); Method m = clazz.getDeclaredMethod("test"); Reflection ref = new Reflection(); m.invoke(ref); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class Reflection { private void test(){ System.out.println("test1 private private method"); } public void test2(){ System.out.println("test2 public sssssssssssssss"); } public static void test3(){ System.out.println("test333333 sttic sssssssssssssss"); } } 测试代码一: public class TestReflection { public static void main(String[] args) { try { Class clazz = Class.forName(Reflection.class.getName()); Method m = clazz.getDeclaredMethod("test"); Reflection ref = new Reflection(); m.invoke(ref); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 测试结果: Java代码 [java.lang.IllegalAccessException: Class test1.TestReflection can not access a member of class test1.Reflection with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:588) at test1.TestReflection.main(TestReflection.java:13) [java.lang.IllegalAccessException: Class test1.TestReflection can not access a member of class test1.Reflection with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:588) at test1.TestReflection.main(TestReflection.java:13) 改进后的测试代码: 在执行m.invoke(ref)之前先调用 m.setAccessible(true), 即 Java代码 m.setAccessible(true); m.invoke(ref); m.setAccessible(true); m.invoke(ref); 问题三: 如果方法中有两个重载方法,分别为test(int a), test(Integer a),如何通过反 射调用相应的test方法, 代码: Java代码 public class Reflection { public void test(int a){ System.out.println(a+"int parameter method"); } public void test(Integer a){ System.out.println(a+"Integer parameter method"); } } public class Reflection { public void test(int a){ System.out.println(a+"int parameter method"); } public void test(Integer a){ System.out.println(a+"Integer parameter method"); } } 实现代码: Java代码 import java.lang.reflect.Method; public class TestReflection { public static void main(String[] args) { try { Class clazz = Class.forName(Reflection.class.getName()); Method m1 = clazz.getDeclaredMethod("test",Integer.class); Method m2 = clazz.getDeclaredMethod("test",int.class); System.out.println(int.class); System.out.println(Integer.class); Reflection ref = new Reflection(); Integer in = Integer.valueOf(3); m1.invoke(ref,1); m1.invoke(ref,in); m2.invoke(ref,1); m2.invoke(ref,in); ref.test(1); ref.test(in); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } import java.lang.reflect.Method; public class TestReflection { public static void main(String[] args) { try { Class clazz = Class.forName(Reflection.class.getName()); Method m1 = clazz.getDeclaredMethod("test",Integer.class); Method m2 = clazz.getDeclaredMethod("test",int.class); System.out.println(int.class); System.out.println(Integer.class); Reflection ref = new Reflection(); Integer in = Integer.valueOf(3); m1.invoke(ref,1); m1.invoke(ref,in); m2.invoke(ref,1); m2.invoke(ref,in); ref.test(1); ref.test(in); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 结果输出: Java代码 int class java.lang.Integer 1Integer parameter method 3Integer parameter method 1int parameter method 3int parameter method 1int parameter method 3Integer parameter method int class java.lang.Integer 1Integer parameter method 3Integer parameter method 1int parameter method 3int parameter method 1int parameter method 3Integer parameter method 结论一:int 和Integer对象是可以自动转换的,但是在反射情况下,作为参数时二者是不同的类型的。 结论二:在test(int i)和test(Integer in)同时存在的情况下,如果调用的是方法中是Integer对象,则不进行自动拆包转换,而是直接调用test(Integer in)方法,否则自动拆包调用test(int i)方法。即: Java代码 Integer in = Integer.valueOf(2); ref.test(in)//调用的是test(Integer in),如果此方法不存在则调用test(int i). Integer in = Integer.valueOf(2); ref.test(in)//调用的是test(Integer in),如果此方法不存在则调用test(int i). 以上是对反射做的一些学习,如果有不对的地方,欢迎大家指点拍砖,,
/
本文档为【java反射机制】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索