什么是反射Reflect
反射(Reflect)是运行时动态访问类与对象的技术
反射是JDK1.2版本后的高级特性,隶属于java.lang.reflect
大多数Java框架都基于反射实现参数配置、动态注入等特性
反射的核心类
Class类
Constructor构造方法类
Method方法类
Field成员变量类
1、Class类
Class是JVM中代表"类和接口"的类
Class对象具体包含了某个特定类的结构信息
通过Class类对象可获取对应类的构造方法/方法/成员变量
Class核心方法
方法 | 用途 |
---|---|
Class.forName() | 静态方法,用于获取指定Class对象 |
classObj.newInstance() | 通过默认构造方法创建新的对象 |
classObj.getConstructor() | 获得指定的public修饰构造方法Constructor对象 |
classObj.getMethod() | 获得指定的public修饰方法Method对象 |
classObj.getField() | 获取指定的public修饰成员变量Field对象 |
怎么判断我们的Class对象是否被加载了呢?
通过静态代码块可以判断类是否被加载到jvm
package com.xmaven.reflect.entity;
/**
* @ClassName User
* @Description TODO 员工实体类
* @Author Ambition
* @Date 2021/2/7 16:44
* @Version 1.0.0
**/
public class User {
/**
* 通过静态代码块可以判断类是否被加载到jvm
*/
static {
System.out.println("User类已被加载到jvm,并且已经初始化");
}
private Integer id;
public String username;
private String password;
private Float salary;
private String dname;
public User() {
System.out.println("User默认的无参构造方法被执行了!");
}
public User(Integer id, String username, String password, Float salary, String dname) {
this.id = id;
this.username = username;
this.password = password;
this.salary = salary;
this.dname = dname;
System.out.println("User带参构造方法已被执行");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Float getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", salary=" + salary +
", dname='" + dname + '\'' +
'}';
}
public User updateSalary(Float val){
this.salary = this.salary +val;
System.out.println(this.username + "调薪至" + this.salary);
return this;
}
}
编写demo
package com.xmaven.reflect;
import com.xmaven.reflect.entity.User;
/**
* @ClassName ClassSample
* @Description TODO
* @Author Ambition
* @Date 2021/2/7 16:52
* @Version 1.0.0
**/
public class ClassSample {
public static void main(String[] args) {
try {
// Class.forName()方法将指定的类加载到jvm,并返回对应的Class对象
Class<?> userClass = Class.forName("com.xmaven.reflect.entity.User");
// newInstance通过默认构造方法创建新的对象
User user = (User) userClass.newInstance();
System.out.println(user);
} catch (ClassNotFoundException e) {
// 类名与类路径书写错误是抛出“类无法找到”异常
e.printStackTrace();
} catch (InstantiationException e) {
// 对象无法实例化,抛出"实例化异常"
e.printStackTrace();
} catch (IllegalAccessException e) {
// 非法访问异常,当在作用域外访问对象方法或成员变量时抛出异常
e.printStackTrace();
}
}
}
2、Constructor构造方法类
Constructor类是对Java类中的构造方法的抽象
Constructor对象包含了具体类的某个具体构造方法的声明
通过Constructor对象调用带参构造方法创建对象
Constructor类核心方法
方法 | 用途 |
---|---|
classObj.getConstructor() | 获取指定public修饰的构造方法对象 |
constructorObj.newInstance() | 通过对应的构造方法创造对象 |
编写demo(注:公用一个实体类)
package com.xmaven.reflect;
import com.xmaven.reflect.entity.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @ClassName ConstructorSample
* @Description TODO 利用带参构造方法创建对象
* @Author Ambition
* @Date 2021/2/7 17:20
* @Version 1.0.0
**/
public class ConstructorSample {
public static void main(String[] args) {
try {
Class<?> userClass = Class.forName("com.xmaven.reflect.entity.User");
// 构造方法中的填写相应的类型,匹配我们对象里面的方法
Constructor<?> constructor = userClass.getConstructor(new Class[]{
Integer.class, String.class, String.class, Float.class, String.class
});
// Obj[]数组中的参数需要和我们上面的参数类型填写一致才行
User user = (User) constructor.newInstance(new Object[]{
100, "李磊", "root", 2001f, "文化部"
});
System.out.println(user);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
// 没有找到与之对应格式的方法
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
// 当被调用的方法的内部抛出了异常而没有被捕获的时候
e.printStackTrace();
}
}
}
3、Method方法类
Method对象指代某个类中的方法的描述
Method对象使用classObj.getMethod()方法获取
通过Method对象调用指定对象的对应方法
Method类核心方法
方法 | 用途 |
---|---|
classObj.getMethod() | 获取指定public修饰的方法对象 |
methodObj.invoke() | 调用指定对象的对应方法 |
编写demo(注:公用一个实体类)
package com.xmaven.reflect;
import com.xmaven.reflect.entity.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @ClassName MethodSample
* @Description TODO 利用Method方法类调用
* @Author Ambition
* @Date 2021/2/7 17:37
* @Version 1.0.0
**/
public class MethodSample {
public static void main(String[] args) {
try {
Class<?> userClass = Class.forName("com.xmaven.reflect.entity.User");
Constructor<?> constructor = userClass.getConstructor(new Class[]{
Integer.class, String.class, String.class, Float.class, String.class
});
User user = (User) constructor.newInstance(new Object[]{
1000, "张三", "root", 3800f, "研发部"
});
/**
* 第一个里面参数是传入的方法名 里面可能有多个方法名相同的方法,参数不同
* 第二个参数 传入我们需要的带参的方法的参数类型
*/
Method updateSalaryMethod = userClass.getMethod("updateSalary", new Class[]{
Float.class
});
User newUser = (User) updateSalaryMethod.invoke(user, new Object[]{1000f});
System.out.println(newUser);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
4、Field成员变量类
Field对应某个具体类中的成员变量的声明
Field对象使用classObj.getField()方法获取
通过Field对象可为某个对象成员变量赋值/取值
Field类核心方法
方法 | 用途 |
---|---|
classObj.getField() | 获取指定public修饰的成员变量对象 |
fieldObj.set() | 为某对象指定成员变量赋值 |
fieldObj.get() | 获取某对象指定成员变量数值 |
package com.xmaven.reflect;
import com.xmaven.reflect.entity.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/**
* @ClassName FieldSample
* @Description TODO Field对成员变量进行赋值/取值
* @Author Ambition
* @Date 2021/2/7 18:01
* @Version 1.0.0
**/
public class FieldSample {
public static void main(String[] args) {
try {
Class<?> userClass = Class.forName("com.xmaven.reflect.entity.User");
Constructor<?> constructor = userClass.getConstructor(new Class[]{
Integer.class, String.class, String.class, Float.class, String.class
});
User user = (User) constructor.newInstance(new Object[]{
100, "李磊", "root", 2001f, "运维部"
});
// Field的赋值/取值操作
Field usernameField = userClass.getField("username");
usernameField.set(user,"张三");
String username = (String) usernameField.get(user);
System.out.println("username = " + username);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
// 没有找到成员变量类的异常
e.printStackTrace();
}
}
}
getDeclared系列方法
getDeclaredConstructor(s)|Method(s)|Field(s)获取对应的对象
getConstructor(s)|Method(s)|Field(s)只能获取public对象
访问非作用域内构造方法、方法、成员变量,会抛出异常
编写demo
package com.xmaven.reflect;
import com.xmaven.reflect.entity.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @ClassName GetDeclaredSample
* @Description TODO 获取对象所有成员变量值
* @Author Ambition
* @Date 2021/2/7 18:19
* @Version 1.0.0
**/
public class GetDeclaredSample {
public static void main(String[] args) {
try {
Class<?> userClass = Class.forName("com.xmaven.reflect.entity.User");
Constructor<?> constructor = userClass.getConstructor(new Class[]{
Integer.class, String.class, String.class, Float.class, String.class
});
User user = (User) constructor.newInstance(new Object[]{
100, "李磊", "root", 2001f, "运维部"
});
// 获取当前类的所有成员变量
Field[] fields = userClass.getDeclaredFields();
for (Field field : fields) {
if (field.getModifiers() == 1) { // public修饰
Object val = field.get(user);
System.out.println(field.getName() + ":" + val);
} else if (field.getModifiers() == 2) { // private修饰
// 方法名拼接
String methodName = "get" + field.getName().substring(0,1).toUpperCase()
+ field.getName().substring(1);
Method getMethod = userClass.getMethod(methodName);
Object val = getMethod.invoke(user);
System.out.println(field.getName() + ":" + val);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
反射在项目中的应用案例
语言国际化简单demo
编写一个接口
package com.xmaven.i18n;
/**
* @ClassName I18N
* @Description TODO
* @Author Ambition
* @Date 2021/2/7 18:33
* @Version 1.0.0
**/
public interface I18N {
public String say();
}
实现接口
package com.xmaven.i18n;
/**
* @ClassName Zhcn
* @Description TODO
* @Author Ambition
* @Date 2021/2/7 18:34
* @Version 1.0.0
**/
public class Zhcn implements I18N {
@Override
public String say() {
return "生命不息奋斗不止";
}
}
在工程的src目录下创建一个配置文件
config.properties
内容如下
language=com.xmaven.i18n.Zhcn
编写测试类:
package com.xmaven.i18n;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Properties;
/**
* @ClassName Application
* @Description TODO
* @Author Ambition
* @Date 2021/2/7 18:36
* @Version 1.0.0
**/
public class Application {
public static void say(){
Properties properties = new Properties();
String configPath = Application.class.getResource("/config.properties").getPath();
try {
configPath = URLDecoder.decode(configPath, "UTF-8");
properties.load(new FileInputStream(configPath));
String language = properties.getProperty("language");
I18N i18n = (I18N)Class.forName(language).newInstance();
System.out.println(i18n.say());
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Application.say();
}
}
评论区