感觉:Class类是个头,得到Class类对象,然后得到Employee类对象(基于默认的无参构造);(这是Java反射二:反射的核心类:Class类中的内容)
根据Class类对象,得到Constructor构造方法类对象,然后根据Constructor类对象可以得到Employee对象(基于带参构造方法);(这是本篇博客的内容)
目录
(3)NoSuchMethodException异常举例:感受下,NoSuchMethodException异常的触发时机。
反射的核心类:有四个。本篇博客主要介绍Constructor构造方法类。
构造方法:java类中必须要存在的一个方法,作用是对象被创建以后,对这个对象进行初始化操作。
1.Constructor构造方法类简介
通过Constructor对象可以得到具体构造方法有几个参数,参数的类型是什么。也可以通过Constructor对象调用带参构造方法。
Constructor类核心方法:
说明:
(以Employee类为例)
(1)通过类对象(Java反射二:反射的核心类:Class类这篇博客中介绍的Class对象啦)的getConstructor()方法获取(Employee类中的)由public修饰的Constructor构造方法对象(就是Constructor对象);
(2)上一步获取了Constructor对象,,,然后调用Constructor对象的newInstance()方法调用带参构造方法,创建对应类的对象;
Class对象的newInstance()方法是通过调用默认构造方法(就是无参构造方法啦)创建新的对象;
如果想通过类的带参构造创建对象,就需要先通过【classObj.getConstructor()】获取到Constructor构造方法对象,然后调用Constructor对象的newInstance()方法;
2.案例:
(1)具体代码
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一下,这个异常就在这儿被捕捉了。(这个异常不常用了,知道就行)
(2)运行结果
(3)NoSuchMethodException异常举例:感受下,NoSuchMethodException异常的触发时机。