Java反射机制,可以在程序中访问 已经写好类和方法 的Java对象的描述,实现访问、检测、修改Java本身的信息 等功能 。提供功能的包:java.lang.reflect
Modifier类 常用解析方法: (解析返回整型数值)
修饰符 | 静态方法 | 说明 |
---|---|---|
boolean | Modifier.isPublic(int mod) | 被public修饰,则true |
boolean | Modifier.isProtected(int mod) | 被protected修饰,则true |
boolean | Modifier.isPrivate(int mod) | 被private修饰,则true |
boolean | Modifier.isStatic(int mod) | 被static修饰,则true |
boolean | Modifier.isFinal(int mod) | 被final修饰,则true |
boolean | Modifier.toString(int mod) | 以字符串形式返回所有修饰符 |
其他信息
类型 | 修饰符 | 方法 | 说明 |
---|---|---|---|
包路径 | Package | getPackage() | 获取该类的存放路径 |
类名称 | String | getName() | 获取类名称 |
继承类 | Class | getSuperclass() | 获取该类的继承类 |
实现接口 | Class[] | getInterfaces() | 获取该类实现的所有接口 |
内部类 | Class[] | getClasses() | 获取所有权限为public的内部类 |
内部类 | Class[] | getDeclaredClasses() | 获取所有内部类 |
内部类声明类 | Class | getDeclaringClass() | 如果该类为内部类,则返回它的成员类,否则为null(空) |
Class Constructor
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Executable
java.lang.reflect.Constructor
通过方法访问构造方法,将返回Constructor类型对象,每个Constructor对象代表一个构造方法
获取构造方法:
修饰符 | 方法 | 说明 |
---|---|---|
Constructor[] | class.getConstructors() | 获取所有权限为public(公开)的构造方法 |
Constructor | class.getConstructor(Class>···parameterTypes) | 获取权限为public的指定构造方法 |
Constructor[] | class.getDeclaredConstructors() | 获取所有的构造方法,按声明顺序排列 |
Constructor | class.getDeclaredConstructor(Class>···parameterTypes) | 获取指定的构造方法 |
Constructor类 常用方法:
修饰符 | 方法 | 说明 |
---|---|---|
int | Constructor.getModifiers() | 获取构造方法的修饰符 |
String | Constructor.getName() | 获取构造方法的名字 |
Class[] | Constructor.getParameterTypes() | 获取构造方法的参数类型 |
boolean | Constructor.isVarArgs() | 带有可变数量的参数,则true |
Class[] | Constructor.getExceptionTypes() | 获取构造方法可能抛出的异常类型 |
Object T |
Constructor.newInstance(Obj··· initargs) | 利用指定参数创建该类对象,如果未设置参数,则以无参构造方法创建 |
通过 java.lang.reflect.Modifier类 来解析部分无法识别的信息,比如getModifiers() 返回的值是需要解析的
例子:
Student类(学生类)
public class Student {
public int id ;
public String name ;
public double Achievement;
//无参构造方法
public Student(){
super();
}
//有参构造方法(参数1)
public Student(int id){
super();
this.id = id;
}
//可变参数
public Student(String...strs){
System.out.println("可变参数获取的值有:");
for (String tmp : strs){
System.out.println(tmp);
}
}
//私有构造方法(参数3)
private Student(int id , String name , double Achievement)throws NumberFormatException{
super();
this.id = id ;
this.name = name;
this.Achievement = Achievement;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", Achievement=" + Achievement +
'}';
}
}
Demo类 (执行类)
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Demo {
public static void main(String[] args) {
try {
//获取类
Class c = Class.forName("Student");
//获取所有构造方法
Constructor[] cons = c.getDeclaredConstructors();
//遍历该类中的构造方法
for(Constructor con : cons){
//修饰符类型
System.out.print(Modifier.toString(con.getModifiers())+" ");
//构造方法名
System.out.print(con.getName()+" (");
//获取参数
Class[] paras = con.getParameterTypes();
//遍历参数元素
for (int i = 0; i < paras.length; i++) {
System.out.print(paras[i].getSimpleName()+" args");
if( i < paras.length-1){
System.out.print(" , ");
}
}
System.out.println(") { } ");
System.out.println("查看是否允许带有可变数量的参数:"+con.isVarArgs());
//获取构造方法可能抛出的异常类型 且遍历 异常类型
System.out.println("该构造方法可能抛出的异常类型为:");
Class[] geterror = con.getExceptionTypes();
for (Class tmp : geterror){
System.out.println(tmp+"\t");
}
System.out.println("---");
}
System.out.println("==================================");
Constructor cs = c.getDeclaredConstructor();
Object obj = cs.newInstance();
System.out.println(obj.toString());
Constructor cs2 = c.getDeclaredConstructor(int.class);
Object obj2 = cs2.newInstance(1322334);
System.out.println(obj2.toString());
Constructor cs3 = c.getDeclaredConstructor(int.class , String.class , double.class );
//获取操作权限
cs3.setAccessible(true);
Object obj3 = cs3.newInstance(1332445 , "小明" , 84.2);
System.out.println(obj3.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
private Student (int args , String args , double args) { }
查看是否允许带有可变数量的参数:false
该构造方法可能抛出的异常类型为:
class java.lang.NumberFormatException
---
public transient Student (String[] args) { }
查看是否允许带有可变数量的参数:true
该构造方法可能抛出的异常类型为:
---
public Student (int args) { }
查看是否允许带有可变数量的参数:false
该构造方法可能抛出的异常类型为:
---
public Student () { }
查看是否允许带有可变数量的参数:false
该构造方法可能抛出的异常类型为:
---
==================================
Student{id=0, name='null', Achievement=0.0}
Student{id=1322334, name='null', Achievement=0.0}
Student{id=1332445, name='小明', Achievement=84.2}
Class Field
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Field
通过方法访问成员变量,将返回Field类型对象,每个Field对象代表一个成员变量
获取成员变量
修饰符 | 方法 | 说明 |
---|---|---|
Field[] | class.getFields() | 获取 所有 权限为public的成员变量 |
Field | class.getField(String name) | 获取权限为public的 指定 成员变量 |
Field[] | class.getDeclaredFields() | 获取说有成员变量,按声明顺序排列 |
Field | class.getDeclaredField(String name) | 获取指定的成员变量 |
Field类 常用方法
修饰符 | 方法 | 说明 |
---|---|---|
String | Field.getName() | 返回变量名 |
class | Field.getType() | 返回该成员类型的class对象 |
Object | Field.get(Object obj) | 指定对象obj中成员变量的值进行返回 |
void | Field.set(Object obj , Object value) | 指定对象obj中成员变量的值置为value |
int | Field.getInt(Object obj) | 获取指定对象obj中类型为int的值 |
void | Field.setInt(Object obj , int i) | 指定对象obj中类型为int的值置为 i |
float | Field.getFloat(Object obj) | 获取指定对象obj中类型为float的值 |
void | Field.setFloat(Object obj , float f) | 指定对象obj中类型为float的值置为 f |
boolean | Field.getBoolean(Object obj) | 获取指定对象obj中类型为boolean的值 |
void | Field.setBoolean(Object obj , boolean z) | 指定对象obj中类型为boolean的值置为 z |
void | Field.setAccessible(boolean flag) | 设置是否忽略权限限制直接访问私有成员 |
int | Field.getModifiers() | 获取该成员变量修饰符的整型 |
Student类 (学生信息类)
public class Student {
/*
*
* 学号
* 名字
* 性别
* 总分数
*
* */
//分别设置初始值
public int id = 99999;
public String name = "XXX";
public String esx = "男";
private double Ovresult = 720.0;
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", esx='" + esx + '\'' +
", Ovresult=" + Ovresult +
'}';
}
}
Demo类 (执行类)
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class Demo {
public static void main(String[] args) {
try{
/* 遍历Student类的成员变量
*
* */
//获取类
Class c = Class.forName("Student");
//获取该类所有成员变量
Field[] fid= c.getDeclaredFields();
//获取所有的构造方法
Constructor cs = c.getDeclaredConstructor();
//创建该类对象 Student
Student setSude = (Student) cs.newInstance();
//遍历成员变量
System.out.println("遍历Student类的成员变量:");
for (Field tmp : fid){
//修饰符
System.out.print(Modifier.toString(tmp.getModifiers())+" ");
//类型
//class.getSimpleName()方法 返回类型名称(简略名)
System.out.print(tmp.getType().getSimpleName()+" ");
//变量名
System.out.print(tmp.getName()+" = ");
//获取指定的成员变量
//tmp.getName()返回成员变量名
Field f = c.getDeclaredField(tmp.getName());
//忽略权限限制直接访问私有成员
f.setAccessible(true);
System.out.print(f.get(setSude)+";");
System.out.println();
}
/* 更改Student类的成员变量的值
*
* 由于枚举型,为学习则这样表示
* 数组索引位置的说明:(顺序严格)
* 更改开关
* 更改结果(无更改用null代替)
*
* */
//限于更改一位同学的数据
Object[] mations = new Object[]{
//更改 学号(0 ,1)
true,
12345,
//更改 名字(2 ,3)
true,
"小明",
//更改性别(4 ,5)(此处为无更改)
false,
null,
//更改 总分数(6 ,7)
true,
523.5
};
System.out.println("============================");
//获取所有成员变量(按声明顺序获取)
Field[] setmations = c.getDeclaredFields();
System.out.println("====信息更新====");
for (Field tmp : setmations){
//更改学号
if (tmp.getName().equals("id") && (Boolean) mations[0]){
tmp.set(setSude , (int)mations[1]);
System.out.print("学号更改为:");
System.out.println(tmp.get(setSude));
}
//更改姓名
if (tmp.getName().equals("name") && (Boolean) mations[2]){
tmp.set(setSude , (String)mations[3]);
System.out.print("姓名更改为:");
System.out.println(tmp.get(setSude));
}
//更改性别
if (tmp.getName().equals("esx") && (Boolean) mations[4]){
tmp.set(setSude , (String)mations[5]);
System.out.print("性别更改为:");
System.out.println(tmp.get(setSude));
}
//更改总成绩
if (tmp.getName().equals("Ovresult") && (Boolean) mations[6]){
//忽略权限限制直接访问私有成员
tmp.setAccessible(true);
tmp.set(setSude, (double)mations[7]);
System.out.print("总成绩更改为:");
System.out.println(tmp.get(setSude));
}
}
//重新遍历学生数据
System.out.println("====重新遍历学生数据====");
/*
*
* (1)自选
*
* */
// for (Field tmp : setmations){
// System.out.print(tmp.getName()+" = ");
// System.out.print(tmp.get(setSude));
// System.out.println();
// }
/*
*
* (2)自选
*
* */
System.out.println(setSude.toString());
}catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
运行结果
遍历Student类的成员变量:
public int id = 99999;
public String name = XXX;
public String esx = 男;
private double Ovresult = 720.0;
============================
====信息更新====
学号更改为:12345
姓名更改为:小明
总成绩更改为:523.5
====重新遍历学生数据====
Student{id=12345, name='小明', esx='男', Ovresult=523.5}
Class Method
java.lang.Object
java.lang.reflect.AccessibleObject
java.lang.reflect.Executable
java.lang.reflect.Method
通过方法访问方法,将返回Method类型对象,每个Method对象代表一个方法
获取方法
修饰符 | 方法 | 说明 |
---|---|---|
Method[] | class.getMethods() | 获取所有权限为public的方法 |
Method | class.getMethod(String name , Class>····parameterTypes) | 获取权限为public的指定方法 |
Method[] | class.getDeclaredMethods() | 获取所有的方法,按声明顺序排列 |
Method | class.getDeclaredMethod(String name , Class>····parameterTypes) | 获取指定方法 |
Method类 常用方法
修饰符 | 方法 | 说明 |
---|---|---|
String | Method.getName() | 获取方法名称 |
Class[] | Method.getParameterTypes() | 获取参数的类型 |
Class | Method.getReturnType() | 获取方法返回的类型 |
Class[] | Method.getExceptionTypes() | 返回方法抛出的异常类型 |
Object | Method.invoke(Object obj , Object … args) | 指定参数args指定obj方法 |
Boolean | Method.isVarArgs() | 带有可变数量的参数,则true |
int | Method.getModifiers() | 获取方法的修饰符(呈现形式整数) |
Dog类
public class Dog {
//算术 (数值相加)
// 抛出算术异常ArithmeticException
public int Countadd(int a , int b ) throws ArithmeticException{
return (a+b);
}
//行为
public void Behavior(String naem ,String...agrs){
System.out.print("我的小狗叫:"+naem);
System.out.print(",他会");
for (String tmp : agrs){
System.out.print(tmp+"\t");
}
System.out.println();
}
//主人(认领 / 更换)
private String hostnaem = null;
private void Thehost(String name){
this.hostnaem = name;
}
}
Demo类
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Demo {
public static void main(String[] args) {
//遍历Dog类的所有方法
try {
Class c = Class.forName("Dog");
//获取所有方法
Method[] mod = c.getDeclaredMethods();
//遍历方法
for (Method tmp : mod){
//修饰符权限
System.out.print(Modifier.toString(tmp.getModifiers())+" ");
//方法返回类型
System.out.print(tmp.getReturnType()+" ");
//方法名字
System.out.print(tmp.getName()+" (");
//参数
Class[] paras = tmp.getParameterTypes();
for (int i = 0; i < paras.length; i++) {
System.out.print(paras[i].getSimpleName());//.getSimpleName() java.lang.String
if (i < paras.length-1){
System.out.print(" ,");
}
}
System.out.print(") ");
//抛出异常(无则跳过)
Class[] exces = tmp.getExceptionTypes();
if (exces.length != 0){
System.out.print(" throws ");
for (int i = 0; i < exces.length; i++) {
System.out.print(exces[i].getSimpleName());
if (i < exces.length-1){
System.out.print(",");
}
}
}
System.out.print("{ } ");
System.out.println(" 可变数量的参数?"+tmp.isVarArgs());
}
//调用方法Dog类中的Countadd()方法(算术行为)
System.out.println("======Countadd()方法");
//获取构造方法(无参构造方法)
Constructor cs = c.getConstructor();
//实例化对象
Dog tmpmethod =(Dog) cs.newInstance();
Method m= c.getDeclaredMethod("Countadd", int.class , int.class);
System.out.println(m.invoke(tmpmethod , 4 , 3));
//调用方法Dog类中的Behavior()方法(行为)
System.out.println("======Behavior()方法");
Method m2= c.getDeclaredMethod("Behavior", String.class , String[].class);
//获取权限
m2.setAccessible(true);
m2.invoke(tmpmethod , "Jak" , new String[]{
"奔跑" , "吃"});
//Dog属者(主人)
//调用方法Dog类中的Thehost()方法
System.out.println("\n======Thehost()方法");
Method m3= c.getDeclaredMethod("Thehost", String.class);
m3.setAccessible(true);
m3.invoke(tmpmethod , "Tom");
}catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
运行结果
public transient void Behavior (String ,String[]) { } 可变数量的参数?true
public int Countadd (int ,int) throws ArithmeticException{ } 可变数量的参数?false
private void Thehost (String) { } 可变数量的参数?false
======Countadd()方法
7
======Behavior()方法
我的小狗叫:Jak,他会奔跑 吃
======Thehost()方法
Class Annotation
java.lang.Object
java.text.Annotation
对Annotation类型未了解,可前去网址了解:点击了解
访问的前提注解要有该注解@Retention(RetentionPolicy.RUNTIME)
获取注解
修饰符 | 调用的类型 | 方法 | 说明 |
---|---|---|---|
Annotation | Constructor(构造方法) Field(成员变量) Method(方法) |
getAnnotation(Class annotationClass) | 获取指定的Annotation,不存在则返回null |
Annotation[] | Constructor(构造方法) Field(成员变量) Method(方法) |
getAnnotations() | 获取所有的Annotation |
方法
修饰符 | 调用的类型 | 方法 | 说明 |
---|---|---|---|
String | Class AnnotationClass | toString() | 返回此注释的String表示形式 |
boolean | Constructor(构造方法) Field(成员变量) Method(方法) |
isAnnotationPresent(Class annotationClass) | 查看是否添加注解 |
例子:
BookAnnotation注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)//可被反射利用
public @interface BookAnnotation {
//备注
String remark() default "";
//属性是否打开
boolean enable() default true;
}
Book类
public class Book {
//书名
@BookAnnotation(remark = "书名")
public String name;
//类型
@BookAnnotation(remark = "类型" , enable = false)//不启动属性
public String species;
//价钱
@BookAnnotation(remark = "价钱")
public int price;
//厂商
@BookAnnotation(remark = "厂商")
public String firm;
}
Demo类
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) {
try{
Class c = Book.class;
//获取Book类的所有成员变量
Field[] fields = c.getDeclaredFields();
//遍历成员变量
for (Field tmp : fields){
//查看是否添加注解(成员变量)
if (tmp.isAnnotationPresent(BookAnnotation.class)){
System.out.println(tmp.getName()+"注解过了");
//获取所有注解
BookAnnotation b = tmp.getAnnotation(BookAnnotation.class);
//返回remark值
System.out.println("内容为:"+b.remark());
//返回enable值
System.out.println("属性是否有效:"+b.enable());
System.out.println("注解形式:"+b.toString());
}
System.out.println("\n==============");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
运行结果
name注解过了
内容为:书名
属性是否有效:true
注解形式:@BookAnnotation(enable=true, remark="书名")
==============
species注解过了
内容为:类型
属性是否有效:false
注解形式:@BookAnnotation(enable=false, remark="类型")
==============
price注解过了
内容为:价钱
属性是否有效:true
注解形式:@BookAnnotation(enable=true, remark="价钱")
==============
firm注解过了
内容为:厂商
属性是否有效:true
注解形式:@BookAnnotation(enable=true, remark="厂商")
==============
以上是个人学习后写出来的代码分享,如果有问题可在下面留言!