反照总结
反射就是加载类,并解剖出类的各个组成部分。通俗的说反射就是通过一个文件来解析类。
一、要明白怎样加载类的方法,有三种:
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.****.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.****.reflect包中并编译产生相应的class文件.下面就是该类中各种构造器解剖的方式如下:
// 解析:public Student()
@Test //解析无参的构造函数
public void test1() throws ClassNotFoundException, SecurityException,
NoSuchMethodException, IllegalArgumentException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
// 1、加载类
Class cls = Class.forName("cn.****.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.****.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.****.reflect.Student");
//2、获取加载类中的所有的构造器
Constructor csr[] = cls.getConstructors();
//3、遍历构造器csr
for(Constructor c:csr){
//打印出构造器参数的类型及构造器名称
System.out.println(c.toGenericString());
}
}
//解析:public cn.****.reflect.Student(java.lang.String[])
@Test
public void test4()throws Exception{
//1、加载类
Class cls = Class.forName("cn.****.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.****.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方法内部是反射类无参的构造函数创建的对象,所以利用此种方式创建类对象时,类必须有一个无参的构造函数。