文章目录
- 前言
- 一、反射是什么?
- 二、访问构造方法
- 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);
//以字符串的形式获得该构造方法
总结
以上就是今天要讲的内容,本文仅仅简单介绍了访问构造方法的使用,而反射提供了大量能使我们快速便捷地处理数据的函数和方法,指正的内容欢迎在评论区中留言。