Java反射机制
Java 语言的反射机制
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?
Java 反射机制主要提供了以下功能
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法
Reflection 是Java被视为动态(或准动态)语言的一个关键性质。
public static void main(String[] args) throws Exception {
// 加载初始化命令行参数指定的类,每一个类初始化加载时都有一个对应的Class类,这个Class类可以获得该类的所有方法
Class<?> classType=Class.forName(args[0]);
// 获得类的所有方法
Method methods[]=classType.getDeclaredMethods();
for(int i=0;i<methods.length;i++){
System.out.println(methods[i].toString());
}
}
}
public class ReflectTester {
public Object copy(Object object) throws Exception {
// 获得对象类型,获得Object对象所对应的Class类
Class<?> classType = object.getClass();
// 将Object所属的类的名字打印出来,getName()获得类的完整名字
System.out.println("Class:" + classType.getName());
// getConstructors():获得类的public类型的构造方法。
// getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes
// 参数指定构造方法的参数类型。
// 通过默认构造方法创建一个新的对象,Constructor类代表的object类的构造方法,newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
Object objectCopy = classType.getConstructor(new Class[] {})
.newInstance(new Object[] {});// 通过默认的构造方法来创建一个当前类的实例,先调用Class类的getConstructor()方法获得一个Constructor
// 对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
// getDeclaredFields()获得对象的所有属性,Field类代表object类的成员变量(成员变量也称为类的属性),如果是getFields()是获得类的public类型的所有方法
Field fields[] = classType.getDeclaredFields();// Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性
// 获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性拷贝到新的对象中
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
// 得到field对象所对应的属性的名字
String fieldName = field.getName();
// 将fieldName的第一个字母转化为大写赋给firstLetter.
String firstLetter = fieldName.substring(0, 1).toUpperCase();
// 获得和属性对应的getXXX()方法的名字,将"get"+大写的首字母+剩下的字母(从1到最后一个字母)
String getMethodName = "get" + firstLetter + fieldName.substring(1);
// 获得和属性对应的setXXX()方法的名字
String setMethodName = "set" + firstLetter + fieldName.substring(1);
// getMethod()获得类的public的类型的方法,getDeclaredMethod()获得类的所有类型的方法
// 获得和属性对应的getXXX()方法,Method类代表object类的方法,getMethod(String name,
// Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes
// 参数指定方法的参数类型。
Method getMethod = classType.getMethod(getMethodName,
new Class[] {});
// 获得和属性对应的setXXX()方法
Method setMethod = classType.getMethod(setMethodName,
new Class[] { field.getType() });// 返回设置的field属性的Class类型
// invoke调用原对象的getXXX()方法,第一个为参数的方法对象的名称,每二个为参数的方法对象的参数列表
Object value = getMethod.invoke(object, new Object[] {});// 调用object对象的Get方法
System.out.println(fieldName + ":" + value);
// 调用拷贝对象objectCopy的setXXX()方法
setMethod.invoke(objectCopy, new Object[] { value });
}
return objectCopy;
}
public static void main(String[] args) throws Exception {
Customer customer = new Customer("Tom", 21);
customer.setId(new Long(1));
Customer customerCopy = (Customer) new ReflectTester().copy(customer);
System.out.println("Copy information:" + customerCopy.getId() + " "
+ customerCopy.getName() + " " + customerCopy.getAge());
}
}
class Customer {
private Long id;
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class InvokeTester {
public int add(int param1, int param2) {
return param1 + param2;
}
public String echo(String msg) {
return "echo: " + msg;
}
// public InvokeTester(String str){
// }
public static void main(String[] args) throws Exception {
// 获得InvorkeTester类所对应的Class对象
Class<?> classType = InvokeTester.class;
// 调用不带参数的默认构造方法生成一个实例
Object invokeTester = classType.newInstance();
// Object invokeTester = classType.getConstructor(new
// Class[]{}).newInstance(new Object[]{});
// 调用InvokeTester对象的add()方法
Method addMethod = classType.getMethod("add", new Class[] { int.class,
int.class });
// invoke用于调用方法,Method类的invoke(Object obj,Object
// args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回
// 尽管InvokeTester 类的add()方法的两个参数以及返回值都是int类型,调用add Method
// 对象的invoke()方法时,只能传递Integer 类型的参数,并且invoke()方法的返回类型也是Integer
// 类型,Integer 类是int 基本类型的包装类
Object result = addMethod.invoke(invokeTester, new Object[] {
new Integer(100), new Integer(200) });
System.out.println((Integer) result);
// 调用InvokeTester对象的echo()方法
Method echoMethod = classType.getMethod("echo",
new Class[] { String.class });
result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
System.out.println((String) result);
}
}
{
public static void main(String args[]) throws Exception
{
// classType为java.lang.String对应的Class类
Class<?> classType = Class.forName("java.lang.String");
// 创建一个长度为10的字符串数组,生成java.lang.String对应的一个数组,
Object array = Array.newInstance(classType, 10);
// 把array数组的索引位置为5的元素设为"hello"
Array.set(array, 5, "hello");
// 获得array数组的索引位置为5的元素的值
String s = (String) Array.get(array, 5);
System.out.println(s);
}
}
public static void main(String args[]) {
int[] dims = new int[] { 5, 10, 15 };
// Integer.TYPE获得Integer对应的Class对象,dims决定是数组的维数及长度
Object array = Array.newInstance(Integer.TYPE, dims);
// 返回数组第一维索引为3的类型的一个对象,此时为一个二维数组,第一维为3所在的一个二维数组
Object arrayObj = Array.get(array, 3);
// 返回该数组的组件类型,如果不为数组的话返回NULL
Class<?> cls = arrayObj.getClass().getComponentType();
System.out.println(cls);
// ==》System.out.println(cls.toString());
// 将第二维为5加进去,此时arrayObj为一个一维数组,第一维为3,第二维为5所在的一个数组
arrayObj = Array.get(arrayObj, 5);
// 将一维数组的第十个元素设置为37
Array.setInt(arrayObj, 10, 37);
int arrayCast[][][] = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);
}
}
Class object 诞生管道 | 示例 |
运用getClass() 注:每个class都有此函数运用 |
String str="abc"; Class c1=str.getClass();//str所对应的Class类 |
运用Class.getSuperClass() |
Button b=new Button; Class c1=b.getClass(); Class c2=c1.getSuperClass();//c1的父类所对应的Class类 |
运用static method Class.forname() (最常被使用) |
Class c1=Class.forName("java.lang.String");//java.lang.String所对应的Class类 Class c2=Class.forName("java.awt.Button"); Class c3=Class.forName("java.util.LinkedList$Entry"); Class c4=Class.forName("I"); Class c5=Class.forName("[I"); |
运用.class语法 |
Class c1=String.class;//String所对应的Class类 Class c2=java.awt.Button.class; Class c3=Main.InnerClass.class; Class c4=int.class; Class c5=int[].class; |
运用primitive wrapper classes的TYPE的语法 |
Class c1=Boolean.TYPE;//Boolean所对应的Class类 Class c2=Byte.TYPE; Class c3=Character.TYPE; Class c4=Short.TYPE; Class c5=Integer.TYPE; Class c6=Long.TYPE; Class c7=Float.TYPE; Class c8=Double.TYPE; Class c9=Void.TYPE; |
Class c=Class.forName("DynTest");
Class[] pType=new Class[]{double.class,int.class};
Constructor ctor=c.getConstructor(pTypes);
//指定parameter list,便可获得特定之ctor
Object obj=null;
Object[] arg=new Object[]{3.14159,125};//自变量
obj=ctor.newInstance(arg);
System.out.println(obj);
...
System.out.printl("func invoked");
return s;
}
public static void main(String args[]){
Class c=Class.forName("Test");
Class ptypes[]=new Class[2];
ptypes[0]=Class.forName("java.lang.String");
ptypes[1]=Class.forName("java.util.Hashtable");
method m=c.getMethod("func",ptypes);
Test obj=new Test();
Object args[]=new Object[2];
arg[0]=new String("Hello World");
arg[1]=null;
Object r=m.invoke(obj,arg);
Integer rval=(String)r;
System.out.println(rval);
}
public double d;
public static void main(String args[]){
Class c=Class.forName("Test");
Field f=c.getField("d");//指定field名称
Test obj=new Test();
System.out.println("d="+(Double)f.get(obj));
f.set(obj,12.34);
System.out.println("d="+obj.d);
}
}