1: java中的反射机制:
a)在Java 运行时 环境中,对任意一个类, 可以知道这个类所有的属性和方法。
b)任意一个对象,可以动态地获取类的信息,然后调用类中的方法, 也是基于java中的反射。
2: java中反射能够提供的功能:
a)在运行时判断任意一个对象所属的类.
b)在运行时构造任意一个类的对象.
c)在运行时调用任意一个对象的方法.
3 :Java 反射相关的API简介:
位于java.lang.reflect包中
--Class类:代表一个类
--Filed类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
Class类:类的实例表示正在运行的java 应用程序中的类和接口。
来个小例子:
编写测试类的代码:
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
class A extends Object implements ActionListener{
private int a = 3;
public Integer b = new Integer(4);
public A(){}
public A(int id,String name){}
public int abc(int id,String name){return 0;}
public void actionPerformed(ActionEvent e){}
}
1)获取Class A 类中的属性。
//用来获取A类中的属性和属性值。
public class GetAattribute {
public static void main(String[] args) {
A a = new A();
Class aClass = a.getClass();
try{
System.out.println("反射类中所有公有的属性");
Field[] fpublic =aClass.getFields();
for(int j=0;j<fpublic.length;j++){
Class cl = fpublic[j].getType();
System.out.println("fb:"+cl);
}
System.out.println("反射类中所有的属性");
Field[] fall = aClass.getDeclaredFields();
for(int j=0;j<fall.length;j++){
Class cl = fall[j].getType();
System.out.println("fa:"+cl);
}
System.out.println("反射类中私有属性的值");
Field f = aClass.getDeclaredField("a");
f.setAccessible(true);
Integer i = (Integer)f.get(a);
System.out.println(i);
/* Field fInteger=aClass.getDeclaredField("b");
fInteger.setLong("b", 10L);
fInteger.setAccessible(true);
System.out.println(fInteger);*/
}catch(Exception e){
e.printStackTrace();
}
}
}
这里用到了两个方法,getFields()、getDeclaredFields(),它们分别是用来获取反射类中所有公有属性和反射类中所有的属性的方法。另外还有getField(String)和getDeclaredField(String)方法都是用来过去反射类中指定的属性的方法,要注意的是getField方法只能取到反射类中公有的属性,而getDeclaredField方法私有公共的都能够取到;
这里还用到了Field 类的setAccessible方法,它是用来设置是否有权限访问反射类中的私有属性的,只有设置为true时才可以访问,默认为false。另外 Field类还有set(Object AttributeName,Object value)方法,可以改变指定属性的值。
2)如何获取Class A类中的构造方法:
//获取A类中的构造函数, 以及构造函数的类型
public class GetAconstructor {
public static void main(String[] args) {
A a = new A();
printConstructors(a);
}
public static void printConstructors(A a) {
Class aClass = a.getClass();
//获取指定类的类名
String className = aClass.getName();
System.out.println("获取A类的名字:"+className);
try {
//获取指定类的构造方法 , 这个获取的是有参数的构造函数。
Constructor[] theConstructors = aClass.getConstructors();
for(int i=0; i<theConstructors.length; i++) {
//获取构造函数
Class[] parameterTypes = theConstructors[i].getParameterTypes();
System.out.print(className + "(");
for(int j=0; j<parameterTypes.length; j++)
System.out.print(parameterTypes[j].getName() + " ");
System.out.println(")");
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
用getConstructors()方法获取了反射类的构造方法的集合,并用Constructor类的getParameterTypes()获取该构造方法的参数。
3)获取一下反射类Class A 的父类和接口:
//获取A类的父类和接口
public class GetAparentClassAndinterface {
public static void main(String[] args) throws Exception {
A aClass = new A();
printInterfaceNames(aClass);
}
public static void printInterfaceNames(Object o) {
Class aClass = o.getClass();
//获取反射类A的接口
Class[] theInterfaces = aClass.getInterfaces();
for(int i=0; i<theInterfaces.length; i++){
System.out.println(theInterfaces[i].getName());
}
//获取反射类A的父类(超类)
Class theparentclass = aClass.getSuperclass();
System.out.println(theparentclass.getName());
}
}
只是用Class类的getInterfaces()方法获取反射类的所有接口,由于接口可以有多个,所以它返回一个 Class数组。用getSuperclass()方法来获取反射类的父类(超类),由于一个类只能继承自一个类,所以它返回一个Class对象。
4)获取反射类Class A 类中的方法:
//获取反射类中的方法
public class getAmethods {
public static void main(String[] args) {
A a = new A();
printMethods(a);
}
public static void printMethods(Object o) {
Class aClass = o.getClass();
System.out.println("反射类A:"+aClass);
String className = aClass.getName();
System.out.println("反射类A的名字:"+className);
//获取反射类中的方法
Method[] methods = aClass.getMethods();
for(int i=0; i<methods.length; i++) {
//输出方法的返回类型
System.out.print(methods[i].getReturnType().getName());
//输出方法名
System.out.print(" "+methods[i].getName()+"(");
//获取方法的参数
Class[] parameterTypes = methods[i].getParameterTypes();
for(int j=0; j<parameterTypes.length; j++){
System.out.print(parameterTypes[j].getName());
if(parameterTypes.length>j+1){
System.out.print(",");
}
}
System.out.println(")");
}
}
}
它只是获得了反射类的所有方法,包括继承自它父类的方法。然后获取方法的返回类型、方法名和方法参数。
5)获取反射类的属性、构造方法、父类、接口和方法之后就可以帮我们创建对象了。
//我们获取了反射类的属性、构造方法、父类、接口和方法,就可以创建对象了
public class GetObject {
public Object getObject(String cName,String MethodName,String[] type,String[] param){
Object retobj = null;
try {
//加载指定的Java类
Class cls = Class.forName(cName);
//获取指定对象的实例
Constructor ct = cls.getConstructor(null);
Object obj = ct.newInstance(null);
//构建方法参数的数据类型
Class partypes[] = this.getMethodClass(type);
//在指定类中获取指定的方法
Method meth = cls.getMethod(MethodName, partypes);
//构建方法的参数值
Object arglist[] = this.getMethodObject(type,param);
//调用指定的方法并获取返回值为Object类型
retobj= meth.invoke(obj, arglist);
}
catch (Throwable e) {
System.err.println(e);
}
return retobj;
}
//获取参数类型Class[]的方法
public Class[] getMethodClass(String[] type){
Class[] cs = new Class[type.length];
for (int i = 0; i < cs.length; i++) {
if(!type[i].trim().equals("")||type[i]!=null){
if(type[i].equals("int")||type[i].equals("Integer")){
cs[i]=Integer.TYPE;
}
else if(type[i].equals("float")||type[i].equals("Float")){
cs[i]=Float.TYPE;
}
else if(type[i].equals("double")||type[i].equals("Double")){
cs[i]=Double.TYPE;
}
else if(type[i].equals("boolean")||type[i].equals("Boolean")){
cs[i]=Boolean.TYPE;
}
else{
cs[i]=String.class;
}
}
}
return cs;
}
//获取参数Object[]的方法
public Object[] getMethodObject(String[] type,String[] param){
Object[] obj = new Object[param.length];
for (int i = 0; i < obj.length; i++) {
if(!param[i].trim().equals("")||param[i]!=null){
if(type[i].equals("int")||type[i].equals("Integer")){
obj[i]= new Integer(param[i]);
}
else if(type[i].equals("float")||type[i].equals("Float")){
obj[i]= new Float(param[i]);
}
else if(type[i].equals("double")||type[i].equals("Double")){
obj[i]= new Double(param[i]);
}
else if(type[i].equals("boolean")||type[i].equals("Boolean")){
obj[i]=new Boolean(param[i]);
}
else{
obj[i] = param[i];
}
}
}
return obj;
}
}
getObject()方法接收的五个参数分别是,Java的类名,方法名,参数的类型和参数的值。 由于一些返回值处理没处理好, main没有测试起来, 还要多想想。
关于反射的总结:
a)反射提供一种动态链接程序组件的多功能方法,它允许程序创建和控制任何类的对象.
b)它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息
c)但反射有两个缺点:第一个是性能问题,用于字段和方法接入时反射要远慢于直接代码, 但是要是在使用反射的过程中,作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。
对反射的理解也不是很深, 在实际的开发中也用得,因此整理的这些, 对于最后一个getObject()方法,有一些参数转换方面的有问题没能进行main方法测试, 如果有大神可以帮我看看
来源:http://www.iteye.com/topic/137944