复习了java反射,在这总结下
直接贴代码吧,都写在注释里了,供以后参考
import java.lang.reflect.*;
class CountAdd {
public final int q=1;public int add(int a,int b){
return a+b;}
}
//反射是把一个类转换成一个class对象,具有查看属性,方法的方法
//只写了一个例子,获取类属性方法
public class FanShe {
public static void haha(Class c){
Field[] fs = c.getDeclaredFields();
//属性,class调用只能获得类的修饰符名字,要获得属性的需要先获得属性对象,类型为Field,获取所有的用getDeclaredFields(),获取特定的用getDeclaredField(String name)
StringBuffer sb = new StringBuffer(); //字符串缓冲区,可以加入各种类型数据作为字符串
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n"); //类的修饰符与名字,getModifiers()返回类型为int,java专门提供了Modifier类来处理修饰符,这里在最后又做了测试
for(Field field:fs){
sb.append("\t");//跳格
sb.append(Modifier.toString(field.getModifiers())+" ");//属性的修饰符,获取修饰符需要两步,先用属性类的方法返回修饰符的编号,再用Modifier.toString(int a)获取字符串形式的修饰符
sb.append(field.getType().getSimpleName() + " ");//属性的类型
sb.append(field.getName()+";\n");//属性的名字
}
Constructor[] con=c.getDeclaredConstructors(); //构造方法,类似属性,获取方法对象类型为Constructor
for(Constructor constructor:con){
sb.append("\t");//跳格
sb.append(Modifier.toString(constructor.getModifiers())+" "); //修饰符
sb.append(constructor.getName()+"{}\n");//方法名
}
Method[] me=c.getDeclaredMethods(); //方法,类似属性,获取方法对象类型为Method
for(Method method:me){
sb.append("\t");//跳格
sb.append(Modifier.toString(method.getModifiers())+" "); //修饰符
sb.append(method.getReturnType().getSimpleName() + " ");//类型 在这里是getReturnType(),返回值为class
sb.append(method.getName()+"(");//方法名
Class<?>[] cla=method.getParameterTypes();//形参类型 getParameterTypes()返回值为数组对象
for(Class clas:cla){
sb.append(clas.getSimpleName()+"){}\n");
}
}
sb.append("}");
System.out.println(sb);
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
// TODO 自动生成的方法存根
@SuppressWarnings("rawtypes")
Class c = Class.forName("java.lang.Integer");
//获取所有的属性
haha(c);
Class a=Class.forName("CountAdd");
Object ob=a.newInstance();//可以看出是把CountAdd对象转换成Object对象,向上转换了,也就是说a.newInstance()其实得到的是子类的向上转型,向上转型有子类特有的变量和方法但是不能用,所以返回的类只和加载到java虚拟机的有关,不会因为转型而改变
CountAdd addd=(CountAdd) ob;//可以向下转型来获得子类特有的方法
CountAdd add=new CountAdd();
Object aa=Class.forName("CountAdd");
boolean bo=(add.getClass()==ob.getClass());//返回true,ob与addd指向相同的堆地址,与add指向的内容相同
System.out.println(bo);
haha(add.getClass());
haha(a);
haha(ob.getClass());
haha(addd.getClass());//四个返回的内容相同,这里复习了转型,可以不看
int in=a.getModifiers();
String str=Modifier.toString(in);
String str1=a.getSimpleName();
String str2=a.getName();
System.out.println(str);//public
System.out.println(in);//1,api里说明了排序依次是public protected private abstract static final transient volatile synchronized native strictfp interface
System.out.println(str1);//CountAdd 名称
System.out.println(str2);//CountAdd 全名(带路径)
Field fl=a.getDeclaredField("q");//访问特定属性
System.out.println(fl.getType().getSimpleName());//getType()返回class对象,但在这不用getSimpleName()也行
System.out.println(a);//如果直接输出class对象默认调用toString()
System.out.println(fl.getType());//getType()返回的class对象转化成字符串就是int,该对象的名称也是int
Class cla=fl.getType();
haha(cla);//结果为public abstract final class int ,为什么int类toString()得到的不是class int?也许和修饰符有关,同时为抽象和终态的特殊类,这样的类是创建不出的
System.out.println(fl.getName());//q属性的名称
}
}