Java反射机制提供了另外一种创建对象方法,Class类提供了一个实例方法newInstance(),通过该方法 可以创建对象,使用起来比较简单,下面两条语句实现了创建字符串String对象。
Class clz = Class.forName("java.lang.String"); String str = (String) clz.newInstance();
这两条语句相当于String str = new String()语句。
注意:意newInstance()方法有可以会抛出 InstantiationException和IllegalAccessException异常,InstantiationException不能实例化异常, IllegalAccessException是不能访问构造方法异常。
一、调用构造方法
调用方法newInstance()创建对象,这个过程中需要调用构造方法,上面的代码只是调用了String的默认 构造方法。如果想要调用非默认构造方法,需要使用Constructor对象,它对应着一个构造方法,获得 Constructor对象需要使用Class类的如下方法:
Constructor[] getConstructors():返回所有公有构造方法Constructor对象数组
Constructor[] getDeclaredConstructors():返回所有构造方法Constructor对象数组。
Constructor getConstructor(Class… parameterTypes):根据参数列表返回一个共有
Constructor对 象。参数parameterTypes是Class数组,指定构造方法的参数列表。
Constructor getDeclaredConstructor(Class… parameterTypes):根据参数列表返回一个Constructor对 象。参数parameterTypes同上。
示例代码如下:
public class HelloWorld { public static void main(String[] args) { try { Class clz = Class.forName("java.lang.String"); // 使用String的默认的构造方法public String() String str1 = (String) clz.newInstance(); System.out.println(str1); // 1.设置构造方法参数类型 Class[] params = new Class[1]; // 第一个参数是String params[0] = String.class; // 2.获取与参数对应的构造方法 Constructor constructor = clz.getConstructor(params); // 3.为构造方法传递参数 Object[] argObjs = new Object[1]; // 第一个参数传递Hello argObjs[0] = "Hello"; // 4.调用非默认构造方法,构造方法第一个参数是String类型 String str2 = (String) constructor.newInstance(argObjs); System.out.println(str2); } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
Hello
二、案例:依赖注入实现
Java反射机制能够在运行时动态加载类,而不是在编译期。在一些框架开发中经常将要实例化的类名 保存到配置文件中,在运行时从配置文件中读取类名字符串,然后动态创建对象,建立依赖关系 1 。采 用new创建对象依赖关系是在编译期建立的,反射机制能够将依赖关系推迟到运行时建立,这种依赖 关系动态注入进来称为依赖注入。
例如:如图所示有三个类,Student和Worker继承自Person,在HelloWorld类的main()方法中会创建 Person子类实例,至于依赖哪一个类,Student还是Worker,可以在运行时从配置文件中读取,然后创 建对象。
Person类:
public class Person { public String name; public int age; public Person(String name,int age){ this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
worker类:
public class Worker extends Person{ public String factory; public Worker(String name, int age,String factory) { super(name, age); this.factory = factory; } public void setFactory(String factory) { this.factory = factory; } public String getFactory() { return factory; } @Override public String toString() { return "Worker{" + "name='" + name + '\'' + ", age=" + age + ", factory='" + factory + '\'' + '}'; } }
Student类:
public class Student extends Person{ public String school; public Student(String name, int age,String school) { super(name, age); this.school = school; } public void setSchool(String school) { this.school = school; } public String getSchool() { return school; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", school='" + school + '\'' + '}'; } }
写完这三个类之后,在IDEA项目根目录建一个文本文件Configuration.ini,内容如下:
Java反射机制.创建对象.依赖注入实现案例.Student
调用代码如下:
import java.io.*; import java.lang.reflect.Constructor; /** * @author : 蔡政洁 * @email :caizhengjie888@icloud.com * @date : 2020/2/27 * @time : 6:42 下午 */ public class HelloWorld { public static void main(String[] args) { try{ // 通过调用readClassName()方法从Configuration.ini文件中读取类名 String classname = readClassName(); // 通过从配置文件Configuration.ini中读取的字符串创建Class对象 Class clz = Class.forName(classname); // 1.指定参数类型 Class[] params = new Class[3]; // 第一个参数是String params[0] = String.class; // 第二个参数是int params[1] = int.class; // 第三个参数是String params[2] = String.class; // 2.获得对应参数的构造方法 Constructor constructor = clz.getConstructor(params); // 3.设置传递参数 Object[] argObjs = new Object[3]; // 第一个参数传递Tony argObjs[0] = "Tony"; // 第二个参数传递21 argObjs[1] = 21; // 第三个参数传递北京大学 argObjs[2] = "北京大学"; // 4.采用非默认构造方法 Object p = constructor.newInstance(argObjs); System.out.println(p); } catch (Exception e) { e.printStackTrace(); } } // 从Configuration.ini文件中读取类名 public static String readClassName(){ FileInputStream readfile = null; InputStreamReader ir = null; BufferedReader in = null; try { readfile = new FileInputStream("Configuration.ini"); ir = new InputStreamReader(readfile); in = new BufferedReader(ir); // 读取文件中的一行数据 String str = in.readLine(); return str; } catch (FileNotFoundException e) { System.out.println("处理FileNotFoundException"); e.printStackTrace(); } catch (IOException e) { System.out.println("处理IOException"); e.printStackTrace(); } return null; } }
运行结果:
Student{name='Tony', age=21, school='北京大学'}