反射总结
反射就是加载类,并解剖出类的各个组成部分。通俗的说反射就是通过一个文件来解析类。
一、要明白怎样加载类的方法,有三种:
1、Class.forName(""),如:Class.forName("com.mysql.jdbc.Driver")
2、对象.getClass()?如:?Student?st=new?Student();?st.getClass()
3、类名.class?如:?Student.Class;
Class对象提供了如下常用方法:
二、获取加载类中所有的构造器
Public??Constructor??getConstructor(Class<?>...?parameterTypes)?
Public??Method??getMethod(String?name,?Class<?>...?parameterTypes)?
Public??Field??getField(String?name)??
//以上三种可以解析?public类的构造器
//下面的三种方法是解析private类的构造器
public?Constructor?getDeclaredConstructor(Class...?parameterTypes)
public?Method?getDeclaredMethod(String?name,Class...?parameterTypes)
public?Field?getDeclaredField(String?name)
这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor、?Method?、?Field?对象表示。常用的是getConstructor()
三、创建类的实例
Constructor类提供了如下方法,用于创建类的对象
public?Object?newInstance(Object...?initargs),initargs用于指定构造函数接收的参数调用对象的方法
四、调用对象的方法
首先以Student类举例如下
(1)、三种加载类的方法
public?class?StudentTest?{
@Test
public?void?test()?throws?ClassNotFoundException?{
//?1、Class.forName("")加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
System.out.println(cls);
//?2、对象.getClass()加载类
Student?stu?=?new?Student();
Class?cls1?=?stu.getClass();
System.out.println(cls1);
//?3、类名.class?加载类
Class?cls2?=?Student.class;
System.out.println(Student.class);
}
(2)、举例反射类无参、有参、私有的构造函数,创建类的对象,案例如下:首先创建一个普通的Java类Student类,该类位于cn.csdn.reflect包中并编译产生相应的class文件.下面就是该类中各种构造器解剖的方式如下:
//?解析:public?Student()
@Test??//解析无参的构造函数
public?void?test1()?throws?ClassNotFoundException,?SecurityException,
NoSuchMethodException,?IllegalArgumentException,
InstantiationException,?IllegalAccessException,
InvocationTargetException?{
//?1、加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
//?2、通过无参数的构造器解析
Constructor?constructor?=?cls.getConstructor(null);
//?3、创建类的实例
Student?entity?=?(Student)?constructor.newInstance(null);
????????//4、调用对象的方法
entity.study();
//解析:public?Student(String?name,int?age);
@Test??//解析有参的构造函数
public?void?test2()throws?Exception{
//1、加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
//2、通过带有参数的构造器解析
Constructor?constructor?=?cls.getConstructor(String.class,int.class);
//3、创建类实例
Student?entity?=?(Student)constructor.newInstance("redarmy",90);
//4、调用方法
entity.study();
System.out.println(entity.getName());
}
//怎么知道?Student类中有哪些构造器
@Test
public?void?test3()throws?Exception{
//1、加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
//2、获取加载类中的所有的构造器
Constructor?csr[]?=?cls.getConstructors();
//3、遍历构造器csr
for(Constructor?c:csr){
//打印出构造器参数的类型及构造器名称
?System.out.println(c.toGenericString());
}
}
????//解析:public?cn.csdn.reflect.Student(java.lang.String[])
@Test
public?void?test4()throws?Exception{
//1、加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
//2、根据构造器参数类型获取相应的构造器对象????
Constructor?csr?=?cls.getConstructor(String[].class);
String?str[]={"111","123"};
//3、创建实体对象
Student?entity?=?(Student)csr.newInstance((Object)str);
//4、调用方法
entity.study();
}
@Test??//解析私有的构造方法
public?void?test5()throws?Exception{
//1、加载类
Class?cls?=?Class.forName("cn.csdn.reflect.Student");
//2、根据构造器参数类型获取相应的构造器对象????
Constructor?csr?=?cls.getDeclaredConstructor(List.class);
csr.setAccessible(true);//暴力
//3、创建实体对象
Student?entity?=?(Student)csr.newInstance(new?ArrayList());
//4、调用方法
entity.study();
}
}
多学一招:sun公司为简化开发人员创建对象,它在class对象中也提供了一个newInstance方法,用于创建类的对象。这样开发人员可以避免每次都需要去反射Constructor?类以创建对象。
不过需要注意的是:class.newInstance方法内部是反射类无参的构造函数创建的对象,所以利用此种方式创建类对象时,类必须有一个无参的构造函数。
<!--EndFragment-->