文章目录
- 前言
- 一、反射是什么?
- 二、访问构造方法
- 1.Constructor对象的获取方法
- 2.Constructor方法的使用
- 总结
前言
Java的反射机制可以实现访问、检测和修改Java对象本身信息的功能,在java.lang.reflect包下提供此功能。可以使程序员更加深入地控制程序的运行过程。可以理解为随时调用某个类的某个构造方法,成员方法,属性。
一、反射是什么?
Java反射是指在运行时(Runtime)动态获取和操作一个类的信息的能力。通过Java反射,可以在运行时获取类的属性、方法、构造函数等信息,并且可以动态调用这些属性和方法。
Java反射允许程序在运行时动态加载、探知和使用编译时未知的类,对象,方法等,可以实现动态生成对象,动态调用方法,动态修改属性等功能。使用Java反射,可以实现一些框架和库的功能,例如Spring框架中的依赖注入、Hibernate框架中的ORM映射等。
二、访问构造方法
Constructor类就是java反射机制的java.lang包下的具体方法。
使用Constructor对象可以访问相应的构造方法。获取Constructor对象需要使用以下的方法,返回Constructor类型的对象或数组。
1.Constructor对象的获取方法
方法 | 功能描述 |
getConstructors() | 获取所有公有的构造方法 |
getConstructor(Class<?>...parameterTypes) | 获取对应的公有的构造方法 |
getDeclaredConstructors() | 获取所有的构造方法 |
getDeclaredConstructor(Class<?>...parameterTypes) | 获取指定的构造方法(无论是否私有) |
获取所有的构造方法,具体的一个例子,想要使用Constructor对象随时调用某类的构造方法,先实例化一个该类的对象,然后使用getClass()方法将该对象包装为原始类型Class,最后使用以上的方法获取所有的构造方法。
实操展示:
Example example = new Example();
Class<? extends Example> exampleClass =example.getClass();
Constructor constructor[] = exampleClass.getDeclaredConstructors();
//该constructor数组获取了example类的全部构造方法
获取指定的构造方法,操作与以上步骤一致,唯一不同点在getDeclaredConstructor()的括号中填入 数据类型.Class
实操展示:
Example example = new Example();
Class<? extends Example> exampleClass =example.getClass();
Constructor constructor =
exampleClass.getDeclaredConstructor(String.class,int.class,int.class);
//该constructor对象操纵的构造方法数据类型为 String,int,int
或者为:
Example example = new Example();
Class<? extends Example> exampleClass =example.getClass();
Constructor constructor =
exampleClass.getDeclaredConstructor(new Class{}[String.class,int.class,int.class]);
//该constructor对象操纵的构造方法数据类型为 String,int,int
2.Constructor方法的使用
方法 | 功能描述 |
isVarArgs() | 查看该构造方法是否允许带有可变数量的参数,如果允许返回ture,否则返回false |
getParameterTypes() | 按照声明顺序以Class数组的形式获取该构造方法的各个参数的类型 |
getExceptionTypes() | 以Class数组的形式获取该构造方法可能抛出的异常 |
newInstance(Object...initarges) | 通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法 |
setAccessible(boolean flag) | 如果该构造方法的权限为private,flag值为ture的话,可以无视该权限 |
getModifiers() | 获取可以解析出该构造方法所采用修饰符的整数(private=0,protected=1,public=2) |
实操展示:
原想调用的方法:
public class Example {
String name=null;
int age=0;
int id=0;
public Example(){}
@SuppressWarnings("unused")
private Example(int id){
this.id=id;
}
public Example(String name,int age,int id){
this.name=name;
this.age=age;
this.id=id;
}
public Example(String...strings){
if(strings.length>0){
this.name=strings[0];
}
if(strings.length>1){
this.age=Integer.valueOf(strings[1]);
}
if(strings.length>2){
this.id=Integer.valueOf(strings[2]);
}
}
public void input(){
System.out.println("姓名:"+name+" 年龄:"+age+" id="+id);
}
}
该Example类有四个构造方法,将在下面的Demo类中,使用Constructor类的常用方法,逐一调用,并输出各个构造方法的信息。
import java.lang.reflect.Constructor;
public class Demo{
public static void main(String[] args) {
Example person = new Example("张三", 18,101);
Class<? extends Example> personC =person.getClass();
@SuppressWarnings("rawtypes")
Constructor[] declaredConstructors = personC.getDeclaredConstructors();
for(int i=0;i<declaredConstructors.length;i++){
Constructor<?> constructor = declaredConstructors[i];
System.out.println("该类的名称:"+constructor.getName());
//获取该构造方法的名称
System.out.println("查看是否允许带有可变数量的参数:"+constructor.isVarArgs());
//获取该构造方法的参数是否为可变的
System.out.println("该构造方法的参数类型依次为:");
@SuppressWarnings("rawtypes")
Class type[]=constructor.getParameterTypes();
if(type.length==0){
System.out.println("该构造方法是无参的");
}
for(int j=0;j<type.length;j++){
System.out.println(type[j]);
}
//获取该构造方法的参数类型
System.out.println("该构造方法可能抛出的异常类型:");
@SuppressWarnings("rawtypes")
Class excpetion[]= constructor.getExceptionTypes();
if(excpetion.length==0){
System.out.println("无");
}
for(int j=0;j<excpetion.length;j++){
System.out.println(excpetion[j]);
}
//获取该构造方法可能抛出的异常类型
Example example =null;
while (example==null) {
try {
if (i==0) {
Object contect[] = new Object[]{new String[]{"王五","30","104"}};
example=(Example)constructor.newInstance(contect); //此方法所填值为object对象,newInstance方法不接受原始类型,例如String,需要封装成Object类
}else if(i==1){
example=(Example)constructor.newInstance("李四",20,102);
}else if(i==2){
example=(Example)constructor.newInstance(103);
}else if (i==3) {
example=(Example)constructor.newInstance();
}
//实例化各个构造方法
} catch (ClassCastException e) {
e.printStackTrace();
} catch (Exception e){
//如果创建对象时异常,方法为私有,运行以下方法
constructor.setAccessible(true);
e.printStackTrace();
}
}
if (example!=null) {
example.input();
}
System.out.println("-------------------------------------");
}
}
}
运行结果:
如上图当我们创建好一个该类的对象后,再转换为Constructor对象,就可以随时使用调用其newInstance()方法调用该类的构造方法,在代码运行的过程中实现动态调整数值。
补充:
静态方法 | 功能描述 |
isPublic(int mod) | 查看是否被public修饰符修饰,如果是则返回true,否则返回false |
isProtected(int mod) | 查看是否被protected修饰符修饰,如果是则返回true,否则返回false |
isPrivate(int mod) | 查看是否被private修饰符修饰,如果是则返回true,否则返回false |
isStatic(int mod) | 查看是否被static修饰符修饰,如果是则返回true,否则返回false |
isFinal(int mod) | 查看是否被final修饰符修饰,如果是则返回true,否则返回false |
toString(int mod) | 以字符串的形式返回所有修饰符 |
举个例子说明如何使用。例子:判断contructor对象所代表的构造方法是否被final修饰符修饰,以及以字符串的形式获得该构造方法的所有修饰符的常写代码如下:
int modifiers = constructor.getModifiers();
//获取该constructor对象的构造方法的限制符整数值
boolean isEmbellishByPrivate = Modifier.isFinal(modifiers);
//是否被final修饰符修饰
String embellishment = Modifier.toString(modifiers);
//以字符串的形式获得该构造方法
总结
以上就是今天要讲的内容,本文仅仅简单介绍了访问构造方法的使用,而反射提供了大量能使我们快速便捷地处理数据的函数和方法,指正的内容欢迎在评论区中留言。