学网站建设语言资料管理系统
一.获取构造器对象
获取构造器对象我们有四种方法,其中带Constructor的获取单个构造器对象。而带Constructors的是获取构造器对象数组。带Declared的是无论构造器是否私有都能拿到该构造器对象,而不带Declared的方法无法获取到私有的构造器对象。
首先我们将要使用到的Cat对象定义出来:
package com.njau.d2_reflect;import com.sun.xml.internal.ws.api.ha.StickyFeature;public class Cat {private String name;private int age;private Cat(String name, int age) {System.out.println("有参构造器执行了!");this.name = name;this.age = age;}private Cat() {System.out.println("无参构造器执行了!");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +'}';}
}
接着我们使用上述四种方法获取构造器对象,在获取构造器对象的第一步,就是首先获取该类对象,因为构造器是类的一部分,只有获取到了该类对象,才能进一步获取该类的构造器对象。
Constructor<?>[] getConstructors() 获取全部的构造器(不包括private修饰的,只包括public修饰的)
Constructor<?>[] getDeclaredConstructors() 获取全部的构造器(包括private,public修饰的)
Constructor<?>[] getConstructor(Class<?>...parameterTypes) 获取某个构造器(不包括private修饰的,只包括public修饰的)
Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes) 获取某个构造器(包括private,public修饰的)
在获取某个构造器时,使用getDeclaredConstructor方法,其中()内有参数的获取有参构造器,没有参数的获取无参构造器。
package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Constructor;/*** 目标:获取类的构造器、并对其进行操作* Class提供了从类中获取构造器的方法* Constructor<?>[] getConstructors() 获取全部的构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructors() 获取全部的构造器(包括private,public修饰的)* Constructor<?>[] getConstructor(Class<?>...parameterTypes) 获取某个构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes) 获取某个构造器(包括private,public修饰的)* 获取类构造器的作用:依然是初始化对象返回* 获取类构造器的作用:依然是初始化对象返回* T newInstance(Object...initargs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)*/
public class Test2Constructor {@Testpublic void testGetConstructors() throws Exception {// 反射第一步:先得到类的Class对象Class c1 = Cat.class;System.out.println(c1.getName()); // com.njau.d2_reflect.Cat
// Constructor[] constructors = c1.getConstructors();Constructor[] constructors = c1.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());}}@Testpublic void testGetConstructor() throws Exception {Class c2 = Cat.class;
// Constructor constructor = c2.getConstructor();Constructor constructor = c2.getDeclaredConstructor();System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());// Constructor constructor1 = c2.getConstructor(String.class,int.class);Constructor constructor1 = c2.getDeclaredConstructor(String.class,int.class);System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());}
}
.class用来拿到当前的类型。携带Declared方法功能较为强大,因此我们在使用时要使用带Declared的方法。getName()和getParameterCount()用来拿到构造器名字和构造器参数个数。
二.获取类构造器的作用
Cat.java
package com.njau.d2_reflect;import com.sun.xml.internal.ws.api.ha.StickyFeature;public class Cat {private String name;private int age;private Cat(String name, int age) {System.out.println("有参构造器执行了!");this.name = name;this.age = age;}private Cat() {System.out.println("无参构造器执行了!");}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +'}';}
}
作用:初始化一个对象返回
在使用反射初始化对象时,我们首先获得了类的构造器对象。该构造器对象可以调用newInstance方法创建出一个类的实例化对象并返回。在该方法中传入参数即调用有参构造器,无参数则调用无参构造器。
package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Constructor;/*** 目标:获取类的构造器、并对其进行操作* Class提供了从类中获取构造器的方法* Constructor<?>[] getConstructors() 获取全部的构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructors() 获取全部的构造器(包括private,public修饰的)* Constructor<?>[] getConstructor(Class<?>...parameterTypes) 获取某个构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes) 获取某个构造器(包括private,public修饰的)* 获取类构造器的作用:依然是初始化对象返回* 获取类构造器的作用:依然是初始化对象返回* T newInstance(Object...initargs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)*/
public class Test2Constructor {@Testpublic void testGetConstructors() throws Exception {// 反射第一步:先得到类的Class对象Class c1 = Cat.class;System.out.println(c1.getName()); // com.njau.d2_reflect.Cat
// Constructor[] constructors = cat.getConstructors();Constructor[] constructors = c1.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());}// System.out.println(cat.getConstructor(String.class, int.class));}@Testpublic void testGetConstructor() throws Exception {Class c2 = Cat.class;
// Constructor constructor = c2.getConstructor();Constructor constructor = c2.getDeclaredConstructor();System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());// Constructor constructor1 = c2.getConstructor(String.class,int.class);Constructor constructor1 = c2.getDeclaredConstructor(String.class,int.class);System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());Cat cat1 = (Cat) constructor.newInstance(); // private修饰的,无法直接使用无参构造器进行初始化(Object对象,要进行强转)System.out.println(cat1); }
}
我们在刚才的无参构造器constructor的基础上调用newInstance方法来实例化对象。因为无参构造器constructor自己本身不知道自己是什么类型的,因此他声明出来的类实例化对象是Object类型的,因此要强转成Cat类型才行。
但当我们执行该代码时,发现报错。报错类型为
可以看到因为该无参构造器是私有的private修饰,因此并没有成功创建该类的实现类对象。要想解决这个问题,除了将该无参构造器改为公共的以外,还可以使用setAccessible()方法。
我们可以调用setAccessible方法设置为true,表示禁止检查访问控制,即使用暴力反射。这样的话即使是私有的构造方法也可以进行对象的实例化。
package com.njau.d2_reflect;import org.junit.Test;import java.lang.reflect.Constructor;/*** 目标:获取类的构造器、并对其进行操作* Class提供了从类中获取构造器的方法* Constructor<?>[] getConstructors() 获取全部的构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructors() 获取全部的构造器(包括private,public修饰的)* Constructor<?>[] getConstructor(Class<?>...parameterTypes) 获取某个构造器(不包括private修饰的,只包括public修饰的)* Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes) 获取某个构造器(包括private,public修饰的)* 获取类构造器的作用:依然是初始化对象返回* 获取类构造器的作用:依然是初始化对象返回* T newInstance(Object...initargs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)*/
public class Test2Constructor {@Testpublic void testGetConstructors() throws Exception {// 反射第一步:先得到类的Class对象Class c1 = Cat.class;System.out.println(c1.getName()); // com.njau.d2_reflect.Cat
// Constructor[] constructors = cat.getConstructors();Constructor[] constructors = c1.getDeclaredConstructors();for (Constructor constructor : constructors) {System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());}// System.out.println(cat.getConstructor(String.class, int.class));}@Testpublic void testGetConstructor() throws Exception {Class c2 = Cat.class;
// Constructor constructor = c2.getConstructor();Constructor constructor = c2.getDeclaredConstructor();System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());// Constructor constructor1 = c2.getConstructor(String.class,int.class);Constructor constructor1 = c2.getDeclaredConstructor(String.class,int.class);System.out.println(constructor1.getName() + "--->" + constructor1.getParameterCount());constructor.setAccessible(true); // 先设置为true,才能使用private修饰的无参构造器进行初始化对象Cat cat1 = (Cat) constructor.newInstance(); // private修饰的,无法直接使用无参构造器进行初始化(Object对象,要进行强转)System.out.println(cat1); // Cat{name='null', age=0}constructor1.setAccessible(true);Cat cat2 = (Cat) constructor1.newInstance("招财猫", 3);System.out.println(cat2);}
}