Java 反射有以下3个动态特性
反射机制允许 Java 程序加载一个运行时才得知其名称的类,获悉其完整 API 信息,包括修饰符(诸如 public、static 等)、超类、实现的接口,也包括属性和方法的所有信息;
并可生成其实例、对其属性赋值或调用其方法。
通过 Java 反射可以实现一下功能。
Java 程序中获得 Class 实例通常有三种方式。
调用类或接口实例的 getClass() 方法
Class clz = obj.getClass(); //obj为某个类型的实例
调用类或接口的 class 属性。
Class clz = Student.class;//Student 为自定义的学生类型
使用 Class.forName() 方法。
Class clz = Class.forName("com.mysql.cj.jdbc.Driver")
方法 | 说明 |
---|---|
String getName() | 以字符串形式返回该类型的名称 |
String getSimpleName() | 以字符串形式返回该类型的简称 |
Package getPackage() | 获取该类型所在的包 |
Class getSuperclass() | 返回该类型的超类的 Class 实例 |
Class [] getInterfaces() | 返回该类型所实现的全部接口的 Class 实例 |
int getModifiers() | 返回该类型的所有修饰符,由访问修饰符对应的 int 常量组成 |
Class [] getDeclaredClasses() | 返回该类型中包含的全部类的Class 实例 |
Class getDeclaringClass() | 返回该类型所在的外部类的 Class 实例 |
public class BaseClass {
}
public final class Person extends BaseClass implements java.io.Serializable{
private String name;
static final int age=30;
protected String address;
public String message;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, String address, String message) {
this.name = name;
this.address = address;
this.message = message;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", message='" + message + '\'' +
'}';
}
private void silentMethod() throws IOException,NullPointerException {
System.out.println("这是悄悄话");
}
}
public class Test {
public static void main(String[] args) {
Class c1= Person.class;
String fullName=c1.getName();
String simpleName=c1.getSimpleName();
System.out.println("以下是"+fullName+"类的基本信息");
System.out.println("--------------------------------");
//获取 Person 类所在的包
Package pkg=c1.getPackage();
System.out.println(simpleName+"定义在"+pkg.getName()+"包中");
System.out.println("--------------------------------");
//获得 c1 所表示的实体(类、接口、基本类型或void)的父类的 Class
//如果 c1 表示 Object 类、一个接口、一个基本类型或 void,则返回 null
//如果 c1 表示一个数组类,则返回表示 Object 类的 Class 实例
Class superClass = c1.getSuperclass();
System.out.println(simpleName+"类的父类是"+superClass.getName());
System.out.println("--------------------------------");
//获得 c1 所表示的类实现的接口
//如果 c1 表示一个不实现任何接口的类或接口,则此方法返回一个长度为 0 的数组
//如果 c1 表示一个基本类型或 void,则此方法返回一个长度为 0 的数组
Class [] interfaces=c1.getInterfaces();
System.out.println(simpleName+"类所实现的接口:");
for (Class anInterface : interfaces) {
System.out.println("\t"+anInterface.getName());
}
System.out.println("--------------------------------");
//每个修饰符对应一个 int 常量,返回的修饰符信息将类所拥有的修饰符以"或"运算组合
//通过与 Modifier 类中的常量进行"与"运算即可判断该类型是否拥有某个修饰符
int modifier =c1.getModifiers();
System.out.println(simpleName+"类的修饰符:");
if((modifier& Modifier.PUBLIC)==Modifier.PUBLIC){
System.out.println("\t访问修饰符是:PUBLIC");
}else{
System.out.println("\t访问修饰符是:default(package)");
}
if((modifier& Modifier.FINAL)==Modifier.FINAL){
System.out.println("\t这个类是final的");
}
if((modifier& Modifier.ABSTRACT)==Modifier.ABSTRACT){
System.out.println("\t这个类是一个抽象类");
}
if((modifier& Modifier.INTERFACE)==Modifier.INTERFACE){
System.out.println("\t这是一个接口");
}
}
}
方法 | 说明 |
---|---|
Constructor getConstructor(Class params) | 返回该类型指定参数列表的 public 构造方法,构造方法的参数列表与 params 所指定的类型列表匹配 |
Constructor [] getConstructors() | 返回该类型的所有 public 构造方法 |
Constructor getDeclaredConstructor(Class oarams) | 返回该类型的指定参数列表的构造方法,访问级别不限 |
Constructor [] getDeclaredConstructors() | 返回该类型的所有构造方法 访问级别不限 |
public class Test {
public static void main(String[] args) throws NoSuchMethodException {
Class c1= Person.class;
//获取 Person 类声明的所有构造方法
//它们是公共、保护、默认(包)访问和私有构造方法
//如果此 Class 实例标识一个接口、一个基本类型、一个数组类或 void
//获取所有用 public 修饰符修饰的构造函数
Constructor[] constructors1 = c1.getConstructors();
//获取所有的构造函数 没有修饰符限制
Constructor[] constructors2 = c1.getDeclaredConstructors();
//根据给的参数类型 找到相对应的 使用 public 修饰的构造函数
Constructor constructor3 = c1.getConstructor(String.class);
//根据给的参数类型找到相对应的构造函数 没有访问修饰符限制
Constructor constructor4 = c1.getDeclaredConstructor(String.class);
System.out.println("===============构造方法展示===============");
for (Constructor constructor : constructors2) {
System.out.println("访问修饰符:");
//获取访问修饰符对应的常量
int modifier=constructor.getModifiers();
if((modifier& Modifier.PUBLIC)==Modifier.PUBLIC){
System.out.println("PUBLIC");
}else if((modifier& Modifier.PRIVATE)==Modifier.PRIVATE){
System.out.println("PRIVATE");
}else if((modifier& Modifier.PROTECTED)==Modifier.PROTECTED){
System.out.println("PROTECTED");
}else{
System.out.println("default(package)");
}
//获取构造方法的参数列表
Class [] parameter =constructor.getParameterTypes();
if(parameter.length==0){
System.out.println("该构造方法没有参数");
}else{
System.out.print("该构造方法的参数有:[");
for (int i = 0; i < parameter.length; i++) {
if(i!=0){
System.out.print(", ");
}
System.out.print(parameter[i].getSimpleName());
}
System.out.println("]");
}
System.out.println("---------------------------------");
}
}
}
方法 | 说明 |
---|---|
Field getField(String name) | 返回该类型中指定名称的 public 属性 |
Field [] getFields() | 返回该类型中的所有 public 属性 |
Field getDeclaredField(String name) | 返回该类型中指定名称的属性,与属性的访问级别无关 |
Field getDeclaredFields() | 返回该类型中的全部属性,与属性的访问级别无关 |
public class Test {
public static void main(String[] args) throws NoSuchFieldException {
Class c1 = Person.class;
//获取所有用 public 修饰符修饰的属性
Field[] field1 = c1.getFields();
//获取所有的属性 没有修饰符限制
Field[] field2 = c1.getDeclaredFields();
//根据给的属性名 找到相对应的 使用 public 修饰的属性
Field field3 = c1.getField("message");
//根据给的属性名找到相对应的属性没有访问修饰符限制
Field field4 = c1.getDeclaredField("name");
System.out.println("=================属性展示=================");
for (Field field : field2) {
System.out.println("属性名:"+field.getName());
System.out.println("属性类型:"+field.getType());
int modifier=field.getModifiers();
if((modifier& Modifier.PUBLIC)==Modifier.PUBLIC){
System.out.println("PUBLIC");
}else if((modifier& Modifier.PROTECTED)==Modifier.PROTECTED){
System.out.println("PROTECTED");
}else if((modifier& Modifier.PRIVATE)==Modifier.PRIVATE){
System.out.println("PRIVATE");
}else{
System.out.println("default(package)");
}
if((modifier& Modifier.FINAL)==Modifier.FINAL){
System.out.println("这时一个 final 属性");
}
if((modifier& Modifier.STATIC)==Modifier.STATIC){
System.out.println("这时一个静态属性");
}
System.out.println("-----------------------------");
}
}
}
方法 | 说明 |
---|---|
Method getMethod(String name,Class params) | 返回该示例中指定的public 方法 |
Method [] getMethods() | 返回该实例中所有的public方法 |
Method getDeclaredMethod(String name,Class params) | 返回该实例中指定的方法,与方法访问级别无关 |
Method [] getDeclaredMethod() | 返回该实例中的全部方法,与方法访问级别无关 |
package cn.zmt.cn;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test03 {
public static void main(String[] args) throws NoSuchMethodException {
Class c1 = Person.class;
//获取所有 public 修饰的方法
Method[] methods1 = c1.getMethods();
//获取所有的方法 没有访问修饰符限制
Method[] methods2 = c1.getDeclaredMethods();
//根据方法名和参数列表 获取到指定的 public 修饰的方法
Method method3 = c1.getMethod("setName", String.class);
//根据方法名和参数列表 获取到指定的方法 没有访问修饰符限制
Method method4 = c1.getDeclaredMethod("setName", String.class);
System.out.println("======================方法展示======================");
for (Method method : methods2) {
System.out.println("方法名:"+method.getName());
System.out.println("返回值类型:"+method.getReturnType().getSimpleName());
//获取方法的参数列表
Class [] params=method.getParameterTypes();
if(params.length==0){
System.out.println("该方法没有参数");
}else{
System.out.print("该方法的参数列表为:[");
for (int i = 0; i < params.length; i++) {
if(i!=0){
System.out.print(",");
}
System.out.print(params[i].getSimpleName());
}
System.out.println("]");
}
System.out.print("访问修饰符:");
//获取访问修饰符对应的常量
int modifier=method.getModifiers();
if((modifier& Modifier.PUBLIC)==Modifier.PUBLIC){
System.out.println("PUBLIC");
}else if((modifier& Modifier.PRIVATE)==Modifier.PRIVATE){
System.out.println("PRIVATE");
}else if((modifier& Modifier.PROTECTED)==Modifier.PROTECTED){
System.out.println("PROTECTED");
}
if((modifier& Modifier.FINAL)==Modifier.FINAL){
System.out.println("这是一个 final 方法");
}
if((modifier& Modifier.STATIC)==Modifier.STATIC){
System.out.println("这是一个静态方法");
}
if((modifier& Modifier.ABSTRACT)==Modifier.ABSTRACT){
System.out.println("这是一个抽象方法");
}
if((modifier& Modifier.SYNCHRONIZED)==Modifier.SYNCHRONIZED){
System.out.println("这是一个同步方法");
}
//获取方法所属的类或接口的 Class 实例
Class declaringClass=method.getDeclaringClass();
System.out.println("方法声明在:"+declaringClass.getName());
Class [] exceptions=method.getExceptionTypes();
if(exceptions.length==0){
System.out.println("该方法没有声明异常");
}else {
System.out.print("该方法声明的异常有:[");
for (int i = 0; i < exceptions.length; i++) {
if(i!=0){
System.out.print(",");
}
System.out.print(exceptions[i].getSimpleName());
}
System.out.println("]");
}
System.out.println("--------------------------------");
}
}
}
使用 newInstance() 方法创建实例
Class c1= Person.class;//加载 Person 类
Object obj=c1.newInstance();//调用 Person 类的无参构造创建Person 类实例
System.out.println(obj); //调用 Person 实例的 toString() 方法,属性均为默认值
//直接调用类的构造函数(有参/无参)
Class c1= Student.class;
Object o = c1.newInstance();
System.out.println(o.toString());
//通过 Class 实例调用 newInstance() 方法
Constructor constructor1=Student.class.getConstructor();
Object o1 = constructor1.newInstance();
System.out.println(o1);
//通过反射获取具体构造函数(有参/无参) 调用 newInstance() 方法
Constructor constructor2=Student.class.getConstructor(String.class,int.class);
Object o2 = constructor2.newInstance("张小胖",19);
System.out.println(o2.toString());
Constructor constructor3=Student.class.getDeclaredConstructor(String.class);
//用于设置 public 访问修饰符级别外的是否可用
constructor3.setAccessible(true);
Object o3 = constructor3.newInstance("赵");
System.out.println(o3);
方法 | 说明 |
---|---|
xxx getXxx(Object obj) | xxx表示8中基本数据类型之一 |
Object get(Object obj) | 以 Object 类型返回 obj 中相关的属性的值 |
void setXxx(Object obj,xxx val) | 将 obj 中相关属性的值设置为 val。xxx 为八种基本数据类型之一 |
void set(Object obj,Object val) | 将 obj 中相关属性的值设置为 val |
void setAccessible(boolean fiag) | 对相关属性设置访问权限。设置为 true 可以禁止 Java 语言访问检查 |
通过反射方式访问 Person 类的 name 属性,实现取值和赋值
public class Test {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
//通过反射加载一个 Person 实例
Class c1= Person.class;
Object object = c1.newInstance();
//获取 private String name 属性
Field name=c1.getDeclaredField("name");
//name 属性为 private ,这里已超出其访问范围,不能直接访问
//通过 setAccessable 方法,设定为可以访问
name.setAccessible(true);
System.out.println("赋值前 name:"+name.get(object));
//为name 赋值
name.set(object,"赵");
System.out.println("赋值后 name:"+name.get(object));
}
}
Object invoke(Object obj,Object args);
public class Test {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
Class c1= Person.class;
//没有参数可以不写或用null 表示
Method getAge=c1.getDeclaredMethod("getAge",null);
//getAge 方法为 default(package),这里已超出其访问范围,不能直接访问
//通过setAccessable 方法,设定为可以访问
getAge.setAccessible(true);
//调用 getAge 方法并传参,没有参数可以不写或用 null 表示
//getAge 方法为静态方法,调用时可以不指定具体 Person 实例
Object returnAge = getAge.invoke(null, null);
System.out.println("年龄是:"+returnAge);
//创建 Person 实例
Object person=c1.newInstance();
Method silentMethod=c1.getDeclaredMethod("silentMethod",null);
//通过 setAccessable 方法,设定可以访问
silentMethod.setAccessible(true);
//调用 silentMethod 方法并传参,没有参数可以不写或用null表示
silentMethod.invoke(person,null);
//根据方法名和参数列表获取 public void setName(String)方法
Method setName=c1.getDeclaredMethod("setName", String.class);
//setName 方法为 public 可以直接访问
//调用 setName 方法并传参
setName.invoke(person,"赵");
//验证
Object returnName=c1.getDeclaredMethod("getName",null).invoke(person);
System.out.println("name是:"+returnName);
}
}
//通过 setAccessable 方法,设定可以访问
silentMethod.setAccessible(true);
//调用 silentMethod 方法并传参,没有参数可以不写或用null表示
silentMethod.invoke(person,null);
//根据方法名和参数列表获取 public void setName(String)方法
Method setName=c1.getDeclaredMethod("setName", String.class);
//setName 方法为 public 可以直接访问
//调用 setName 方法并传参
setName.invoke(person,"赵");
//验证
Object returnName=c1.getDeclaredMethod("getName",null).invoke(person);
System.out.println("name是:"+returnName);
}
}