反射机制概述
是一套类库
反射机制是JDK中的一套类库,这套类库可以帮助我们操作/读取 class 字节码文件。
后期学习的大量的java框架,底层都是基于反射机制实现的,所以必须掌握(要能够数量的使用反射机制中的方法)。
反射机制可以让程序更加灵活。怎么灵活????
反射机制最核心的几个类:
1 2 3 4
| java.lang.Class:Class类型的实例代表硬盘上的某个class文件。或者说代表某一种类型。 java.lang.reflect.Filed:Filed类型的实例代表类中的属性/字段 java.lang.reflect.Constructor: Constructor类型的实例代表类中的构造方法 java.lang.reflect.Method: Method类型的实例代表类中的方法
|
反射机制的缺点:容易打破封装
获取Class
- 在java语言中获取Class的三种方式:
==某种类型的字节码文件在内存当中只有一份==
1 2 3 4 5 6 7 8 9 10 11 12 13
| Class userClass = Class.forName("com.powernode.javase.reflect.User");
String s1 = "动力节点"; Class stringClass2 = s1.getClass();
System.out.println(stringClass == stringClass2);
User user = new User("zhangsan", 20); Class userClass2 = user.getClass(); System.out.println(userClass2 == userClass);
|
第一种方式:Class c = Class.forName(“完整的全限定类名”);
注意:
- 1.全限定类名是带有包名的。
- 2.是lang包下的,java.lang也不能省略。
- 3.这是个字符串参数。
- 4.如果这个类根本不存在,运行时会报异常:java.lang.ClassNotFoundException
- 5.这个方法的执行会导致类的加载动作的发生。、
1 2 3 4 5 6
|
Class stringClass = Class.forName("java.lang.String");
Class userClass = Class.forName("com.powernode.javase.reflect.User");
|
第二种方式:Class c = obj.getClass();
注意:这个方法是通过引用去调用的。
1 2 3 4 5 6 7
| String s1 = "动力节点"; Class stringClass2 = s1.getClass();
System.out.println(stringClass == stringClass2);
|
第三种方式:在java语言中,任何一种类型,包括基本数据类型,都有 .class 属性。用这个属性可以获取Class实例。
1 2 3 4 5
| Class intClass = int.class; Class doubleClass = double.class; Class stringClass3 = String.class; Class userClass3 = User.class;
|
第四种方式:①通过类加载器获取
1 2 3
| ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class clazz = classLoader.loadClass(“全限定类名”);
|
类加载器也是对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class<?> aClass = systemClassLoader.loadClass("com.powernode.javase.reflect.User");
System.out.println(aClass.newInstance());
|
Class.forName和classLoader.loadClass()的区别?
==Class.forName():类加载时会进行初始化。==
==classLoader.loadClass():类加载时不会进行初始化,直到第一次使用该类。==
反射作用的体现
实例化对象
1 2 3 4 5 6 7 8
|
Class userClass = Class.forName("com.powernode.javase.reflect.User");
User user = (User)userClass.newInstance();
|
读取属性配置文件
==读取属性配置文件,获取类名,通过反射机制实例化对象。==
通过这个案例的演示就知道反射机制是灵活的。这个程序可以做到对象的动态创建。
只要修改属性配置文件就可以完成不同对象的实例化。
classObj.newInstance();已经过时
1 2 3 4 5 6 7 8 9 10 11 12 13
| ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.javase.reflect.classInfo");
String className = bundle.getString("className");
Class classObj = Class.forName(className);
Object obj = classObj.newInstance();
System.out.println(obj);
|
反射Field
==关于反射机制中的 java.lang.reflect.Field(代表的是一个类中的字段/属性)==
Field[] fields = vipClass.getDeclaredFields();
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Vip { // Field public String name;
private int age;
protected String birth;
boolean gender;
public static String address = "北京海淀";
public static final String GRADE = "金牌"; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| Class vipClass = Class.forName("com.powernode.javase.reflect.Vip");
Field[] fields = vipClass.getDeclaredFields();
for(Field field : fields){ System.out.println(field.getName()); Class fieldType = field.getType(); System.out.println(fieldType.getSimpleName()); System.out.println(Modifier.toString(field.getModifiers())); }
|
==System.out.println(Modifier.toString(field.getModifiers()));==
反编译(反射)类的字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| Class stringClass = Class.forName("com.powernode.javase.reflect.Vip");
StringBuilder sb = new StringBuilder();
sb.append(Modifier.toString(stringClass.getModifiers()));
sb.append(" class ");
sb.append(stringClass.getName());
sb.append(" extends ");
sb.append(stringClass.getSuperclass().getName());
Class[] interfaces = stringClass.getInterfaces(); if(interfaces.length > 0){ sb.append(" implements "); for (int i = 0; i < interfaces.length; i++) { Class interfaceClass = interfaces[i]; sb.append(interfaceClass.getName()); if(i != interfaces.length - 1){ sb.append(","); } } }
sb.append("{\n");
Field[] fields = stringClass.getDeclaredFields(); for (Field field : fields){ sb.append("\t"); sb.append(Modifier.toString(field.getModifiers())); sb.append(" "); sb.append(field.getType().getName()); sb.append(" "); sb.append(field.getName()); sb.append(";\n"); }
sb.append("}");
System.out.println(sb);
|
通过反射机制如何访问Field,如何给属性赋值,如何读取属性的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| Customer customer = new Customer();
customer.name = "张三";
System.out.println(customer.name);
Class clazz = Class.forName("com.powernode.javase.reflect.Customer");
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(customer, 30);
System.out.println("年龄:" + ageField.set(customer, 30););
Field nameField = clazz.getDeclaredField("name");
nameField.set(customer, "李四");
System.out.println(nameField.get(customer));
|
1.获取类
1
| Class clazz = Class.forName("com.powernode.javase.reflect.Customer");
|
2.获取相对于的field
1
| Field ageField = clazz.getDeclaredField("age");
|
3.调用方法打破封装
1 2 3
| ageField.setAccessible(true);
|
4.修改属性的值
1
| ageField.set(customer, 30);
|
5.读取属性的值
反射Method
反编译(反射)类的Method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class UserService {
public boolean login(String username, String password){
return "admin".equals(username) && "123456".equals(password); }
public String concat(String s1, String s2, String s3){ return s1 + s2 + s3; }
public void logout(){ System.out.println("系统已安全退出!"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| Class clazz = Class.forName("com.powernode.javase.reflect.UserService");
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods){ System.out.println(Modifier.toString(method.getModifiers())); System.out.println(method.getReturnType().getName()); System.out.println(method.getName());
Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters){ System.out.println(parameter.getType().getName()); System.out.println(parameter.getName()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
public class ReflectTest09 { public static void main(String[] args) throws Exception{ StringBuilder sb = new StringBuilder(); Class stringClass = Class.forName("com.powernode.javase.reflect.UserService"); sb.append(Modifier.toString(stringClass.getModifiers())); sb.append(" class "); sb.append(stringClass.getName()); sb.append(" extends "); sb.append(stringClass.getSuperclass().getName()); Class[] interfaces = stringClass.getInterfaces(); if(interfaces.length > 0){ sb.append(" implements "); for (int i = 0; i < interfaces.length; i++) { sb.append(interfaces[i].getName()); if(i != interfaces.length - 1){ sb.append(","); } } } sb.append("{\n");
Method[] methods = stringClass.getDeclaredMethods(); for(Method method : methods){ sb.append("\t"); sb.append(Modifier.toString(method.getModifiers())); sb.append(" "); sb.append(method.getReturnType().getName()); sb.append(" "); sb.append(method.getName()); sb.append("("); Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; sb.append(parameter.getType().getName()); sb.append(" "); sb.append(parameter.getName()); if(i != parameters.length - 1){ sb.append(","); } } sb.append("){}\n"); }
sb.append("}");
System.out.println(sb);
} }
|
用反射调用类的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
UserService userService = new UserService();
boolean isSuccess = userService.login("admin", "123456"); System.out.println(isSuccess ? "登录成功" : "登录失败");
userService.logout();
Class clazz = Class.forName("com.powernode.javase.reflect.UserService");
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);
Object retValue = loginMethod.invoke(userService, "admin", "123456"); System.out.println(retValue);
Method logoutMethod = clazz.getDeclaredMethod("logout"); logoutMethod.invoke(userService);
Class clazz = Class.forName("com.powernode.javase.reflect.UserService");
|
1.获取login方法(提供方法名,提供形参列表)
1
| Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);
|
2.调用login方法()
1 2 3
| Object retValue = loginMethod.invoke(userService, "admin", "123456"); System.out.println(retValue);
|
3.调用logout方法
1 2
| Method logoutMethod = clazz.getDeclaredMethod("logout"); logoutMethod.invoke(userService);
|
反射Constructor
通过反射机制获取一个类中所有的构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| StringBuilder sb = new StringBuilder(); Class clazz = Class.forName("java.lang.String"); sb.append(Modifier.toString(clazz.getModifiers())); sb.append(" class "); sb.append(clazz.getName()); sb.append(" extends "); sb.append(clazz.getSuperclass().getName()); Class[] interfaces = clazz.getInterfaces(); if(interfaces.length > 0) { sb.append(" implements "); for (int i = 0; i < interfaces.length; i++) { sb.append(interfaces[i].getName()); if(i != interfaces.length - 1){ sb.append(","); } } } sb.append("{\n");
Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor con : cons){ sb.append("\t"); sb.append(Modifier.toString(con.getModifiers())); sb.append(" "); sb.append(con.getName()); sb.append("(");
Parameter[] parameters = con.getParameters(); for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; sb.append(parameter.getType().getName()); sb.append(" "); sb.append(parameter.getName()); if(i != parameters.length - 1){ sb.append(","); } }
sb.append("){}\n"); }
sb.append("}");
System.out.println(sb); }
|
通过反射机制调用构造方法来创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| Order order1 = new Order(); System.out.println(order1);
Order order2 = new Order("1111122222", 3650.5, "已完成"); System.out.println(order2);
Class clazz = Class.forName("com.powernode.javase.reflect.Order");
Constructor defaultCon = clazz.getDeclaredConstructor();
Object obj = defaultCon.newInstance(); System.out.println(obj);
Constructor threeArgsCon = clazz.getDeclaredConstructor(String.class, double.class, String.class);
Object obj1 = threeArgsCon.newInstance("5552454222", 6985.0, "未完成"); System.out.println(obj1);
|
1. 通过反射机制来实例化对象?
1
| Class clazz = Class.forName("com.powernode.javase.reflect.Order");
|
2. 获取Order的无参数构造方法
1
| Constructor defaultCon = clazz.getDeclaredConstructor();
|
3. 获取三个参数的构造方法
1
| Constructor threeArgsCon = clazz.getDeclaredConstructor(String.class, double.class, String.class);
|
4.调用无参数构造方法实例化对象
1 2
| Object obj = defaultCon.newInstance(); System.out.println(obj);
|
5.调用三个参数的构造方法
1 2
| Object obj1 = threeArgsCon.newInstance("5552454222", 6985.0, "未完成"); System.out.println(obj1);
|
模拟框架的部分实现
config.properties
1 2 3 4
| className=com.powernode.javase.reflect.UserService methodName=concat parameterTypes=java.lang.String,java.lang.String,java.lang.String parameterValues=abc,def,xyz
|
模拟框架的部分代码。通过读取属性配置文件,获取类信息,方法信息,然后通过反射机制调用方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| ResourceBundle bundle = ResourceBundle.getBundle("com.powernode.javase.reflect.config"); String className = bundle.getString("className"); String methodName = bundle.getString("methodName"); String parameterTypes = bundle.getString("parameterTypes"); String parameterValues = bundle.getString("parameterValues");
Class<?> clazz = Class.forName(className); Constructor<?> defaultCon = clazz.getDeclaredConstructor(); Object obj = defaultCon.newInstance();
String[] strParameterTypes = parameterTypes.split(","); Class[] classParameterTypes = new Class[strParameterTypes.length]; for (int i = 0; i < strParameterTypes.length; i++) { classParameterTypes[i] = Class.forName(strParameterTypes[i]); } Method method = clazz.getDeclaredMethod(methodName, classParameterTypes);
Object retValue = method.invoke(obj, parameterValues.split(","));
System.out.println(retValue);
|
类加载及双亲委派机制
类的加载过程
①装载(loading)
类加载器负责将类的class文件读入内存,并创建一个java.lang.Class对象
②连接(linking)
1.验证(Verify)
2.准备(Prepare)
1 2 3 4 5
| 正式为静态变量在方法区中开辟存储空间并设置默认值
public static int k = 10; 此时:k会赋值0
public static final int f = 10; 此时: f会赋值10
|
3.解析(Resolve)
1
| 将虚拟机常量池内的符号引用替换为直接引用(地址)的过程。
|
③初始化(initialization)
低版本的JDK中类加载器的名字:
启动类加载器:负责加载rt.jar
扩展类加载器:ext/*.jar
系统类加载器:classpath
类加载器
①虚拟机内部提供了三种类加载器(Java9+):
- 启动类加载器(BootstrapClassLoader):加载Java最核心的类,例如String
- 平台类加载器(PlatformClassLoader):加载Java平台扩展的类库,例如解析XML的
- 应用类加载器(AppClassLoader):加载classpath中的自己写的 (系统类加载器/应用类加载器 )
- 同时我们还可以自定义一个类加载器(UserClassLoader)用户类加载器
②获取类加载器可以通过 getParent()方法一级一级获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ClassLoader appClassLoader = ReflectTest15.class.getClassLoader(); System.out.println("应用类加载器:" + appClassLoader);
ClassLoader appClassLoader2 = ClassLoader.getSystemClassLoader(); System.out.println("应用类加载器:" + appClassLoader2);
ClassLoader appClassLoader3 = Thread.currentThread().getContextClassLoader(); System.out.println("应用类加载器:" + appClassLoader3);
System.out.println("平台类加载器:" + appClassLoader.getParent());
System.out.println("启动类加载器:" + appClassLoader.getParent().getParent())
|
启动类加载器
1
| System.out.println("启动类加载器:" + appClassLoader.getParent().getParent())
|
平台类加载器
1
| System.out.println("平台类加载器:" + appClassLoader.getParent());
|
应用类加载器
1 2 3
| ClassLoader appClassLoader = ReflectTest15.class.getClassLoader(); ClassLoader appClassLoader2 = ClassLoader.getSystemClassLoader(); ClassLoader appClassLoader3 = Thread.currentThread().getContextClassLoader();
|
双亲委派机制
①某个类加载器接收到加载类的任务时,通常委托给“父 类加载”完成加载。
②最“父 类加载器”无法加载时,一级一级向下委托加载任务。
③作用:
保护程序的安全。
防止类加载重复。
通过反射获取父类的泛型
1.Animal
1 2 3 4 5 6 7 8
|
public class Animal<X, Y, Z> { }
|
2.cat
1 2
| public class Cat extends Animal<String, Integer, Double>{ }
|
3.获取父类的泛型(x,y,z)Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public class Test { public static void main(String[] args) { Class<Cat> catClass = Cat.class;
Type genericSuperclass = catClass.getGenericSuperclass();
if(genericSuperclass instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } } } }
|
通过反射获取接口的泛型
1.flyable
1 2
| public interface Flyable<X, Y> { }
|
2.Mouse
1 2 3 4 5 6
| public class Mouse implements Flyable<String, Integer>, Comparable<Mouse>{ @Override public int compareTo(Mouse o) { return 0; } }
|
3.获取Type[] genericInterfaces = mouseClass.getGenericInterfaces();
1 2 3 4 5 6 7 8 9 10 11 12 13
| Class<Mouse> mouseClass = Mouse.class;
Type[] genericInterfaces = mouseClass.getGenericInterfaces(); for (Type g : genericInterfaces) { if(g instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) g; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } } }
|
通过反射获取属性的泛型
1.user
1 2 3
| public class User { private Map<Integer, String> map; }
|
2.获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Test { public static void main(String[] args) throws Exception{ Class<User> userClass = User.class; Field mapField = userClass.getDeclaredField("map"); Type genericType = mapField.getGenericType(); if(genericType instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericType; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } } } }
|
通过反射获取方法参数的泛型
1.Myclass
1 2 3 4 5 6 7
| public class MyClass {
public Map<Integer, Integer> m(List<String> list, List<Integer> list2){ return null; }
}
|
2.获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| Class<MyClass> myClassClass = MyClass.class;
Method mMethod = myClassClass.getDeclaredMethod("m", List.class, List.class);
Type[] genericParameterTypes = mMethod.getGenericParameterTypes(); for(Type g : genericParameterTypes){ if(g instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) g; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } } }
Type genericReturnType = mMethod.getGenericReturnType(); if(genericReturnType instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) genericReturnType; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } }
|
通过反射获取构造函数的泛型
1 2
| public User(Map<String ,Integer> map){ }
|
1 2 3 4 5 6 7 8 9 10 11 12
| Class<User> userClass = User.class; Constructor<User> con = userClass.getDeclaredConstructor(Map.class); Type[] genericParameterTypes = con.getGenericParameterTypes(); for(Type g :genericParameterTypes){ if(g instanceof ParameterizedType){ ParameterizedType parameterizedType = (ParameterizedType) g; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for(Type a : actualTypeArguments){ System.out.println(a.getTypeName()); } } }
|