反射
一、认识反射机制
1、反射的基本概念
1.1、反射是指程序可以访问、检测和修改它本身状态或行为的一种能力, 并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
1.2、反射工作机制:程序运行时,java 系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类,通过专门的类可以访问这些信息,用来保存这些信息的类是class 类,class 类为编写可动态操纵的 java 代码程序提供了强大功能。
二、获取Class对象的三种方式
1、第一种方式
1.1、Class c = Class.forName(“带包名的完整类名”);
package reflect;
public class Test1 {
public static void main(String[] args){
//获取Class对象的第一种方式:Class c = Class.forName("带包名的完整类名");
try {
Class strClass = Class.forName("java.lang.String");
Class dateClass = Class.forName("java.util.Date");
Class intClass = Class.forName("java.lang.Integer");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、第二种方式
2.1、Class c = 对象.getClass();
package reflect;
public class Test1 {
public static void main(String[] args) {
//获取Class对象的第二种方式:Class c = 对象.getClass();
Class strClass = null;
try {
strClass = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//java中任何一个对象都有一个方法:getClass()
String s = "abc";
Class str = s.getClass();
// true(==判断的是对象的内存地址
System.out.println(strClass == str);
}
}
3、第三种方式
3.1、Class c = 任何类型.class;
package reflect;
import java.util.Date;
public class Test1 {
public static void main(String[] args) {
//获取Class对象的第二种方式:Class c = 任何类型.class;
//Java语言中任何一种类型,包括基本数据类型。都有.class属性
Class str = String.class;
Class date = Date.class;
Class i = int.class;
Class d = double.class;
}
}
三、获取类来实例化对象
1、通过反射机制创建对象
1.1、代码示例
package reflect;
/*
通过Class对象的newInstance()方法来实例化对象
newInstance()其实内部调用的是无参构造方法,
所以必须保证无参构造方法存在
*/
public class Test2 {
public static void main(String[] args) {
//不使用反射机制创建对象
User user1 = new User();
System.out.println("Usr1 = " + user1);
//通过反射机制创建对象
try {
//获取Class对象
Class c = Class.forName("reflect.User");
//通过Class来实例化对象
Object user2 = c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
1.2、Class.forName(“完整类名”);方法的执行会导致类加载
package reflect;
public class MyClass {
static {
System.out.println("MyClass类的静态代码块执行了");
}
}
package reflect;
/*
Class.forName("完整类名");
此方法的执行会导致类加载,类加载时静态代码块会执行
如果你只是希望一个类的静态代码块执行,其它代码一律不执行,
你可以使用此方法
*/
public class Test3 {
public static void main(String[] args) {
try {
Class c = Class.forName("reflact.MyClass"); //MyClass类的静态代码块执行了
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、通过反射机制获取类中所有field
2.1、代码示例
package reflact;
public class Student {
private String name;
private int age;
boolean sex;
public int num;
public static final double PI = 3.1415926;
}
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/*
通过反射机制获取Student类中的所有field
*/
public class Test4 {
public static void main(String[] args) throws ClassNotFoundException {
//创建这个为了拼接字符串
StringBuilder str = new StringBuilder();
//通过反射机制获取Student类
Class c = Class.forName("reflect.Student");
str.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
str.append("\t");
str.append(Modifier.toString(field.getModifiers()));
str.append(" ");
str.append(field.getType().getSimpleName());
str.append(" ");
str.append(field.getName());
str.append(";\n");
}
str.append("}");
System.out.println(str);
}
}
3、通过反射机制访问java对象的属性
3.1、代码示例
public class Student {
private String name;
private int age;
boolean sex;
public int num;
public static final double PI = 3.1415926;
}
import java.lang.reflect.Field;
public class Test5 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//通过反射机制访问对象的属性
Class c = Class.forName("reflact.Student");
//obj即是Student对象,底层是调用了无参构造方法
Object obj = c.newInstance();
//获取num属性,根据属性的名称获取
Field numField = c.getDeclaredField("num");
//给obj对象(Student对象)的num属性赋值
numField.set(obj,1001);
//获取属性的值
System.out.println("numValue = " + numField.get(obj));
//获取私有属性
Field nameField = c.getDeclaredField("name");
//打破封装,设置之后,在外部也可以访问private
nameField.setAccessible(true);
//给name属性赋值
nameField.set(obj,"jack");
//获取name属性的值
System.out.println("nameValue = " + nameField.get(obj));
}
}
4、反射Method
4.1、代码示例
public class UserService {
//登陆方法
public boolean login(String name,String password){
if("admin".equals(name) && "123".equals(password)){
return true;
}
return false;
}
public void login(int i) {
System.out.println("您已登陆系统");
}
public void logout() {
System.out.println("您已退出系统");
}
}
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
//反射Method
public class Test6 {
public static void main(String[] args) throws ClassNotFoundException {
//获取类
Class userClass = Class.forName("reflect.UserService");
//获取所有的Method,包括私有的
Method[] methods = userClass.getDeclaredMethods();
System.out.println("方法的数量:" + methods.length);
//遍历Method
for (Method method : methods) {
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获取方法的返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取方法名
System.out.println(method.getName());
//获取方法的修饰符列表,一个方法可能有多个
Class[] parametreTypes = method.getParameterTypes();
for (Class parameterType : parametreTypes) {
System.out.println(parameterType.getSimpleName());
}
}
}
}
5、反编译一个类的方法
5.1、代码示例
package reflect;
public class UserService {
//登陆方法
public boolean login(String name,String password){
if("admin".equals(name) && "123".equals(password)){
return true;
}
return false;
}
public void login(int i) {
System.out.println("您已登陆系统");
}
public void logout() {
System.out.println("您已退出系统");
}
}
package reflect;
//反编译一个类的方法
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test7 {
public static void main(String[] args) throws ClassNotFoundException {
//为了拼接字符串
StringBuilder s = new StringBuilder();
Class c = Class.forName("reflect.UserService");
s.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");
//获取所有方法
Method[] methods = c.getDeclaredMethods();
//遍历方法
for (Method method : methods) {
s.append("\t");
//获取修饰符
s.append(Modifier.toString(method.getModifiers()));
s.append(" ");
//获取返回值
s.append(method.getReturnType().getSimpleName());
s.append(" ");
//获取方法名
s.append(method.getName());
s.append(" (");
//获取参数列表
Class[] paramTypes = method.getParameterTypes();
//遍历参数列表
for (Class paramType : paramTypes) {
s.append(paramType.getSimpleName());
s.append(",");
}
//删除指定下标位置上的字符
s.deleteCharAt(s.length()-1);
s.append(") {}\n");
}
s.append("}");
System.out.println(s);
}
}
6、通过反射机制调用类的方法
6.1、示例代码
package reflect;
public class UserService {
//登陆方法
public boolean login(String name,String password){
if("admin".equals(name) && "123".equals(password)){
return true;
}
return false;
}
public void login(int i) {
System.out.println("您已登陆系统");
}
public void logout() {
System.out.println("您已退出系统");
}
}
package reflect;
//通过反射机制调用类的方法
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test8 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("reflect.UserService");
//创建对象
Object obj = c.newInstance();
//获取方法
Method loginMethod = c.getDeclaredMethod("login",String.class,String.class);
//调用方法
Object retValue = loginMethod.invoke(obj,"admin","123123");
System.out.println(retValue);
Method logoutMethod = c.getDeclaredMethod("logout");
System.out.println(logoutMethod.invoke(obj));
}
}
7、反编译一个类的构造方法
7.1、示例代码
package reflect;
//反编译一个构造方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Test9 {
public static void main(String[] args) throws ClassNotFoundException {
//为了拼接字符串
StringBuilder s = new StringBuilder();
Class c = Class.forName("java.lang.String");
s.append(Modifier.toString(c.getModifiers()) + "class" + c.getSimpleName() + "{\n");
//拼接构造方法
Constructor[] constructors = c.getDeclaredConstructors();
for (Constructor constructor : constructors) {
s.append("\t");
//获取修饰符列表
s.append(Modifier.toString(constructor.getModifiers()));
s.append(" ");
//获取构造方法名
s.append(c.getSimpleName());
s.append("(");
//获取参数
Class[] params = constructor.getParameterTypes();
for (Class param : params){
s.append(param.getSimpleName());
s.append(",");
}
//删除多余下标位置上的字符
if (params.length > 0){
s.deleteCharAt(s.length()-1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
}
8、通过反射机制调用构造方法实例化对象
8.1、示例代码
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//通过反射机制实例化对象
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("reflect.VipUser");
//调用无参构造方法实例化对象
Object obj = c.newInstance();
System.out.println("obj:" + obj);
//获取有参构造方法
Constructor con = c.getConstructor(int.class,String.class,String.class,boolean.class);
//调用构造方法创建对象
Object newObj = con.newInstance(110,"jack","2022-03-02",true);
System.out.println("newObj:" + newObj);
//获取无参构造方法
Constructor con2 = c.getConstructor();
Object newObj2 = con2.newInstance();
System.out.println("newObj2:" + newObj2);
}
}
9、获取一个类的父类
9.1、示例代码
package reflect;
//获取一个类的父类方法
public class Test11 {
public static void main(String[] args) throws ClassNotFoundException {
//String类型
Class c = Class.forName("java.lang.Class");
//获取String的父类
Class superClass = c.getSuperclass();
System.out.println("String的父类是:" + superClass.getSimpleName());
//获取String类实现的所有接口
Class[] interfaces = c.getInterfaces();
for (Class in : interfaces){
System.out.println(in.getName());
}
}
}
10、获取文件中的内容
10.1、示例代码
//className=comztt
package reflect;
/*
java.util包下提供了一个资源绑定器,便于获取属性配置文件中的内容。
使用以下这种方式的时候,属性配置文件xxx.properties必须放到类路径下。
*/
import java.util.ResourceBundle;
public class Test12 {
public static void main(String[] args) {
// 资源绑定器,只能绑定xxx.properties文件,并且这个文件必须在类路径下,文件扩展名也必须是properties
// 并且在写路径的时候,路径后面的扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("reflect/db");
String className = bundle.getString("className");
System.out.println(className);
}
}