反射(java.lang.reflect)用于分析类能力
(一)Class类
1.定义
Java运行时为每一个对象都维护的一个类型标识,用于跟踪对象所属的类提供给虚拟机分析调用,而保存这些信息的类就是Class类
(一个Class类对象可以理解为一个类型,这个类型可以是类或基本数据类型int等)
2.作用
通过对象所属的Class类,我们可以获取对象类型的数据域,方法,父类等一切类信息,还可以用它来创建实例对象
获得父类
//2.获取父类
Class superc1=c1.getSuperclass();
创建实例
//利用反射创建一个实例对象
Class myClass=Class.forName("java.util.Random");
Random random=(Random)myClass.newInstance();
3.获得Class类的3种途径
调用Class的静态方法获取:Class.forName(String className)
对象调用getClass()方法获取Class
通过类型名.class获取,如T.class,T可以是基本数据类型int等,也可以是具体的类如Random.class
Class myClass=Class.forName("java.util.Random");
myClass=newRandom().getClass();
myClass=Random.class;
(二)用于描述一个class的三个类:Field,Method,Constructor
Field类代表一个class中的数据域
Method类代表一个class中的方法
Constructor类代表一个class中的构造器
这三个类都继承Accessible
1.获取一个类中的Field,Method,Constructor
Class类调用getDeclaredFields()方法获得该类的所有数据域
Class类调用getDetclaredMethods()方法获得该类的所有方法
Class类调用getDetclaredConstructors()方法获得该类的构造器
2.获得一个Class|Field|Method|Constructor的修饰符
//Modifier.toString()能够获取c1的修饰符public final
String modifiers=Modifier.toString(c1.getModifiers());
调用这四个类的getModifiers()方法可以返回一个int,作为参数传入Modifier.toString(),该方法会根据int判断出修饰符
3.获得Field数据域的类型(Class)与Field的名称
Class classType=f.getType();
String name=f.getName();
4.获取Method的返回类型,Method名称,Method参数类型
String returnType=methods[j].getReturnType().getName();
String methodName=methods[j].getName();
Class[] paraTypes=methods[j].getParameterTypes();
5.打印一个类的具体信息
packageReflect;importjava.lang.reflect.Constructor;importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;/*** @ClassName ReFlectionTest
* @Description 利用反射打印Double类的所有方法
* @Author cherry
* @Date 2018/6/9 21:22
* @Update 2018/6/9 21:22
**/
public classReFlectionTest{public static voidmain(String[] argv){
String className="java.lang.Double";try{//1.获取Class
Class c1=Class.forName(className);//2.获取父类
Class superc1=c1.getSuperclass();//3.Modifier.toString()能够获取c1的属性public final
String modifiers=Modifier.toString(c1.getModifiers());//4.打印c1的属性
if(modifiers.length()>0)System.out.print(modifiers+" ");//5.打印c1的类名
System.out.print("class "+className);//6.若有继承则打印
if(superc1!=null&&superc1!=Object.class)System.out.print("extends "
+superc1.getName());//7.打印中括号
System.out.print("\n{\n");//8.打印域
printFields(c1);//9.打印构造器
printConstructors(c1);//10.打印方法
printMethods(c1);//11.打印中括号
System.out.print("\n}\n");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}/*** 打印域
*@paramc1*/
public static voidprintFields(Class c1){//1.获得所有域
Field[] fields=c1.getFields();//2.遍历打印
for(Field f:fields){
Class classType=f.getType();
String name=f.getName();//3.打印进位符
System.out.print(" ");//4.打印属性
String modifiers=Modifier.toString(f.getModifiers());if(modifiers.length()>0)System.out.print(modifiers+" ");
System.out.println(classType+" "+name+";");
}
System.out.println();
}/*** 打印传入类的构造器
*@paramc1*/
public static voidprintConstructors(Class c1){//1.获取所有构造器
Constructor[] constructors=c1.getConstructors();//2.遍历打印
for(Constructor c:constructors){//3.打印tab占位符
System.out.print(" ");//4.获取构造器的属性
String modifier=Modifier.toString(c.getModifiers());if(modifier.length()>0)System.out.print(modifier+" ");//5.打印构造器名
String conName=c.getName();
System.out.print(conName+"(");//6.打印参数
Class[] paraTypes=c.getParameterTypes();for(int j=0;j0)System.out.print(", ");
System.out.print(paraTypes[j].getName());
}
System.out.print(");\n");
}
System.out.print("\n");
}/*** 打印方法
*@paramc1*/
public static voidprintMethods(Class c1){//1.获取所有的方法
Method[] methods=c1.getMethods();//2.遍历打印
for(int j=0;j
System.out.print(" ");//4.打印方法属性
String modifiers=Modifier.toString(methods[j].getModifiers());if(modifiers.length()>0)System.out.print(modifiers+" ");//5.打印返回类型
String returnType=methods[j].getReturnType().getName();
System.out.print(returnType+" ");//6.打印方法名
String methodName=methods[j].getName();
System.out.print(methodName+"(");//7.打印参数名
Class[] paraTypes=methods[j].getParameterTypes();for(int i=0;i0)System.out.print(",");
System.out.print(paraTypes[i].getName());
}if(j+1!=methods.length) System.out.print(")\n");
}
}
}
(三)运行时获取一个对象的数据域的具体值
Student student=new Student(18); //创建student对象
Class studentClass=student.getClass(); //获取Student的Class
Field field=studentClass.getDeclaredField("age"); //得到age域
field.setAccessible(true); //设置可访问private域
System.out.println(field.get(student)); //访问age域的值
(四)调用一个对象的方法
Student student=new Student(18); //创建student对象
Class studentClass=student.getClass(); //获取Student的Class
Method setAgeMethod=studentClass.getMethod("setAge", int.class); //获取方法
setAgeMethod.invoke(student,20); //访问age域的值
System.out.println(student.getAge()); //返回20
(五)实现一个泛型数组操作方法
/*** 用于扩展已经填满的数组
*@parama
*@paramnewLength
*@return
*/
public static Object goodCopyOf(Object a,intnewLength){
Class c1=a.getClass(); //获取传入的a的Class
if(!c1.isArray())return null; //若不是数组类型直接返回null
Class compomentType=c1.getComponentType(); //获取数组元素类型
int length=Array.getLength(a); //获取传入的数组的长度
Object newArray=Array.newInstance(compomentType,newLength); //Array.newInstance()根据元素类型与长度新建一个相同类型数组且长度扩大
System.arraycopy(a,0,newArray,0,Math.min(length,newLength)); //将原数组的值赋予新数组
returnnewArray;
}
参考《Java核心技术 卷I》p190