您的位置:首页 > 编程语言 > Java开发

java反射学习--操作私有成员

2013-06-19 10:11 471 查看
反射,reflection,听其名就像照镜子一样,可以看见自己也可以看见别人的每一部分。在java语言中这是一个很重要的特性。

反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。



java中有一个类很特殊,就是Class类,很多朋友在写程序的时候有用过比如Hello.class来查看类型信息,大家就可以把它理解为封装了类的信息,很多解释说Class类没有构造器,其实是有的,只不过它的构造方法是private的(构造函数还有private的??有,这样是为了禁止开发者去自己创建Class类的实例)。



/*

* Constructor. Only the Java Virtual Machine creates Class

* objects.

*/



private
Class() {}



Class类是由虚拟机创建的,不需要我们去显示创建。

好了,先看一个简单的反射例子:

import java.lang.reflect.Method;

public class ShowMethod {

public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("java.lang.Object");

Method[] methods = c.getDeclaredMethods();

for(Method method : methods){
System.out.println(method);
}
}
}


输出:

private static native void java.lang.Object.registerNatives()
public final native java.lang.Class java.lang.Object.getClass()
public native int java.lang.Object.hashCode()
public boolean java.lang.Object.equals(java.lang.Object)
protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException
public java.lang.String java.lang.Object.toString()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
protected void java.lang.Object.finalize() throws java.lang.Throwable


这里注意:forName中的参数一定是完整的类名(包名+类名),并且这个方法需要捕获异常。

当没有创建对象的时候,获取类类型的方法

Class<?> c = Class.forName("java.lang.String");

Class<?> c = String.class;



好了,看一个具体的案例吧,

描述一下这个案例的简单要实现的功能:

DataType.java类中提供几个私有的字段(未提供set和get方法),用另外一个类,修改这几个字段的值,.我们要实现的就是使用反射的方法来访问这些Fields 和Methods.


import java.util.List;

public class DataType {

private int n;

private String str;

private String[] sArr;

private List<Integer> list;

public DataType(){}

public DataType(int n, String str, String[] arr, List<Integer> list) {
this.n = n;
this.str = str;
sArr = arr;
this.list = list;
}

public String toString(){

StringBuilder sb = new StringBuilder();
sb.append("int n=").append(this.n).append(" ");
sb.append("String str=").append(this.str).append(" ");

sb.append("String[] sArr=");
for(int i=0;i<sArr.length;i++){
sb.append(sArr[i]).append(" ");
}

sb.append("List<Integer> list=");
for(int i=0;i<list.size();i++){
sb.append(list.get(i)).append(" ");
}

return sb.toString();
}

}


首先我们先使用不带参数的构造方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class MyTest {

public static void main(String[] args) throws Exception {

int n=100;

String str = "I love java";

String[] sArr = new String[]{"xiaoming","xiaohong","zhangsan"};

List<Integer> list = new ArrayList<Integer>();//0	1	2

for(int i=0;i<3;i++){
list.add(i);
}

Class<DataType> clazz = DataType.class;

//获取默认的构造方法对象
Constructor<DataType> cons = clazz.getConstructor(new Class[]{});
//运行不带参数的构造方法,创建对象实例
DataType dataType = cons.newInstance(new Object[]{});
//获取所有的字段
Field[] fields = clazz.getDeclaredFields();

//为每一个字段赋值
for(Field field : fields){
//首先设置该字段的可访问性
field.setAccessible(true);

if(field.getType().getSimpleName().equals("int")){
field.set(dataType, n);
}else if(field.getType().getSimpleName().equals("String")){
field.set(dataType, str);
}else if(field.getType().getSimpleName().equals("String[]")){
field.set(dataType, sArr);
}else if(field.getType().getSimpleName().equals("List")){
field.set(dataType, list);
}
}

//获取toString方法
Method toStringMethod = clazz.getMethod("toString", new Class[]{});

Object result = toStringMethod.invoke(dataType, new Object[]{});

System.out.println(result);

}
}


输出结果:int n=100 String str=I love java String[] sArr=xiaoming xiaohong zhangsan List<Integer> list=0 1 2

如果用带参数的构造方法来完成相同的功能,


//获取带参数的构造方法对象
Constructor<DataType> cons2 = clazz.getConstructor(new Class[]{int.class,String.class,String[].class,List.class});

DataType dataType2 = cons2.newInstance(new Object[]{n,str,sArr,list});

Object result2 = toStringMethod.invoke(dataType2, new Object[]{});

System.out.println(result2);


输出结果:int n=100 String str=I love java String[] sArr=xiaoming xiaohong zhangsan List<Integer> list=0 1 2








                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: