Java反射机制
2015-07-16 20:36
736 查看
Class类与java.lang.reflect类库一起对反射的概念进行了支持,该类包括FIeld、Method以及Constructor类。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。这样你就可以使用Constructor创建新的对象,用set()和get()方法访问和修改Field对象关联的字段,用invoke()方法调用与Method对象相关联的方法。
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
Java 反射机制主要提供了以下功能:
在运行时判断一个对象的所属类型;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法(包括私有的);
在运行时调用任意一个类生成的对象的方法。
Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
Class类:代表一个类;
Field 类:代表类的成员变量(成员变量也称为类的属性);
Method类:代表类的方法;
Constructor 类:代表类的构造方法
在刚刚学jdbc时用过一行代码,Class.forName(“com.mysql.jdbc.Driver.class”),表示加载驱动的Class对象。下面的例子,使用相同的方法生成Class对象,在运行时,获得类的信息。
要想使用反射,首先需要获得待操作的类所对应的Class对象。Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象。这个Class对象是由JVM生成的,通过它能够获悉整个类的结构。
常用的获取Class对象的3种方式
1、使用Class类的静态方法。 例如:Class<?> classType=Class.forName(“java.lang.String”);
2、使用.class语法。例如:Class<?> classType=String.class;
3、使用对象的getClass()来调用。Object obj = new Object();Class<?> classType=obj.getClass().
Java反射机制也可以在运行时调用任意一个类生成的对象的方法。例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法
如下例程ReflectTester类进一步演示了Reflection API的基本使用方法。
ReflectTester类有一个copy(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回。这个例子只能复制简单的类,假定类的每个属性都有public类型的getXXX()和setXXX()方法。
/**使用类的带参的构造器生成对象
**可以看出此时是不带参数的,相当于 calssType.newInstance();
*/
Object objectCopy = calssType.getConstructor(new Class[]{}).newInstance(new Object[]{});
利用反射,首先是Class对象的获取,之后是Method和Field对象的获取。
以Method为例,从文档中可以看到:getMethod()方法返回的是public的Method对象,而getDeclaredMethod()返回的Method对象可以是非public的。Field的方法同理。
访问私有属性和方法,在使用前要通过AccessibleObject类(Constructor、Field和Method类的基类)中的setAccessible()方法来抑制Java访问权限的检查。
实例1,调用私有方法:
实例2,访问私有属性
反射机制的优点与缺点?
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
用反射机制能干什么事?
刚开始在使用jdbc时侯,在编写访问数据库时写到想吐,有八个表,每个表都有增删改查中操作 那时候还不知道有反射机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率地,而且代码冗余的厉害,最要命的是看着差不多的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一个或少一个字母啊……),一个错误就可以让你找半天。有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,就OK啦,无需为每一个表都创建dao类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。说白了,反射机制就是专门帮我们做那些重复的有规则的事情,所以现在很多的自动生成代码的软件就是运用反射机制来完成的,只要你按照规则 输入相关的参数,所以低级的程序员慢慢的就被抹杀了,为什么?因为代码都不用写了,随便一个人都会开发,还要程序员干什么啊?所以我们只有一条出路,那就是努力努力再努力,成为高级程序员,专门开发傻瓜软件,让其他程序员 到 一边凉快去,呵呵~
参考来源:
圣思园张龙老师反射教学视频;
Java反射机制
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。
Java 反射机制主要提供了以下功能:
在运行时判断一个对象的所属类型;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法(包括私有的);
在运行时调用任意一个类生成的对象的方法。
Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
Class类:代表一个类;
Field 类:代表类的成员变量(成员变量也称为类的属性);
Method类:代表类的方法;
Constructor 类:代表类的构造方法
在刚刚学jdbc时用过一行代码,Class.forName(“com.mysql.jdbc.Driver.class”),表示加载驱动的Class对象。下面的例子,使用相同的方法生成Class对象,在运行时,获得类的信息。
[code]import java.lang.reflect.Method; public class DumpMethods { //从命令行接受一个字符串(该字符串是某个类的全名) //打印该类中的所有方法申明,包括私有的 public static void main(String[] args) throws ClassNotFoundException { //Class类是java反射的入口 Class <?> classType = Class.forName("java.lang.String"); Method [] methods = classType.getDeclaredMethods(); for(Method method :methods){ System.out.println(method); } } } /* *在运行时获得一个类的类型信息,在本例中传入参数“java.lang.String”在编译器是无法知道该类的一些类型信息的 *input : java.lang.String *output:public boolean java.lang.String.equals(java.lang.Object) public boolean java.lang.String.equals(java.lang.Object) public int java.lang.String.hashCode() public int java.lang.String.compareTo(java.lang.Object) . . . */
要想使用反射,首先需要获得待操作的类所对应的Class对象。Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象。这个Class对象是由JVM生成的,通过它能够获悉整个类的结构。
常用的获取Class对象的3种方式
1、使用Class类的静态方法。 例如:Class<?> classType=Class.forName(“java.lang.String”);
2、使用.class语法。例如:Class<?> classType=String.class;
3、使用对象的getClass()来调用。Object obj = new Object();Class<?> classType=obj.getClass().
Java反射机制也可以在运行时调用任意一个类生成的对象的方法。例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法
[code]import java.lang.reflect.Method; public class InvokeTester { public int add(int param1,int param2){ return param1+param2; } public String echo(String msg){ return msg; } public static void main(String[] args) throws Exception { //获得InvokeTester类所对应的Class对象 Class<?> classType = InvokeTester.class; //创建此 Class 对象所表示的类的一个实例,只会去调用其无参构造函数。 Object invokeTester = classType.newInstance(); //返回一个 某个Method 对象 Method addMethod = classType.getMethod("add", new Class[]{int.class,int.class}); //对带有指定参数的指定对象调用由此 Method 对象表示的底层方法 Object result=addMethod.invoke(invokeTester, new Object[]{100,200}); //返回某个Method 对象 Method echo = classType.getMethod("echo", new Class[]{String.class}); //对带有指定参数的指定对象调用由此Method 对象表示的底层方法 Object res = echo.invoke(invokeTester,new Object[]{"Hello reflection"}); System.out.println((Integer)result); System.out.println((String)res); } }
如下例程ReflectTester类进一步演示了Reflection API的基本使用方法。
ReflectTester类有一个copy(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回。这个例子只能复制简单的类,假定类的每个属性都有public类型的getXXX()和setXXX()方法。
/**使用类的带参的构造器生成对象
**可以看出此时是不带参数的,相当于 calssType.newInstance();
*/
Object objectCopy = calssType.getConstructor(new Class[]{}).newInstance(new Object[]{});
[code]import java.lang.reflect.Field; import java.lang.reflect.Method; class Customer{ public Customer(){ } public int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } private Long id; public Long getId() { return id; } public void setId(Long id) { this.id = id; } } public class ReflectTester { public Object copy(Object object) throws Exception{ Class<?> calssType = object.getClass(); Object objectCopy = calssType.getConstructor(new Class[]{}).newInstance(new Object[]{}); //获得该class对象代表的申明字段,包括私有的 Field[] fields = calssType.getDeclaredFields(); for(Field field:fields){ String fieldFirstCharter = field.getName().substring(0,1).toUpperCase(); String fileName = fieldFirstCharter + field.getName().substring(1); String setMethodName = "set"+fileName; String getMethodName = "get"+fileName; System.out.println("setMethodName:"+setMethodName+" getMethodName:"+getMethodName); Method setMethod = calssType.getMethod(setMethodName, new Class[]{field.getType()}); Method getMethod = calssType.getMethod(getMethodName, new Class[]{}); Object value = getMethod.invoke(object, new Object[]{}); setMethod.invoke(objectCopy,new Object[]{value}); } return objectCopy; } public static void main(String[] args) throws Exception { Customer object = new Customer (); object.setAge(19); object.setId(new Long(100000)); object.setName("zhangshan"); Customer objectCopy = (Customer)new ReflectTester().copy(object); System.out.println(objectCopy.getAge()); System.out.println(objectCopy.getId()); System.out.println(objectCopy.getName()); } }
利用反射,首先是Class对象的获取,之后是Method和Field对象的获取。
以Method为例,从文档中可以看到:getMethod()方法返回的是public的Method对象,而getDeclaredMethod()返回的Method对象可以是非public的。Field的方法同理。
访问私有属性和方法,在使用前要通过AccessibleObject类(Constructor、Field和Method类的基类)中的setAccessible()方法来抑制Java访问权限的检查。
实例1,调用私有方法:
[code]public class PrivateClass { private String sayHello(String name){ return "Hello: " + name; } }
[code]import java.lang.reflect.Method; public class TestPrivate { public static void main(String[] args) throws Exception { PrivateClass privateClass = new PrivateClass(); Class<?> classType = privateClass.getClass(); Method method =classType.getDeclaredMethod("sayHello", new Class[]{String.class}); // 抑制Java的访问控制检查,否则,将会Error: TestPrivate can not access a member of class PrivateClass with modifiers "private" method.setAccessible(true); Object result = method.invoke(privateClass, new Object[]{"everyone!"}); System.out.println((String)result); } }
实例2,访问私有属性
[code]public class PrivateClass2 { private String name = "Hello everyone!"; public String getName() { return name; } }
[code]import java.lang.reflect.Field; public class TestPrivate2 { public static void main(String[] args) throws Exception { PrivateClass2 privateClass2 = new PrivateClass2(); Class<?>classType = privateClass2.getClass(); Field field = classType.getDeclaredField("name"); field.setAccessible(true); field.set(privateClass2, "Hello: everyone!"); System.out.println(privateClass2.getName()); } }
反射机制的优点与缺点?
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
用反射机制能干什么事?
刚开始在使用jdbc时侯,在编写访问数据库时写到想吐,有八个表,每个表都有增删改查中操作 那时候还不知道有反射机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率地,而且代码冗余的厉害,最要命的是看着差不多的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一个或少一个字母啊……),一个错误就可以让你找半天。有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,就OK啦,无需为每一个表都创建dao类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。说白了,反射机制就是专门帮我们做那些重复的有规则的事情,所以现在很多的自动生成代码的软件就是运用反射机制来完成的,只要你按照规则 输入相关的参数,所以低级的程序员慢慢的就被抹杀了,为什么?因为代码都不用写了,随便一个人都会开发,还要程序员干什么啊?所以我们只有一条出路,那就是努力努力再努力,成为高级程序员,专门开发傻瓜软件,让其他程序员 到 一边凉快去,呵呵~
参考来源:
圣思园张龙老师反射教学视频;
Java反射机制
相关文章推荐
- Spring基础---Spring源码解析以及入门
- Netbeans配合xdebug调试
- Java IO中的设计模式--装饰器和适配器模式
- LeetCode201 Bitwise AND of Numbers Range Java 题解
- 使用Java IO 流进行文件的复制,复制成功,却打不开复制的文件
- 算法学习之一java实现冒泡排序
- java的构造器和void方法的区别
- 彻底理解JAVA动态代理
- JAVA经典实例
- java小练习
- NGUI--SpringPanel总结
- 如何在Myeclipse中添加插件?
- eclipse最有用快捷键整理_quick code
- SpringMVC——接收请求参数和页面传参
- java学习&复习 2015/07/16
- JVM系列文章(五):Javac编译与JIT编译
- java内部类
- Java基础unit2
- 深入学习JAVA虚拟机笔记
- bj java初学2015-7-16