目录
前言
本文将用到 Student 类和 Address 类进行演示。
Student 类:
package com.hai.tang.model;
public class Student {
public Integer id;
public String name;
public Integer score;
public Address address;
public Student(){}
public Student(Integer id ,String name,Integer score){
this.id=id;
this.name=name;
this.score=score;
}
public Student(String name,Integer id ){
this.id=id;
this.name=name;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String setAndGetName(int id, String name) {
this.id = id;
this.name = name;
return name;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "id:"+id+",name:"+name+",score:"+score+",address:"+address;
}
public String calculation(String name,Integer score ){
return name+"成绩是:"+score;
}
}
Address 类:
package com.hai.tang.model;
public class Address {
public String type;
public String value;
public Address(String type, String value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "type:" + type + ",value:" + value;
}
}
一、获取反射类
1.使用 Class.forName 方式获取反射类
Class studentClass = Class.forName("com.hai.tang.model.Student");
System.out.println(studentClass); //class com.hai.tang.model.Student
2.使用 类名.class 方式获取反射类
Class studentClass = Student.class;
System.out.println(studentClass);//class com.hai.tang.model.Student
3.通过 对象.getClass() 方式获取反射类
Student student = new Student();
Class studentClass = student.getClass();
System.out.println(studentClass);//class com.hai.tang.model.Student
二、反射获取对象的所有构造方法及参数个数、类型
Class<Student> studentClass = Student.class;
//获取 Student 里所有的构造方法
Constructor[] constructors = studentClass.getConstructors();
for (Constructor constructor : constructors) {
//打印该构造方法
System.out.println(constructor);
//获取该构造方法的形参
Class[] params = constructor.getParameterTypes();
//获取该构造方法有几个参数
int paramsCount = params.length;
System.out.println(paramsCount);
for (int i = 0; i < params.length; i++) {
//打印该形参
System.out.println(params[i]);
}
//调用有3个参数的构造方法进行反射创建对象
if (paramsCount == 3) {
try {
Student student = (Student) constructor.newInstance(1, "jack", 89);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
System.out.println();
}
输出:
public com.hai.tang.model.Student(java.lang.String,java.lang.Integer)
2
class java.lang.String
class java.lang.Integer
public com.hai.tang.model.Student(java.lang.Integer,java.lang.String,java.lang.Integer)
3
class java.lang.Integer
class java.lang.String
class java.lang.Integer
public com.hai.tang.model.Student()
0
二、利用反射创建对象
1.调用 newInstance()无参构造方法创建对象
Class<Student> studentClass = Student.class;
try {
//Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
Student student = studentClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
或者 使用getDeclaredConstructor :
Class<Student> studentClass = Student.class;
try {
//或使用getDeclaredConstructor()调用默认构造方法
Constructor<Student> con = studentClass.getDeclaredConstructor();
Student student = con.newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
2.调用有参的构造方法创建对象
Class<Student> studentClass = Student.class;
try {
Constructor<Student> con = studentClass.getDeclaredConstructor(Integer.class, String.class, Integer.class);
Student student = con.newInstance(1,"jack", 89);
System.out.println(student.getName());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
三、反射获取类成员变量名称
1.获取所有成员变量的全部信息
Class clas = Student.class;
Field[] fields = clas.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
输出:
public java.lang.Integer com.hai.tang.model.Student.id
public java.lang.String com.hai.tang.model.Student.name
public java.lang.Integer com.hai.tang.model.Student.score
public com.hai.tang.model.Address com.hai.tang.model.Student.address
2.只获取所有成员变量的名称
Class clas = Student.class;
Field[] fields = clas.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
String fieldName = fields[i].getName();
System.out.println(fieldName);
}
输出:
id
name
score
address
3.获取某一指定字段全部信息
Class clas = Student.class;
Field field = clas.getField("name"); //获取"name"
//输出 public java.lang.String com.hai.tang.model.Student.name
System.out.println(field);
4.只获取某一指定成员变量的名称
Class clas = Student.class;
Field field = clas.getField("name"); //获取"name"
String name = field.getName();
System.out.println(name); //输出name
5.getFields()与getDeclaredFields()的区别
- getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
- getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是 不包括父类的声明字段
四、获取成员变量的值
1.获取公有的成员变量的值
try {
//创建对象
Student student = new Student(1,"李梅",89);
//通过反射获取属性 name 成员变量对应的值
Class clas = Student.class;
Field field = clas.getField("name");
//如果获取的成员变量是私有的 使用get获取会报 IllegalAccessException 错误
Object property = field.get(student);
System.out.println(property.toString());//输出:李梅
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
2.获取私有的成员变量的值
加入 name 是 private 修饰的私有成员变量
try {
//创建对象
Student student = new Student(1,"李梅",89);
//反射获取
Field privateField = Student.class.getDeclaredField("name");
privateField.setAccessible(true);
String name = (String) privateField.get(student);
System.out.println(name);//输出:李梅
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
五、修改成员变量的值
try {
Student student = new Student(1,"李梅",89);
//没有修改时:李梅
System.out.println("没有修改时:" + student.getName());
Class clas = Student.class;
Field field = clas.getDeclaredField("name");
// 若name成员变量是private修饰的,需要将可见范围设为true才可以访问私有类型变量
//field.setAccessible(true);
field.set(student, "张三"); // 将name的值设置为张三
//修改后:张三
System.out.println("修改后:" + student.getName());
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
六、反射获取类的所有方法
1.使用getMethods获取所有方法(包含从父类和Object继承的方法)
Class clas = Student.class;
Method[] methods = clas.getMethods();
Arrays.stream(methods).forEach(System.out::println);
输出:
public java.lang.String com.hai.tang.model.Student.toString()
public com.hai.tang.model.Address com.hai.tang.model.Student.getAddress()
public java.lang.String com.hai.tang.model.Student.getName()
public void com.hai.tang.model.Student.setName(java.lang.String)
public void com.hai.tang.model.Student.setAddress(com.hai.tang.model.Address)
public void com.hai.tang.model.Student.setId(java.lang.Integer)
public java.lang.String com.hai.tang.model.Student.setAndGetName(int,java.lang.String)
public java.lang.Integer com.hai.tang.model.Student.getScore()
public java.lang.String com.hai.tang.model.Student.calculation(java.lang.String,java.lang.Integer)
public void com.hai.tang.model.Student.setScore(java.lang.Integer)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
2.使用getDeclaredMethods获取其类自身声明的所有方法
Class clas = Student.class;
Method[] methods = clas.getDeclaredMethods();
Arrays.stream(methods).forEach(System.out::println);
输出:
public java.lang.String com.hai.tang.model.Student.toString()
public com.hai.tang.model.Address com.hai.tang.model.Student.getAddress()
public java.lang.String com.hai.tang.model.Student.getName()
public void com.hai.tang.model.Student.setName(java.lang.String)
public void com.hai.tang.model.Student.setAddress(com.hai.tang.model.Address)
public java.lang.Integer com.hai.tang.model.Student.getScore()
public void com.hai.tang.model.Student.setScore(java.lang.Integer)
public java.lang.String com.hai.tang.model.Student.calculation(java.lang.String,java.lang.Integer)
public void com.hai.tang.model.Student.setId(java.lang.Integer)
public java.lang.String com.hai.tang.model.Student.setAndGetName(int,java.lang.String)
七、反射执行方法
1.调用某一方法(无参构造器)
try {
Class clas = Student.class;
//要调用的方法名称及参数类型
Method method = clas.getMethod("setAndGetName", int.class,String.class);
//使用newInstance (无参构造器)创建对象,调用方法,传入参数"李梅",接收返回值为 obj (若方法无返回值则会返回null)
Object obj = method.invoke(clas.newInstance(), 1,"李梅");
//获取方法返回结果
String name = (String) obj;
System.out.println(name);//输出:李梅
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
2.调用某一方法(有参构造器)
try {
Class clas = Student.class;
//要调用的方法名称及参数类型
Method method = clas.getMethod("setAndGetName", int.class,String.class);
//使用newInstance (有参构造器)创建对象
Constructor con = clas.getDeclaredConstructor(Integer.class, String.class, Integer.class);
//调用方法,传入参数 2,"张三" ,并接收返回值
Object obj = method.invoke(con.newInstance(1,"李梅", 89),2,"张三");
//获取方法返回结果
String name = (String) obj;
System.out.println(name);//输出:张三
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
3.调用private修饰的私有方法
假设 setAndGetName 方法是 private 修饰的,需要用 getDeclaredMethod 获取方法,并设置setAccessible为true
try {
Class clas = Student.class;
//要调用的方法名称及参数类型
Method method = clas.getDeclaredMethod("setAndGetName", int.class,String.class);
method.setAccessible(true);
//使用newInstance (有参构造器)创建对象
Constructor con = clas.getDeclaredConstructor(Integer.class, String.class, Integer.class);
//调用方法,传入参数 2,"张三" ,并接收返回值
Object obj = method.invoke(con.newInstance(1,"李梅", 89),2,"张三");
//获取方法返回结果
String name = (String) obj;
System.out.println(name);//输出:张三
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
八、综合示例
1.利用反射判断 WebFrom 类中的成员变量的值是否有是 “token” 的
package com.hai.tang.model;
public class WebFrom {
public static String FROM_XT = "xt";
public static String FROM_WX= "wx";
public static String FROM_DINGTALK = "dingtalk";
public static String FROM_EASSSO= "eassso";
public static String FROM_COMMON = "common";
public static String FROM_TOKEN = "token";
public static String FROM_WELINK = "welink";
public static String FROM_SSOTYPE = "ssotype";
public static String FROM_WORKFLOW = "workflow";
public static String FROM_OTHERAPP = "otherapp";
public static String FROM_IDAAS = "IDAAS";
}
实现代码:
import com.hai.tang.model.WebFrom;
import java.lang.reflect.Field;
public class MainServer {
public static void main(String[] args) throws IllegalAccessException {
boolean hasToken = false;
Field[] fields = WebFrom.class.getFields();
for (Field field : fields) {
String name = field.getName();
String webFromValue = (String) field.get(name);
if ("token".equals(webFromValue)) {
hasToken = true;
}
}
System.out.println(hasToken);//输出 true
}
}
2.获取 RedisKeys 类中所有成员变量里的 number、description、expireDate、type
package com.hai.tang.model;
public class RedisKeys {
public static Key developerEids = new Key("$developer-eids","开发者企业号集合","set");
public static Key qrUrlMD5 = new Key("$qr-url","二维码的url缓存","string",60*60);
public static Key wxTicket = new Key("$key-wxTicket-eid","微信ticket ","string",7200);
public static Key portalAppList = new Key("$applist-portal","展现在门户的应用列表","string",7200);
public static Key appServiceIdMap = new Key("$app-serviceIdMap","记录应用映射的服务;安装时写入,卸载时删除;判断license使用","string");
public static Key loginCode = new Key("$login-code","登陆加密码","string",1000*60*60);
public static Key cdnEids = new Key("$eid-has-config-cdn","配置过自定义cdn的企业eid","set");
public static Key JobStatus = new Key("$job_status","任务锁","string",60*10);
}
package com.hai.tang.model;
public class Key {
public String number;
public String description;
public int expireDate = -1;
public String type;
public Key(String number, String description, String type) {
this(number, description, type, -1);
}
public Key(String number, String description, String type, int expireDate) {
this.number = number;
this.description = description;
this.expireDate = expireDate;
this.type = type;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getExpireDate() {
return expireDate;
}
public void setExpireDate(int expireDate) {
this.expireDate = expireDate;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
实现代码:
import com.hai.tang.model.Key;
import java.lang.reflect.Field;
import java.util.*;
public class MainServer {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException {
Class redisKeysClass = Class.forName("com.hai.tang.model.RedisKeys");//要反射的包名
Field[] fields = redisKeysClass.getDeclaredFields();
List<Map<String,String>> list = new ArrayList<>();
for (int i = 0; i < fields.length; i++) {
Map<String, String> map = new HashMap<>();
Object property = fields[i].get(redisKeysClass);
Key key= (Key)property;
map.put("number",key.getNumber());
map.put("description",key.getDescription());
map.put("type",key.getType());
map.put("expireDate",String.valueOf(key.getExpireDate()));
list.add(map);
}
System.out.println(list);
}
}
输出:
[{number=$developer-eids, description=开发者企业号集合, expireDate=-1, type=set},
{number=$qr-url, description=二维码的url缓存, expireDate=3600, type=string},
{number=$key-wxTicket-eid, description=微信ticket , expireDate=7200, type=string},
{number=$applist-portal, description=展现在门户的应用列表, expireDate=7200, type=string},
{number=$app-serviceIdMap, description=记录应用映射的服务;安装时写入,卸载时删除;判断license使用, expireDate=-1, type=string},
{number=$login-code, description=登陆加密码, expireDate=3600000, type=string},
{number=$eid-has-config-cdn, description=配置过自定义cdn的企业eid, expireDate=-1, type=set},
{number=$job_status, description=任务锁, expireDate=600, type=string}]