反射
一、 Class类的使用
法一:知道类,创建类实例
Class c1=Foo.class;
Class c2=int.lass
Class c3=double.class;
法二:知道对象,创建类实例
Food foo=new Food();
Class c2=foo.getClass();
类也是对象,Class类的实例对象,类的类类型
法三:知道String,创建类实例
Class c3=Class.forName(“com.lrq.entity”);
//通过类的类型创建该类的对象实例
Food food=(Food)c3. newInstance();
二、 Class类的动态加载
Ø Class c=Class.forName(args[0]);
Ø OfficeAble oa=(OfficeAble)c.newInstance();
Ø oa.start();
Ø 将OfficeAble作为一个接口
1.创建OfficeBetter类:
2.创建OfficeAble类:
3.创建Word实现OfficeAble接口:
编译与运行:(先将OfficeBetter,OfficeAble,Word编译成字节码,最后输入类名执行)
三、 获取方法信息
public classClassUtil1 {
/**
* 1.输入类对象,打印出对象的类名
* 2.打印出对象的方法名
* 3.打印出对象的返回值类型
* 4.打印出对象的参数列表
* @param o
*/
public static void showClassMessage(Objecto){
Class c1=o.getClass();
System.out.PRintln("类的对象名:"+c1.getName());
System.out.println("================================");
Method[] methods=c1.getMethods();
for (Method m:methods){
System.out.println("类的方法名:"+m.getName());
System.out.println("类的返回值类型:"+m.getReturnType());
Class[]paramType=m.getParameterTypes();
for (Class p:paramType){
System.out.print("类的参数列表:"+p.getName()+"/n");
}
System.out.println("==================================");
}
}
}
四、 获取成员变量,构造函数信息
成员变量:
/**
* 成员变量也是对象
* java.lang.reflect.Fields
* 封装了关于成员变量的操作
*getFields()方法获取的是所有public的成员变量的信息
* getDeclaredFields获取是该类自己声明成员变量的信息
*/
/*Field[] fields=c.getFields();*/
Field[] fields=c.getDeclaredFields();
for(Field fs:fields){
//得到成员变量的类类型
Class fieldType=fs.getType();
Stringtypename=fieldType.getName();
//得到成员变量的名称
String fieldName=fs.getName();
System.out.println(typename+":"+fieldName);
}
构造函数信息:
/**
* 打印构造函数信息
*/
public static void printConmessage(Objecto){
Class c=o.getClass();
/**
* 构造函数也是对象
* java.lang.Constryctor中封装了构造函数信息
* getConstructors获取所有public的构造函数
* getDeclaredConstructors得到所有构造函数
*
*/
//获取所有构造函数
Constructor[]con=c.getDeclaredConstructors();
for(Constructor co:con){
//构造函数名
System.out.print(co.getName()+"(");
//构造函数参数列表----》获取参数列表类类型
Class[]paramTypes=co.getParameterTypes();
for(Class p:paramTypes){
System.out.print(p.getName()+",");
}
System.out.println(")");
}
}
五、 方法反射(Class,Method,invoke)
public classMethodReflect {
public static void main(String[] args) {
A a1=new A();
Class c=a1.getClass();
//指定方法:方法名+参数列表
try {
Methodm=c.getMethod("print",int.class,int.class);
/*Object o=m.invoke(a1,newObject[]{10,20});*/
Object o=m.invoke(a1,10,20);
Methodm1=c.getMethod("print",String.class,String.class);
o=m1.invoke(a1,"hi","man");
Methodm2=c.getMethod("print");
m2.invoke(a1);
} catch (Exception e) {
e.printStackTrace();
}
}
==================================================
static class A{
public void print(){
System.out.println("Hi,Man");
}
public void print(int a,int b){
System.out.println(a+b);
}
public void print(String a,String b){
System.out.println(a.toUpperCase()+b.toLowerCase());
}
}
}
六、 了解集合泛型的本质
1. Java的泛型只在编译阶段有效,目的是为了错误类型输入
2. 编译之后去泛型化,可以通过反射来绕过编译
public classMethodDemo {
public static void main(String[] args) {
ArrayList list=new ArrayList();
ArrayList<String> list1=newArrayList<String>();
list1.add("hello");
Class c1=list.getClass();
Class c2=list1.getClass();
System.out.println(c1==c2);
//反射的操作均是编译之后操作
/**
* c1==c2结果返回true说明编译之后集合的泛型是去泛型化的
*Java中集合的泛型,是防止错误输入的,只在编译阶段有效
* 绕过编译无效
* 验证:我们可以通过方法的反射来操作,绕过编译
*/
try {
Methodm=c2.getMethod("add", Object.class);
m.invoke(list1,20);//绕过编译操作就绕过了泛型
System.out.println(list1.size());
System.out.println(list1);
System.out.println(list==list1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
新闻热点
疑难解答