java反射机制
2015-07-09 09:52
453 查看
1、什么是反射机制
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定完整的类名(包名+类名)、或根据类的一个对象的引用,就可以通过反射机制来获得类的所有信息。反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的。
2、哪里用到反射机制
有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行码Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成 驱动对象实例,并不知道它的具体含义。学了反射机制,才知道,原来这就是反射,现在很多开 框架都用到反射机制,hibernate、struts都是用反射机制实现的。
反射应用场景:
简单地说就是你想new一个对象,调一个方法,但是你还不确定要new哪个对象,调哪个方法,要程序跑起来再看情况而定,你就不能提前在程序里写好常规的方法代码。
例:1、当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢?因为程序是支持插件的(第三方的),在开发的时候并不知道
。所以,无法在代码中New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。反射的目的就是为了扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。
2、在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。
3、我需要加载一个类,但是此类的class文件不在类路径上,需要从其他地方获取,如网络或者其他文件,这个时候就需要自定义类加载器,以定制的方式把类的全限定名转换成一个Java class文件格式的字节数组,加载出来要访问该对象的方法怎么办,就通过加载得到的Class对象通过反射来访问了,这种情况下普通程序无法完成.
3、反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。 1,丧失了编译时类型检查的好处 2,执行反射访问所需代码笨拙冗长 3,性能损失
对于特定的复杂的系统编程任务,反射很有必要,如果编写的程序必须要与编译时未知的类一起工作,就可以用反射仅仅来实例化对象,但不应该通过反射来访问对象,应该通过被实例化对象的接口或者父类来访问对象的方法,这就是接口优先于反射机制的含义。
3.1、实现Java反射的类
1)Class:它表示正在运行的Java应用程序中的类和接口
2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
4)Method:提供关于类或接口中某个方法信息
注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现
4、反射的前传:类类型 Class Class
1、Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
2、Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 很多解释说Class类没有构造器,其实是有的,只不过它的构造方法是private的。
3、虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
4、基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
5、每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
6、 一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
简记:Class类是封装类型信息的类,每个类都有一个Class对象,每个java类运行时都在JVM里表现为一个class对象,当装载类时,Class类型的对象自动创建。某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
4、1程序中如何得到一个类的类型信息(即该类对应的Class对象)?
有三种方法可以的获取:
1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:
MyObject x;
Class c1 = x.getClass();
2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如:
Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class(类字面常量)就代表了匹配的类对象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
注意:Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。当装载类时,Class类型的对象自动创建。某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
4、2 获取反射类的实例
Class类中有一个方法叫做newInstance(),它可以用来创建一个Class类对象的新实例。Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象),
4.2.1 Class类的无参构造对象
这样就通过无参数的形式构造了一个新的对象,如同正常模式中,通过无参构造方法来构造新对象一样。缺点是我们只能利用默认构造函数,因为Class的newInstance是不接受参数的。我们知道,类中除了有无参构造方法,还会存在有参数的构造方法。
4.2.2 Class类的有参构造对象
注:无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在,也就是使用Class类的newInstance()无参构造对象时,原类一定要有对应无参构造函数。
4、3 获取类的构造器
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
1.public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
2.public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
3.public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
4.public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器
从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有
解释一下:第一个是获得一个指定的方法,我们指定了参数是一个String类型,第二段我们获得了所有的构造方法集合,并选取了其中一个创建了新的对象。
注意,以上的四个方法全部需要抛出异常,当我们获得私有的方法的时候,要用setAccessible设置一下可访问的权限,例子中没有演示获取共有方法,那个比较简单,就不做介绍了,其实掌握了上面两个,其他就好理解了。
4、5 获取类的成员变量
了解了构造器,其实你可以猜到成员变量的获取方法了,成员变量用Field类进行封装。
主要的方法非常的类似:
1.public Field getDeclaredField(String name) 获取任意指定名字的成员
2.public Field[] getDeclaredFields() 获取所有的成员变量
3.public Field getField(String name) 获取任意public成员变量
4.public Field[] getFields() 获取所有的public成员变量
可以看出这些方法都是异曲同工的,好了直接看一下例子吧
4、6 获取类的方法
封装类的方法的类是Method.获取method也有四个方法
1.public Method[] getMethods() 获取所有的共有方法的集合
2.public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合
3.public Method[] getDeclaredMethods() 获取所有的方法
4.public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
//反射调用方法,可以通过Method类的invoke方法实现动态方法的调用
//public Object invoke(Object obj, Object... args)
//第一个参数代表对象
//第二个参数代表执行方法上的参数
//若反射要调用类的某个私有方法,可以在这个私有方法对应的Mehtod对象上先 调用setAccessible(true)
class类的其它方法:
取得类所实现的接口 getInterfaces()
取得父类 getSuperclass()
返回该类的类加载器 getClassLoader()
返回表示数组组件类型的 Class getComponentType()
判定此 Class 对象是否表示一个数组类 isArray()
5、java反射机制可以调用到私有方法,是不是就破坏了JAVA的卦装性呢。
这是一个很值得探讨的问题,许多人接触反射时,对反射功能之强大都会抱有怀疑,感觉严重破坏了封装的性质。可是,什么是封装,什么是安全呢?
封装,是将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,也就是说,公有方法能够完成类所具有的功能。当别人使用这个类时,如果通过反射直接调用私有方法,可能根本实现不了类的功能,甚至可能会出错,因此通过反射调用私有方法可以说是没有任何用处的,开发人员没有必要故意去破坏封装好的类。从这点上看,封装性并没有被破坏。
所谓安全,如果意思是保护实现源码不被别人看见,那没有作用。不用反射也能轻易获取源码。
所以我以为反射机制只是提供了一种强大的功能,使得开发者能在封装之外,按照特定的需要实现一些功能。就好比核技术,虽然造核弹很危险吧,但造核电站还是很有用处的(这个比喻似乎不是很恰当,将就将就)。
Java语言是一个严谨的编程语言,语言本身是静态的。为了能让语言具有动态编程的特性,必须要有反射机制。而反射机制本身就是底层的处理,不可能按表层的封转特性来处理。也就是说不给调用私有方法的能力,很多程序受到局限,那么实现起来就麻烦了。
以上说的,有肯能你没明白。举一个生活的例子,你家的电视机是要由外壳的,目的是不让普通人接触到电视中的电路。那么Java语言的基本面向对象特征正是这个层次的应用。也就是对于普通程序员的程序,是通过遥控器来操作电视的。但是,如果你是一个专业的电工的话,那么可以打开电视机的后盖,调整电视中的电路和结构,甚至如果是电工的话,那么调台可能都不使用遥控器,而是通过调整内部电路的电阻的阻值来实现。Java中的反射机制正是提供更高要求的编程来使用的,不需要考虑基本面向对象的特征,而是要考虑能否得到和控制代码中的一切,这样反射机制编程才有意义。
来源:点击打开链接
6、用反射机制能干什么事
刚开始在使用jdbc时侯,在编写访问数据库时写到想吐,有八个表,每个表都有增删改查中操作 那时候还不知道有反射机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率地,而且代码冗余的厉害,最要命的是看着差不多的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一 个或少一个字母啊……),一个错误就可以让你找半天。 有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,就OK啦,无需为每一个表都创建dao类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。说白了,反射机制就是专门帮我们做那些重复的有规则的事情,所以现在很多的自动生成代码的软件就是运用反射机制来完成的,只要你按照规则 输入相关的参数.
参考来源:
深入研究java.lang.Class类
java反射机制初探
java中的反射总结
Java反射机制
简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定完整的类名(包名+类名)、或根据类的一个对象的引用,就可以通过反射机制来获得类的所有信息。反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的。
2、哪里用到反射机制
有些时候,我们用过一些知识,但是并不知道它的专业术语是什么,在刚刚学jdbc时用过一行码Class.forName("com.mysql.jdbc.Driver.class").newInstance();但是那时候只知道那行代码是生成 驱动对象实例,并不知道它的具体含义。学了反射机制,才知道,原来这就是反射,现在很多开 框架都用到反射机制,hibernate、struts都是用反射机制实现的。
反射应用场景:
简单地说就是你想new一个对象,调一个方法,但是你还不确定要new哪个对象,调哪个方法,要程序跑起来再看情况而定,你就不能提前在程序里写好常规的方法代码。
例:1、当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢?因为程序是支持插件的(第三方的),在开发的时候并不知道
。所以,无法在代码中New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。反射的目的就是为了扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。
2、在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。
3、我需要加载一个类,但是此类的class文件不在类路径上,需要从其他地方获取,如网络或者其他文件,这个时候就需要自定义类加载器,以定制的方式把类的全限定名转换成一个Java class文件格式的字节数组,加载出来要访问该对象的方法怎么办,就通过加载得到的Class对象通过反射来访问了,这种情况下普通程序无法完成.
3、反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。 1,丧失了编译时类型检查的好处 2,执行反射访问所需代码笨拙冗长 3,性能损失
对于特定的复杂的系统编程任务,反射很有必要,如果编写的程序必须要与编译时未知的类一起工作,就可以用反射仅仅来实例化对象,但不应该通过反射来访问对象,应该通过被实例化对象的接口或者父类来访问对象的方法,这就是接口优先于反射机制的含义。
3.1、实现Java反射的类
1)Class:它表示正在运行的Java应用程序中的类和接口
2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限
3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限
4)Method:提供关于类或接口中某个方法信息
注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现
4、反射的前传:类类型 Class Class
1、Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
2、Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 很多解释说Class类没有构造器,其实是有的,只不过它的构造方法是private的。
3、虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
4、基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
5、每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
6、 一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
简记:Class类是封装类型信息的类,每个类都有一个Class对象,每个java类运行时都在JVM里表现为一个class对象,当装载类时,Class类型的对象自动创建。某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
4、1程序中如何得到一个类的类型信息(即该类对应的Class对象)?
有三种方法可以的获取:
1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如:
MyObject x;
Class c1 = x.getClass();
2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如:
Class c2=Class.forName("MyObject"),Employee必须是接口或者类的名字。
3、获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class(类字面常量)就代表了匹配的类对象。例如
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
Class类的实例化: class Test { } public class Demo { public static void main(String[] args) { //方式一: Test t = new Test(); Class<? extends Test> c1 = t.getClass(); System.out.println(c1); //方式二: //为了避免特殊性,这里不用Test类,而用java库中的String类 Class<String> c2 = String.class; System.out.println(c2); //方式三: //forName()方法会抛出异常 Class<?> c3 = null; try { c3 = Class.forName("Test"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(c3); } }没有对象实例的时候,forName( )方法、类字面常量,可以在类不确定的情况下实例化Class,更具灵活性
注意:Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。当装载类时,Class类型的对象自动创建。某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
4、2 获取反射类的实例
Class类中有一个方法叫做newInstance(),它可以用来创建一个Class类对象的新实例。Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象),
4.2.1 Class类的无参构造对象
public class Demo { public static void main(String[] args) { //实例化Class对象,forName()方法会抛异常 Class<?> c = null; try { //这里需要完整的包名和类名 c = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //生成一个字符串的引用 String s = null; try { //将构造好的对象向下转型为String类 //newInstance()方法会抛异常 s = (String) c.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } System.out.println("字符串长度: " + s.length()); } }
这样就通过无参数的形式构造了一个新的对象,如同正常模式中,通过无参构造方法来构造新对象一样。缺点是我们只能利用默认构造函数,因为Class的newInstance是不接受参数的。我们知道,类中除了有无参构造方法,还会存在有参数的构造方法。
4.2.2 Class类的有参构造对象
import java.lang.reflect.Constructor; public class Demo { //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了 public static void main(String[] args) throws Exception { Class<?> c = null; try { c = Class.forName("java.lang.String"); } catch (ClassNotFoundException e) { e.printStackTrace(); } char[] ch = {'h','e','l','l','o'}; String s = null; //获得Class类对象的有参构造方法,括号里面参数的写法是:类型.class Constructor<?> con = c.getConstructor(char[].class); //用此构造方法构造一个新的字符串对象,参数为一个char数组 s = (String) con.newInstance(ch); System.out.println("构造的字符串:" + s); } }
注:无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在,也就是使用Class类的newInstance()无参构造对象时,原类一定要有对应无参构造函数。
4、3 获取类的构造器
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
1.public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
2.public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
3.public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
4.public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器
从名字来看,还是很好懂的,带上Declared的都是获得所有的构造方法,包括私有
Class cls1 = Role.class; //指定参数列表获取特定的方法 Constructor con = cls1.getDeclaredConstructor(new Class[]{String.class}); con.setAccessible(true); //设置可访问的权限 Object obj = con.newInstance(new Object[]{"liyang"}); System.out.println(obj); //打印一下这个对象的信息 //获取所有的构造方法集合 Constructor con1[] = cls1.getDeclaredConstructors(); con1[1].setAccessible(true); Object obj1 = con1[1].newInstance(new Object[]{"tom"}); System.out.println(obj1);
解释一下:第一个是获得一个指定的方法,我们指定了参数是一个String类型,第二段我们获得了所有的构造方法集合,并选取了其中一个创建了新的对象。
注意,以上的四个方法全部需要抛出异常,当我们获得私有的方法的时候,要用setAccessible设置一下可访问的权限,例子中没有演示获取共有方法,那个比较简单,就不做介绍了,其实掌握了上面两个,其他就好理解了。
4、5 获取类的成员变量
了解了构造器,其实你可以猜到成员变量的获取方法了,成员变量用Field类进行封装。
主要的方法非常的类似:
1.public Field getDeclaredField(String name) 获取任意指定名字的成员
2.public Field[] getDeclaredFields() 获取所有的成员变量
3.public Field getField(String name) 获取任意public成员变量
4.public Field[] getFields() 获取所有的public成员变量
可以看出这些方法都是异曲同工的,好了直接看一下例子吧
import java.lang.reflect.Field; class Person { public String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } } public class Demo { public static void main(String[] args) throws Exception { Person p = new Person("zhangsan",12); Class<?> c = p.getClass(); //获取公共属性的值 Field f1 = c.getField("name"); //get(p)表明要获取是哪个对象的值 String str = (String) f1.get(p); System.out.println("姓名: " + str); //获取私有属性的值 Field f2 = c.getDeclaredField("age"); //age是私有属性,所以要设置安全检查为true f2.setAccessible(true); int age = (int) f2.get(p); System.out.println("年龄: " + age); } }
4、6 获取类的方法
封装类的方法的类是Method.获取method也有四个方法
1.public Method[] getMethods() 获取所有的共有方法的集合
2.public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合
3.public Method[] getDeclaredMethods() 获取所有的方法
4.public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
Method f = cls1.getMethod("getName", null); Object name = f.invoke(obj, null); System.out.println("we invoke method : "+ name);
import java.lang.reflect.Method; class Person { public void print(int i) { System.out.println("我在写数字: " + i); } public static void say(String str) { System.out.println("我在说: " + str); } } public class Demo { public static void main(String[] args) throws Exception { Person p = new Person(); Class<?> c = p.getClass(); //getMethod()方法需要传入方法名,和参数类型 Method m1 = c.getMethod("print", int.class); //invoke()表示调用的意思,需要传入对象和参数 m1.invoke(p, 10); Method m2 = c.getMethod("say", String.class); //这里的null表示不由对象调用,也就是静态方法 m2.invoke(null, "你妹"); } }
//反射调用方法,可以通过Method类的invoke方法实现动态方法的调用
//public Object invoke(Object obj, Object... args)
//第一个参数代表对象
//第二个参数代表执行方法上的参数
//若反射要调用类的某个私有方法,可以在这个私有方法对应的Mehtod对象上先 调用setAccessible(true)
class类的其它方法:
取得类所实现的接口 getInterfaces()
取得父类 getSuperclass()
返回该类的类加载器 getClassLoader()
返回表示数组组件类型的 Class getComponentType()
判定此 Class 对象是否表示一个数组类 isArray()
5、java反射机制可以调用到私有方法,是不是就破坏了JAVA的卦装性呢。
这是一个很值得探讨的问题,许多人接触反射时,对反射功能之强大都会抱有怀疑,感觉严重破坏了封装的性质。可是,什么是封装,什么是安全呢?
封装,是将具体的实现细节隐藏,而把功能作为整体提供给类的外部使用,也就是说,公有方法能够完成类所具有的功能。当别人使用这个类时,如果通过反射直接调用私有方法,可能根本实现不了类的功能,甚至可能会出错,因此通过反射调用私有方法可以说是没有任何用处的,开发人员没有必要故意去破坏封装好的类。从这点上看,封装性并没有被破坏。
所谓安全,如果意思是保护实现源码不被别人看见,那没有作用。不用反射也能轻易获取源码。
所以我以为反射机制只是提供了一种强大的功能,使得开发者能在封装之外,按照特定的需要实现一些功能。就好比核技术,虽然造核弹很危险吧,但造核电站还是很有用处的(这个比喻似乎不是很恰当,将就将就)。
Java语言是一个严谨的编程语言,语言本身是静态的。为了能让语言具有动态编程的特性,必须要有反射机制。而反射机制本身就是底层的处理,不可能按表层的封转特性来处理。也就是说不给调用私有方法的能力,很多程序受到局限,那么实现起来就麻烦了。
以上说的,有肯能你没明白。举一个生活的例子,你家的电视机是要由外壳的,目的是不让普通人接触到电视中的电路。那么Java语言的基本面向对象特征正是这个层次的应用。也就是对于普通程序员的程序,是通过遥控器来操作电视的。但是,如果你是一个专业的电工的话,那么可以打开电视机的后盖,调整电视中的电路和结构,甚至如果是电工的话,那么调台可能都不使用遥控器,而是通过调整内部电路的电阻的阻值来实现。Java中的反射机制正是提供更高要求的编程来使用的,不需要考虑基本面向对象的特征,而是要考虑能否得到和控制代码中的一切,这样反射机制编程才有意义。
来源:点击打开链接
6、用反射机制能干什么事
刚开始在使用jdbc时侯,在编写访问数据库时写到想吐,有八个表,每个表都有增删改查中操作 那时候还不知道有反射机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率地,而且代码冗余的厉害,最要命的是看着差不多的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一 个或少一个字母啊……),一个错误就可以让你找半天。 有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,就OK啦,无需为每一个表都创建dao类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。说白了,反射机制就是专门帮我们做那些重复的有规则的事情,所以现在很多的自动生成代码的软件就是运用反射机制来完成的,只要你按照规则 输入相关的参数.
参考来源:
深入研究java.lang.Class类
java反射机制初探
java中的反射总结
Java反射机制
相关文章推荐
- URL,URI,URN之间的区别
- Java之美[从菜鸟到高手演变]之HashMap、HashTable
- 【eclipse】用Eclipse编程时,查看源代码,显示Source not found问题的解决方法。
- Spring定时任务的几种实现
- Eclipse 编辑注释模板
- Spring定时任务的几种实现
- Java中处理有效字符,截取小数无效字符
- java实现冒泡排序
- java中用到的基本排序
- Java集合的小抄 Java初学者必备
- java类的生命周期
- Eclipse在异常关闭后,启动闪退的解决办法(转)
- Java根据用户生日计算年龄
- java中静态代码块的用法 static用法详解
- myEclipse 打不开struts-config.xml 报Could not open the editor: An unexpected exception was thrown 错误(转载)
- Java常用类型转换
- Java Annotation
- Spring MVC入门
- java这些东西发展(1)-------大约ORA00604和ORA12705
- myEclipse中的项目导航栏和代码编辑栏不见了