----------------------android培训、java培训、期待与您交流! --------------------
反射
1、反射的产生
反射就是把一个java类的各种成分映射成一个个的java类。然后,我们再继续操作这些java类。一个java类的成分包括包、变量、父类、成员方法、构造函数灯。而用反射的方式就是为了获取这些成分并对其操作。
2、通过反射来查看类的信息
java程序中许多对象在运行时候都会出现两种类型:编译时和运行时。
2.1 获得Class对象
每个类产生以后,系统就会为该类生成一个对应的Class对象,通过该Class对象就可以访问这个类的信息。
常见的获得Class对象的三种方法:
使用Class对象的静态方法:forName("完成的类名");
用类名.class来进行访问。例如:Person.class。
用对象的getClass()方法来获得,这个方法继承自Object。例如:Person p=new Person();p.getClass();
三种方法的比较:
对于第一种和第二种都是直接根据类名来调用的,但相比之下第二种更加具有优势。因为,其代码更加安全,程序在编译的时候就会检查出要访问的Class对象是否存在、程序性能更高,因为这种方法无需调用方法。
2.2 常见的Class方法
获得构造函数
Constructor<T> getConstructor(Class<T>... ParameterType):返回的是该类所指定参数的public构造函数。
Constructor<T>[] getConstructors():返回的是该类所具有的所有的public构造函数。
Constructor<T>[] getDeclaredConstructors():返回的是该类所有声明的构造函数。
获得所访问的Class所包含的所有方法
Method getMethod(String name;Class... ParameterType)返回的是此Class对象所指定name的方法。
Method[] getMethods()返回的是此Class对象所指定的方法。
Method getDeclaredMethod(String name;Class... ParameterType)返回的是此Class对象所声明的名为name的方法。
Method[] getDeclaredMethods()返回的是此Class对象所指定的方法。
获得所访问的Class所包含的变量
Field getField(String name):返回name这个变量所对应的Fileld。
Field[] getFields():返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
Field getDeclaredField(String name:返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
Field[] getDeclaredFields():返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
其他常见的方法:
String getName():返回此Class的名字
boolean isArray():判定此class对象是否是数组。
Object newInstance():返回的是此class对象无参的构造函数的实例对象。
3、以上方法的综合应用
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ReflectionTest2 {
public static void main(String[] args)throws Exception {
Person p=new Person("zhangsan",20);
//调用class对象的相应方法获得构造函数以及创建相应的实例对象
Class clazz=p.getClass();
Constructor constructor1 =clazz.getConstructor();
Constructor constructor2 =clazz.getConstructor(String.class,int.class);
Person p1=(Person)constructor2.newInstance("zhangqi",20);
Person p2=(Person)constructor1.newInstance();
System.out.println(p1.getName()+":"+p1.getAge());
System.out.println(p2.getName()+":"+p2.getAge());
//获得Person上的被private修饰的变量
Field fieldName=clazz.getDeclaredField("name");
fieldName.setAccessible(true);
String revalue=(String)fieldName.get(p);
System.out.println(revalue);
//用反射操作数组
String arr="hellow";
printObject(arr);//直接进行打印
String[] arr1=new String[]{"java","hellow","world"};
printObject(arr1);//拆开进行打印
}
private static void printObject(Object obj)
{
if(obj.getClass().isArray())
{
int len=Array.getLength(obj);
for(int x=0;x<len;x++)
{
Object obj1=Array.get(obj, x);
System.out.println(obj1);
}
}else{
System.out.println(obj);
}
}
}
以上例子中综合运用了反射的基本方法,访问了一个类中的私有的属性。
4、用反射的方法获得集合的泛型参数
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class ReflectionDemo {
/**
*参数类型: 获取泛型集合的
*/
private Map<String,Integer> nap=new HashMap<String,Integer>();
public static void main(String[] args)throws Exception {
Class clazz=ReflectionDemo.class;
Field field=clazz.getDeclaredField("nap");
//field.setAccessible(true);
Class f=field.getType();
System.out.println(f);//interface java.util.Map
Type t=field.getGenericType();
System.out.println(t);//java.util.Map<java.lang.String, java.lang.Integer>
if(t instanceof ParameterizedType)
{
ParameterizedType ps=(ParameterizedType)t;
System.out.println(ps.getRawType());//interface java.util.Map
Type[] types=ps.getActualTypeArguments();
for(Type type:types)
{
System.out.println(type);//class java.lang.String
//class java.lang.Integer
}
}
}
}
5、对javaBean的简单操作
javaBean:也是一个类,就是对于那些满足某些条件的类的一组总称
就是某个类的成员变量时私有的,在外部不可见,只有提供了get和set方法来进行获取和设置。
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Javabeans {
public static void main(String[] args)throws Exception {
Person p=new Person("zhangsa",20);
String propertyName="name";
Object obj1 = getProperty(p, propertyName);
System.out.println(obj1);
Object value="zyk";
setProperty(p, propertyName, value);
System.out.println(p.getName());
}
private static void setProperty(Object obj, String propertyName, Object value)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd2=new PropertyDescriptor(propertyName, obj.getClass());
Method methodsetName=pd2.getWriteMethod();
methodsetName.invoke(obj,value);
}
private static Object getProperty(Object p, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd=new PropertyDescriptor(propertyName, p.getClass());
Method methodgetName=pd.getReadMethod();
Object obj=methodgetName.invoke(p);
return obj;
}
}
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的在我们以后的使用中相信会有更好的应用