反射获取构造方法并使用1
Class类在java.lang包下。该类的泛型是
Class类的实例表示正在运行的Java应用程序中的类和接口
即在反射里面,把一个学生类里面的成员变量、构造方法、成员方法都看成一个个对象
该类的创建对象的方法有:
1、构造器<?>[] getConstructors() 返回一个包含构造器对象的数组,构造器对象反映了此类对象所表示的类的所有公共构造函数。即只获取学生类的公共构造方法
2、构造器<?>[] getDeclaredConstructors() 返回构造器对象的数组,构造器对象反映由此类对象表示的类声明的所有构造函数。即获取学生类的所有构造方法
3、构造器
上面的getConstructor和getDeclaredConstructor方法是有两个。第一个参数表示要获取的构造方法的个数。第二个参数表示数据类型对应的字节码文件对象,或者理解为.class文件对象
学习一下构造方法的类,即Constructor类
该类的泛型是
该类被final修饰,所以该类是最终类。该类继承自Executable类
该类的作用是提供了一个类的单个构造函数的信息和访问权限
该类的创建对象的方法有:
方法 | 作用 |
---|---|
T newInstance(Object... initargs | 使用此构造器对象表示的构造方法,使用指定的初始化参数创建和初始化构造函数声明类的新实例 |
总结: 使用反射来创建对象,有两个类可实现,如下
1、Class类中用于获取构造方法的方法有4个
xxxxxxxxxx
getConstructors()、getDeclaredConstructors()、getConstructor()、getDeclaredConstructor
2、Constructor类中用于创建对象的方法有1个
xxxxxxxxxx
newInstance()
反射获取构造方法并使用1的练习
xxxxxxxxxx
package ch27;
public class a_5_1Student {
//成员变量:私有、默认、公共
private String name;
int age;
public String address;
//公共构造方法,这里的这个也叫无参构造方法
public a_5_1Student() {
}
//私有构造方法
private a_5_1Student(String name) {
this.name = name;
}
//默认构造方法
a_5_1Student(String name, int age) {
this.name = name;
this.age = age;
}
//公共构造方法
public a_5_1Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//私有成员方法
private void function(){
System.out.println("function");
}
//4个公共成员方法
public void method1(){
System.out.println("method");
}
public void method2(String s){
System.out.println("method:"+s);
}
public String method3(String s,int i){
return s + "," + i;
}
//重写的toString方法也是公共成员方法
public String toString() {
return "a_4_1Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
xxxxxxxxxx
package ch27;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//先去看ch27的a_5_1,再来看这里,不然会乱
public class a_5_2测试 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//首先要获取学生类的Class对象
Class<?> c = Class.forName("ch27.a_5_1Student");//forName报红线,Alt+Enter,Add抛出异常
//------------------------------------------------------------------------------------------------------
//在Class类中的getConstructors方法来获取Student类中的构造方法
Constructor<?>[] cons = c.getConstructors();
//增强for遍历上面那行拿到的数组
for(Constructor con : cons){
System.out.println(con);//只能输出学生类里面的公共构造方法。私有和默认的构造方法无法获取
}
System.out.println("-------------------------------");
//------------------------------------------------------------------------------------------------------
//在Class类中的getDeclaredConstructors方法来获取Student类中的构造方法
Constructor<?>[] cons2 = c.getDeclaredConstructors();
//增强for遍历上面那行拿到的数组
for(Constructor con : cons2){
System.out.println(con);//输出学生类里面所有的构造方法,包括公共、私有、默认
}
System.out.println("-------------------------------");
//上面的全部代码是用Class类的方法来创建学生类的构造方法方法的对象-反射
//--------------------------------------------------------------------------------------------------------------
//下面的全部代码是用Constructor类的方法来创建学生类的构造方法方法的对象-反射
//上面的都是获取到学生类的构造方法的数组,如果只想获取到某一个构造方法呢,怎么获取,如下
//比如拿学生类里面的一个公共构造方法,注意这个公共构造方法我们在学生类里面写的是无参的
Constructor<?> con3 = c.getConstructor();//因为是无参公共构造方法,所以getConstructor方法不需要写参数。报红线,Alt+Enter,add抛出异常
//原理:通过最上面的类的字节码文件对象c,来得到上面那行的构造方法对象con3
//上面那行其实就相当于如下的代码,如下的代码是我们之前构造对象的写法,上面那行是使用反射来构造对象的写法
/*a_5_1Student s = new a_5_1Student();
System.out.println(s);*/
//反射来构造对象:通过Constructor构造方法里面的方法来创建对象,即11行+39行+46行,这三行就是一个完整的使用Constructor类来创建对象的过程操作
Object obj = con3.newInstance();//由于38行的c.getConstructor拿到的是学生类里面的无参公共构造方法的对象,所以这行也是无参的。报红线,Alt+Enter,add抛出异常
//原理:通过39行的构造方法对象con3,调用Constructor类里面的方法newInstance创建一个对象obj
System.out.println(obj);//注意要先在学生类里面重写toString方法
//上面那行的输出跟43行的一样,但是,上面那行是使用反射来构造对象,就是我们目前学的,43行的构造对象是以前学的
}
}
反射获取构造方法并使用2
练习1:通过反射实现如下操作,即使用反射来达到下面的效果 1、Student s = new Student("张三",18,"福建"); //带三个参数的构造方法,先在我们的学生类里面准备一个带3个参的公共构造方法 2、System.out.println(s);
基本数据类型也可以通过.class得到对应的class类型
反射获取构造方法并使用2的练习
xxxxxxxxxx
package ch27;
public class a_6_1Student {
//成员变量:私有、默认、公共
private String name;
int age;
public String address;
//公共构造方法,这里的这个也叫无参构造方法
public a_6_1Student() {
}
//私有构造方法
private a_6_1Student(String name) {
this.name = name;
}
//默认构造方法
a_6_1Student(String name, int age) {
this.name = name;
this.age = age;
}
//公共构造方法
public a_6_1Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//私有成员方法
private void function(){
System.out.println("function");
}
//4个公共成员方法
public void method1(){
System.out.println("method");
}
public void method2(String s){
System.out.println("method:"+s);
}
public String method3(String s,int i){
return s + "," + i;
}
//重写的toString方法也是公共成员方法
public String toString() {
return "a_4_1Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
xxxxxxxxxx
package ch27;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class a_6_2测试 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取学生类的Class对象
Class<?> c = Class.forName("ch27.a_6_1Student");
//public a_6_1Student(String name, int age, String address) 在学生类里面写好的
//分析:我们要获取单个构造方法,并且是公共的,即要使用上节课讲的Class类的getConstructor方法,如下
Constructor<?> con = c.getConstructor(String.class, int.class, String.class);//con是构造方法对象
//上面那行说明:基本数据类型也可以通过.class得到对应的class类型
//使用上面那行的构造方法对象con调用Constructor类里面的方法来创建学生类的对象
//分析:要使用上节课将的Constructor类的newInstance()。下面那行的newInstance()里面的数据要和14行的数据类型相对应
Object obj = con.newInstance("张三", 18, "厦门");
System.out.println(obj);//输出a_4_1Student{name='张三', age=18, address='厦门'}
//上面那些代码就是基本的流程,使用反射来创建学生类里面的构造方法的对象
//上面那些代码的操作相当于如下的操作。虽然上面的操作比较麻烦,但是学好反射对以后的学习很有帮助
Object obj2 = con.newInstance("张三", 18, "厦门");
System.out.println(obj2);
}
}
反射获取构造方法并使用3
练习2:通过反射实现如下操作 1、Student s = new Student("张三"); 2、System.out.println(s);
如何获取只有一个参数的私有构造方法的对象,写法:暴力反射 void setAccessible(boolean flag) 将此反射对象的accessible标志设置为指示的布尔值。当值为true,取消访问检查
反射获取构造方法并使用3的练习
xxxxxxxxxx
package ch27;
public class a_7_1Student {
//成员变量:私有、默认、公共
private String name;
int age;
public String address;
//公共构造方法,这里的这个也叫无参构造方法
public a_7_1Student() {
}
//私有构造方法
private a_7_1Student(String name) {
this.name = name;
}
//默认构造方法
a_7_1Student(String name, int age) {
this.name = name;
this.age = age;
}
//公共构造方法
public a_7_1Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//私有成员方法
private void function(){
System.out.println("function");
}
//4个公共成员方法
public void method1(){
System.out.println("method");
}
public void method2(String s){
System.out.println("method:"+s);
}
public String method3(String s,int i){
return s + "," + i;
}
//重写的toString方法也是公共成员方法
public String toString() {
return "a_4_1Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
xxxxxxxxxx
package ch27;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class a_7_2测试 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取学生类的Class对象
Class<?> c = Class.forName("ch27.a_7_1Student");
//如何获取一个参数的构造方法的对象
//在我们的学生类里面有一个私有构造方法是只有一个参数的,那如何获取只有一个参数的私有构造方法的对象,如下
//构造器<T> getDeclaredConstructor(类<?>... parameterTypes) 返回一个构造器对象,
//该对象反映此类对象所表示的类或接口的指定构造函数。即获取学生类的所有构造方法中的某个
Constructor<?> con = c.getDeclaredConstructor(String.class);//得到带一个String参数的构造方法对象,con
//解决下面的24行的报错:使用暴力反射即可
//Class类里面有一个方法:void setAccessible(boolean flag) 将此反射对象的accessible标志设置为指示的布尔值
con.setAccessible(true);
//生成对象
Object obj = con.newInstance("张三");
System.out.println(obj);
//控制台报错IllegalAccessException,因为学生类里面的这个构造方法是private私有的,即无法通过私有的构造方法创建对象
//在这里的上面使用暴力反射即可解决
//25行输出:a_4_1Student{name='张三', age=0, address='null'}
}
}