目录
定义
使用方法
1.Field
2.Method
3.简单实例
JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射的方法主要有三种:Class,Method,Field。这里主要简单使用一下Method和Field方法。
获取对象的属性,给对象属性赋新值
(1)获取Field的常用方法:
getFields():获取public类型的属性(也可以获取到父类的public修饰的属性)并返回一个Field数组;
getDeclaredFields(): 获取所有属性(包括public、protected、default、private权限类型,但不能获取继承父类的属性)并返回一个Field数组;
getField(String name):获取特定的public对象属性,name为属性名;
getDeclaredField(String name): 获取特定的对象属性,属性的访问权限可以是public、protected、default、private,name为属性名;
(2)Field对象的常用方法:
getType():返回Field对象的类型
getName():返回Field对象的名字
set(Object obj,Object value):设置对象属性的值,obj为实例对象,value为要为属性设置的新值
获取对象方法,执行对象方法
继承的方法(包括重载、重写和隐藏的)会被编译器强制执行,这些方法都无法反射。
(1)获取Method对象的方法
getMethod(String name,Object type):获取特定的public对象方法,name为方法名,type为参数类型;
getDeclaredMethod(String name,Object type): 获取特定的对象方法,属性的访问权限可以是public、protected、default、private,name为方法名,type为参数类型;
(2)Method对象的常用方法:
getReturntype():获取Method对象返回类型
getName():返回Method对象的名字
invoke(Object obj,Object value):执行对象方法,obj为实例对象,value为方法参数,没有参数写null
(3)提示
invoke方法的参数和返回类型必须是Object类型的,这就意味着必须进行多次的类型 转化,这样势必会造成代码出错几率。不仅如此,使用反射获得方法指针的代码要比仅仅直接调用方法慢一些。
公用对象People
public class People {
public String name = "小白";
//类构造方法
public People(String name){
this.name = name;
}
//属性的get,set方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) {
//创建一个People类对象
People people = new People("小白");
System.out.println("初始化后name值:"+people.getName());
//初始化
Field attribute = null;
Method method = null;
System.out.println("Field方法执行结果;");
//用Field对象获取people对象的属性信息
try {
//先用getClass方法获取对象实例,再用getField方法获取name属性的Field类对象
attribute = people.getClass().getField("name");
//getName方法获取name属性名
String attrName = attribute.getName();
//getType方法获取name属性类型
String attrType = attribute.getType().toString();
System.out.println("属性名:"+attrName+"\n属性类型:"+attrType+"\n属性值:"+people.getName());
//set方法重新给name属性赋值
attribute.set(people,"大白");
System.out.println("用set方法重新赋值后name值:"+people.getName());
}catch(Exception e){
e.printStackTrace();
}
System.out.println("Method方法执行结果;");
//用Method对象获取people对象的方法信息
try{
//用getMethod方法获取setName方法的Method对象
method = people.getClass().getDeclaredMethod("setName",String.class);
//用Method的getName方法获取setName方法的方法名
String methodName = method.getName();
//用Method的getReturnType方法获取setName方法的返回值类型
String methodType = method.getReturnType().toString();
System.out.println("方法名:"+methodName+"\n方法类型:"+methodType);
//用Method的invoke方法执行该方法
method.invoke(people,"中白");
System.out.println("invoke方法执行后name值:"+people.getName());
}catch(Exception e){
e.printStackTrace();
}
}
}
控制台输出结果
初始化后name值:小白
Field方法执行结果;
属性名:name
属性类型:class java.lang.String
属性值:小白
用set方法重新赋值后name值:大白
Method方法执行结果;
方法名:setName
方法类型:void
invoke方法执行后name值:中白
1)首先获取数组的类对象
2)确认它是一个数组
3)使用Class类(只能定义表示数组的类对象)的getComponent方法确定数组对应类型
4)使用Array类中的静态方法newInstance方法构造新的数组,它有两个参数,一个是数组元素类型,一个是数组长度。
5)用System类中的arraycopy方法将原来数组的数据copy进新数组中,变相实现数据扩容。
import java.lang.reflect.Array;
import java.util.Arrays;
public class ReflectTest {
//泛型数组copy正确方法
public static Object goodCopyOf(Object a,int newLength){
Class c1 = a.getClass();
if(!c1.isArray())
return null;
Class componentType = c1.getComponentType();
int length = Array.getLength(a);
Object newArray = Array.newInstance(componentType,newLength);
System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
return newArray;
}
//泛型数组copy错误方法
public static Object[] badCopy(Object[] a, int newLength){
Object[] newArray = new Object[newLength];
System.arraycopy(a,0,newArray,0,Math.min(a.length,newLength));
return newArray;
}
public static void main(String[] args) {
int [] a = {1,2,3};
a = (int[])goodCopyOf(a,10);
System.out.println(Arrays.toString (a));
String b[] = {"a","b","c"};
b = (String[])goodCopyOf(b,10);
System.out.println(Arrays.toString(b));
System.out.println("This is a bad copy method!");
b = (String[])badCopy(b,10);//抛出错误:java.lang.ClassCastException
}
}