感觉:Class类是个头,得到Class类对象,然后得到Employee类对象(基于默认的无参构造);(这是Java反射二:反射的核心类:Class类中的内容)
根据Class类对象,得到Constructor构造方法类对象,然后根据Constructor类对象可以得到Employee对象(基于带参构造方法);(这是本篇博客的内容)
目录
1.Constructor构造方法类简介
2.案例:
(1)具体代码
(2)运行结果
(3)NoSuchMethodException异常举例:感受下,NoSuchMethodException异常的触发时机。
反射的核心类:有四个。本篇博客主要介绍Constructor构造方法类。
构造方法:java类中必须要存在的一个方法,作用是对象被创建以后,对这个对象进行初始化操作。
通过Constructor对象可以得到具体构造方法有几个参数,参数的类型是什么。也可以通过Constructor对象调用带参构造方法。
Constructor类核心方法:
说明:
(以Employee类为例)
(1)通过类对象(Java反射二:反射的核心类:Class类这篇博客中介绍的Class对象啦)的getConstructor()方法获取(Employee类中的)由public修饰的Constructor构造方法对象(就是Constructor对象);
(2)上一步获取了Constructor对象,,,然后调用Constructor对象的newInstance()方法调用带参构造方法,创建对应类的对象;
Class对象的newInstance()方法是通过调用默认构造方法(就是无参构造方法啦)创建新的对象;
如果想通过类的带参构造创建对象,就需要先通过【classObj.getConstructor()】获取到Constructor构造方法对象,然后调用Constructor对象的newInstance()方法;
Employee类:
package com.imooc.reflect.entity; public class Employee { static { System.out.println("Employee的初始化静态代码块,只有Employee类被" + "加载的时候,这个代码块才会执行性。"); } private Integer eno; private String ename; private Float salary; private String dname; public Employee() { System.out.println("Employee的默认构造方法。"); } public Employee(Integer eno, String ename, Float salary, String dname) { this.eno = eno; this.ename = ename; this.salary = salary; this.dname = dname; System.out.println("Employee的带参构造方法。"); } public Integer getEno() { return eno; } public void setEno(Integer eno) { this.eno = eno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Float getSalary() { return salary; } public void setSalary(Float salary) { this.salary = salary; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } /** * 为了方便观看,Employee对象的四个属性的值,,这儿重写了toString()方法 * @return */ @Override public String toString() { return "Employee{" + "eno=" + eno + ", ename='" + ename + '\'' + ", salary=" + salary + ", dname='" + dname + '\'' + '}'; } }
Employee类几点说明:
(1)为了演示,增加了一个带参构造;
(2)为了方便查看Employee类对象的属性值,重写了toString()方法;
……………………………………………………
ConstructorSample类:
package com.imooc.reflect; import com.imooc.reflect.entity.Employee; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ConstructorSample { public static void main(String[] args) { try { Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee"); Constructor constructor = employeeClass.getConstructor(new Class[]{ //会抛出NoSuchMethodException异常 Integer.class,String.class,Float.class,String.class }); // newInstance()方法返回值类型是Object,所以需要强转。 //会抛出IllegalAccessException,InstantiationException,InvocationTargetException Employee employee = (Employee) constructor.newInstance(new Object[]{ 23,"张三",3000f,"研发部" }); System.out.println(employee); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { // 非法访问异常;比如在程序外侧访问程序内部私有方法,或者访问作用域外方法的时候,就会抛出这个异常; e.printStackTrace(); } catch (InstantiationException e) { //实例化异常;对象无法被实例化的时候会抛出这个异常;比如类是抽象的,就无法被实例化; e.printStackTrace(); } catch (InvocationTargetException e) { //目标调用异常;当被调用的方法内部抛出异常,而在外侧没有被捕获的时候,就会抛出这个异常。。。然后这个异常就在这儿被捕捉了。 e.printStackTrace(); } } }
ConstructorSample说明:
(1)classObj.getConstructor():用于获取指定格式的带参构造方法。
问题:在类中又是不单只有一个带参构造,其可以有多个不同的带参构造,如何进行区分和选择呐?
答案:getConstructor()在传入的参数中,增加了一个数据类型是Class类型的数组,在这个数组中描述构造方法参数的数量以及对应的类型;通过这些就能确定使用哪个带参构造了;
如案例中的:【employeeClass.getConstructor(new Class[]{ Integer.class,String.class,Float.class,String.class });】
(2)constructorObj.newInstance():Constructor对象的newInstance()方法仅用来通过类的带参构造创建对象;
这个方法需要一个数据类型是Object类型的数组,作为实例化对象的实参;
【constructor.newInstance(new Object[]{ 23,"张三",3000f,"研发部" });】
(3)异常信息:
一个以前没接触过的异常:【InvocationTargetException】:目标调用异常;当被调用的方法内部抛出异常,而在外侧(调用处)没有被捕获的时候,就会抛出这个异常。。。然后,这儿catch一下,这个异常就在这儿被捕捉了。(这个异常不常用了,知道就行)