目录
(1)启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器,底层是c++,最顶层
(2)平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块
(3)系统类加载器(System Classloader):负责加载用户类路径上所指定的类库,也称为应用程序类加载器
类加载器:负责将.class文件(存储的物理文件)加载在到内存中
类在什么时候会被加载到内存中?
创建类的实例(对象)
调用类的类方法(静态方法)
访问类/接口的类变量,或者为该类变量赋值(静态变量)
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
总结:用到就加载,不用不加载
加载:
验证:
准备
解析
初始化
通过一个类的全限定名来获取此类的二进制字节流(通过包名+类名【全限定名】,获取这个类,准备用流进行传输)
将这个字节流所代表的静态存储结构转化为运行时数据结构(通过上步得到的流,将其字节码文件加载到内存中)
在内存中生成一个代表这个类的java.lang.Class对象(类加载到内存之后,虚拟机会创建一个该类的class对象来存储类中对应的内容)
任何类被使用时,系统都会为之建立一个java.lang.Class对象
确保Class文件字节流中包含的信息符合当前虚拟机的要求,且不会危害虚拟机本身(检查文件中的信息是否符合虚拟机的规范,有没有安全隐患)
负责为类的类变量(static修饰的变量)分配内存,并设置默认初始化值(初始化静态变量)
将类的二进制数据流中的符号引用替换为直接引用(如果本类中用到了其他的类,此时需要找到其对应的类)
根据程序员通过程序制定的主观计划去初始化类变量和其他资源(静态变量赋值以及初始化其他资源)
类加载器之间的层次关系,称之为类加载器的双亲委派模型
在这个模型当中,要求除了顶层的启动类加载器之外,其余的类加载器都应该有自己的父类加载器
这里的父子关系是逻辑上的继承,如想用自定义类加载器加载一个字节码文件,首先,它不会自己去尝试加载,而是将加载任务委派给其父类加载器去完成
一直委托到最顶层,这些加载器都有其各自的加载范围,当父类加载器无法完成这个加载请求的时候,它就会一层一层的往下返回,直到返回到能完成加载
的类加载器中,完成加载请求
//获取系统类加载器
classLoader systemclassLoader = classLoader.getSystemclassLoader():
//获取系统类加载器的父加载器,平台类加载器
ClassLoader classLoader1 = systemClassLoader.getParent();
//获取平台类加载器的父加载器 --- 启动类加载器
ClassLoader classLoader2 = classLoader1.getparent();
system.out.println("系统类加载器+ systemClassLoader);
system.out.printIn("平台类加载器”+ classLoader1);
System.out.printIn("系统类加载器”+ classLoader2);
方法名 | 说明 |
---|---|
static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
InputStream getResourceAsStream(String name) | 加载某一个资源文件 参数:文件路径 返回值:字节流对象 |
Java反射机制:
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
对于任意一个对象都能够调用它的任意属性和方法;
这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制
Java反射机制(简洁说明):
无视修饰符获取类里面所有的属性和方法先获取配置文件中的信息
动态获取信息并创建对象和调用方法
普通方式创建对象
无法访问私有属性和方法
用反射创建对象
反射调用私有属性:能无视权限修饰符
反射调用私有方法:能无视权限修饰符
总结:利用反射调用它类中的属性和方法时,能无视修饰符
举例:
如果用户有1个需求,并调用其特定方法
接收到程序后又更改需求n次
普通方式:
创建对象1,写其特有方法,get,set,构造,toString,在主方法中创建对象1,调用对象1的方法,再将代码打包发送,之后接收到第一次需求更改消息
创建对象2,写其特有方法,get,set,构造,toString,在主方法中删除对象1和其方法调用,重新创建对象2,调用对象2的方法,再将代码打包发送,之后接收到第二次需求更改消息
创建对象3,写其特有方法,get,set,构造,toString,在主方法中删除对象2和其方法调用,重新创建对象3,调用对象3的方法,再将代码打包发送,之后接收到第三次需求更改消息
...
创建对象n,写其特有方法,get,set,构造,toString,在主方法中删除对象,n-1和其方法调用,重新创建对象n,调用对象n的方法,再将代码打包发送,之后接收到第N次需求更改消息
总结:不灵活,需求更改要改代码
反射方式:动态获取信息,动态调用对象方法
会先将用户所有可能的需求全部过一遍,然后创建n个对象
创建对象1,写好特定方法,get,set,构造,toString,
创建对象2,写好特定方法,get,set,构造,toString,
创建对象3,写好特定方法,get,set,构造,toString,
...
创建对象n,写好特定方法
然后写一个配置文件
配置文件:
要创建对象的全类名(全限定名)
要调用的方法名
在主方法中读取配置文件的信息,读到什么就创建什么对象,读到什么方法就调用什么方法
用户更改需求时,不需要更改主方法中的代码,修改配置文件即可
总结:灵活
利用class对象来创建的
加载前(源代码阶段):用Class的静态方法forName(String 全类名)
已经进入到内存中(Class对象阶段):直接类名.class即可
已经手动创建对象时new 对象名(运行时阶段):对象.getClass()
public class User {
? ?private String name;
? ?private Integer age;
?
? ?public User() {
? }
?
? ?public User(String name, Integer age) {
? ? ? ?this.name = name;
? ? ? ?this.age = age;
? }
?
? ?public String getName() {
? ? ? ?return name;
? }
?
? ?public void setName(String name) {
? ? ? ?this.name = name;
? }
?
? ?public Integer getAge() {
? ? ? ?return age;
? }
?
? ?public void setAge(Integer age) {
? ? ? ?this.age = age;
? }
?
? ?private void run(){
? ? ? ?System.out.println("User is running");
? }
? ?@Override
? ?public String toString() {
? ? ? ?return "User{" +
? ? ? ? ? ? ? ?"name='" + name + '\'' +
? ? ? ? ? ? ? ?", age=" + age +
? ? ? ? ? ? ? ?'}';
? }
}
public class Reflection01 {
? ?public static void main(String[] args) {
? ? ? ?//第一种
? ? ? ?Class userClass1 = null;
? ? ? ?Class userClass2 = null;
? ? ? ?Class userClass3 = null;
? ? ? ?try {
? ? ? ? ?userClass1 = Class.forName("reflection.User");
? ? ? ? ?System.out.println(userClass1);
? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ?e.printStackTrace();
? ? ? }
?
? ? ? ?//第二种
? ? ? ?userClass2 = User.class;
? ? ? ?System.out.println(userClass2);
?
? ? ? ?//第三种
? ? ? ?userClass3 ?= new User().getClass();
? ? ? ?System.out.println(userClass3);
? ? ? ?
//检查
? ? ? ?System.out.println(userClass1 == userClass2);
? ? ? ?System.out.println(userClass1 == userClass3);
? ? ? ?System.out.println(userClass2 == userClass3);
?
? }
}
方法名 | 返回值类型 | 说明 |
---|---|---|
getConstructors() | Constructor<?>[] | 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 class对象表示的类的所有公共构造函数 |
getDeclaredConstructors() | Constructor<?>[] | 返回反映由该 class对象表示的类声明的所有构造函数的 constructor对象的数组。 |
getConstructor(Class<?> ... parameterTypes) | Constructor< T > | 返回一个 constructor对象,该对象反映由该 class对象表示的类的指定公共构造函数。 |
getDeclaredConstructor(Class<?> ... parameterTypes) | Constructor< T > | 返回一个 Constructor对象,该对象反映由此 class对象表示的类或接口的指定构造函数。 |
getFields() | Field[ ] | 返回所有公共成员变量对象的数组 |
getDeclaredFields() | Field[ ] | 返回所有成员变量对象的数组 |
getField(String name) | Field | 返回单个公共成员变量对象 |
getDeclaredField(String name) | Field | 返回单个成员变量对象 |
getMethods() | Method[ ] | 返回所有公共成员方法对象的数组,包括继承的 |
getDeclaredMethods() | Method[ ] | 返回所有成员方法对象的数组,不包括继承的 |
getMethod(String name, Class<?>... parameterTypes) | Method | 返回单个公共成员方法对象 |
getDeclaredMethod(String name, Class<?>... parameterTypes) | Method | 返回单个成员方法对象 |
User对象
public class User {
? ?private String name;
? ?private Integer age;
? ?public Long id;
?
?
?
? ?public User() {
? }
?
? ?public User(String name, Integer age) {
? ? ? ?this.name = name;
? ? ? ?this.age = age;
? }
?
? ?private User(String name){
? ? ? ?this.name = name;
? }
?
? ?public User(String name, Integer age, Long id) {
? ? ? ?this.name = name;
? ? ? ?this.age = age;
? ? ? ?this.id = id;
? }
?
? ?public String getName() {
? ? ? ?return name;
? }
?
? ?public void setName(String name) {
? ? ? ?this.name = name;
? }
?
? ?public Integer getAge() {
? ? ? ?return age;
? }
?
? ?public void setAge(Integer age) {
? ? ? ?this.age = age;
? }
?
? ?public Long getId() {
? ? ? ?return id;
? }
?
? ?public void setId(Long id) {
? ? ? ?this.id = id;
? }
?
? ?private void run(){
? ? ? ?System.out.println("User is running");
? }
? ?private void run(String name,Long id){
? ? ? ?System.out.println("id为"+id+"的用户:"+name+" is running");
? }
? ?private String run(String name,Long id,Integer age){
? ? ? ?return "id为"+id+"的用户:"+name+"年龄:"+age+" is running";
? }
?
? ?public void work(){
? ? ? ?System.out.println("User is working");
? }
? ?public void work(String name){
? ? ? ?System.out.println(name + " is working");
? }
?
? ?public String work(String name,Long id){
? ? ? ?return "id为"+id+"的用户:"+name+" is working";
? }
?
? ?@Override
? ?public String toString() {
? ? ? ?return "User{" +
? ? ? ? ? ? ? ?"name='" + name + '\'' +
? ? ? ? ? ? ? ?", age=" + age +
? ? ? ? ? ? ? ?", id=" + id +
? ? ? ? ? ? ? ?'}';
? }
}
?
测试:
public class Reflection02 {
? ?public static void main(String[] args) {
? ? ? ?Class<User> userClass = User.class;
? ? ? ?Constructor<?>[] constructors01 = userClass.getConstructors();
?
? ? ? ?for (int i = 0; i < constructors01.length; i++) {
? ? ? ? ? ?System.out.println(constructors01[i]);
? ? ? }
? ? ? ?System.out.println("----------------------------------------------------");
? ? ? ?Constructor<?>[] constructors02 = userClass.getDeclaredConstructors();
? ? ? ?for (int i = 0; i < constructors02.length; i++) {
? ? ? ? ? ?System.out.println(constructors02[i]);
? ? ? }
? }
}
方法名 | 返回值类型 | 说明 |
---|---|---|
T newInstance(Object... initargs) | 创建出来的对象 | 根据指定的构造方法创建对象 |
public class Reflection03 {
? ?public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?//利用有参构造创建User对象
? ? ? ?method01();
? ? ? ?//利用无参构造创建User对象
? ? ? ?method02();
?
? ? ? ?//空参简写
? ? ? ?method03();
?
? ? ? ?//利用私有构造创建User对象,(暴力反射)
? ? ? ?method04();
? }
?
? ?private static void method04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?Class<?> userClass = Class.forName("reflection.User");
? ? ? ?final Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class);
? ? ? ?//被private修饰的是不能直接使用的
? ? ? ?//如果用反射强行获取需要临时取消访问检查
? ? ? ?declaredConstructor.setAccessible(true);
? ? ? ?User user = (User) declaredConstructor.newInstance("san");
? ? ? ?System.out.println(user);
? }
?
? ?private static void method03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
? ? ? ?Class<?> userClass = Class.forName("reflection.User");
? ? ? ?//在Class类中,有一个newInstance方法,可以利用空参直接创建对象
? ? ? ?//此方法已过时,替换为getDeclaredConstructor().newInstance()
? ? ? ?User user1 = (User)userClass.newInstance();
? ? ? ?User user2 = (User)userClass.getDeclaredConstructor().newInstance();
? ? ? ?System.out.println(user1);
? ? ? ?System.out.println(user2);
?
? }
?
? ?private static void method02() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?Class<?> userClass = Class.forName("reflection.User");
? ? ? ?Constructor<?> constructor = userClass.getConstructor();
? ? ? ?User user1 = (User) constructor.newInstance();
? ? ? ?System.out.println(user1);
? }
?
? ?private static void method01() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
? ? ? ?Class<?> userClass = Class.forName("reflection.User");
? ? ? ?Constructor<?> constructor = userClass.getConstructor(String.class, Integer.class);
?
? ? ? ?User user2 = (User) constructor.newInstance("小明", 29);
?
? ? ? ?System.out.println(user2);
? }
}
方法名 | 返回值类型 | 说明 |
---|---|---|
set(Object object,Object value) | void | 给指定对象的成员变量赋值 |
get(Object obj) | Object | 返回指定对象的Field的值 |
获取class对象
获得Field对象
赋值或获取值
public class Reflection04 {
? ?public static void main(String[] args) throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
? ? ? ?Class<User> userClass = User.class;
// ? ? ? method01(userClass);
// ? ? ? method02(userClass);
// ? ? ? method03(userClass);
// ? ? ? method04(userClass);
// ? ? ? method05(userClass);
? ? ? ?method06(userClass);
?
?
? }
?
? ?private static void method06(Class<User> userClass) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?Field name = userClass.getDeclaredField("name");
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?//取消访问检查
? ? ? ?name.setAccessible(true);
? ? ? ?//更改值
? ? ? ?name.set(user,"小明");
? ? ? ?//获取值
? ? ? ?Object o = name.get(user);
?
?
? ? ? ?System.out.println(user);
? ? ? ?System.out.println(o);
? }
?
? ?private static void method05(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
? ? ? ?Field id = userClass.getDeclaredField("id");
?
? ? ? ?//利用set方法赋值
? ? ? ?//先创建一个User对象
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?//获得对象之后就可以赋值
? ? ? ?id.set(user,1000L);
? ? ? ?System.out.println(user);
?
? }
?
? ?private static void method04(Class<User> userClass) throws NoSuchFieldException {
? ? ? ?final Field name = userClass.getDeclaredField("name");
? ? ? ?System.out.println(name);
? }
?
? ?private static void method03(Class<User> userClass) throws NoSuchFieldException {
? ? ? ?//想要获取到的成员变量必须是真实存在的,且必须是public修饰的
? ? ? ?Field id = userClass.getField("id");
?
? ? ? ?System.out.println(id);
? }
?
? ?private static void method02(Class<?> userClass) {
? ? ? ?for (Field declaredField : userClass.getDeclaredFields()) {
? ? ? ? ? ?System.out.println(declaredField);
? ? ? }
? }
?
? ?private static void method01(Class<?> userClass) {
?
? ? ? ?Field[] fields = userClass.getFields();
? ? ? ?for (Field field : fields) {
? ? ? ? ? ?System.out.println(field);
? ? ? }
? }
}
方法名 | 返回值类型 | 说明 |
---|---|---|
invoke(Object o,Object... args) 参数一:用o对象调用该方法 参数二:调用方法的传递的参数(如果没有就不用写) | Object | 在具有指定参数的指定对象上调用此 方法 对象表示的基础方法。 调用方法 |
获取class对象
获取Method对象
运行方法
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
?
public class Reflection05 {
? ?public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?Class<User> userClass = User.class;
? ? ? ?//获取所有公共成员方法
? ? ? ?method01(userClass);
? ? ? ?System.out.println("--------------------------------");
? ? ? ?//获取所有成员方法(包括继承的)
? ? ? ?method02(userClass);
? ? ? ?System.out.println("--------------------------------");
? ? ? ?//获取单个公开成员方法
? ? ? ?method03(userClass);
? ? ? ?//获取单个成员方法
? ? ? ?method04(userClass);
?
?
?
? ? ? ?//运行成员方法
? ? ? ?//运行公开成员方法(无参无返回值)
? ? ? ?method05(userClass);
? ? ? ?//运行公开成员方法(有参无返回值)
? ? ? ?method06(userClass);
? ? ? ?//运行成员方法(无参无返回值)
? ? ? ?method07(userClass);
? ? ? ?//运行成员方法(有参无返回值)
? ? ? ?method08(userClass);
? ? ? ?//运行公开成员方法(有返回值)
? ? ? ?method09(userClass);
?
? ? ? ?//运行成员方法(有返回值)
? ? ? ?method10(userClass);
?
?
? }
?
? ?private static void method10(Class<User> userClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method run = userClass.getDeclaredMethod("run", String.class, Long.class, Integer.class);
? ? ? ?run.setAccessible(true);
? ? ? ?String invoke = (String) run.invoke(user, "小王", 201L,10);
? ? ? ?System.out.println(invoke);
? }
?
? ?private static void method09(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method work = userClass.getMethod("work", String.class, Long.class);
? ? ? ?work.setAccessible(true);
? ? ? ?String invoke = (String) work.invoke(user, "小王", 200L);
? ? ? ?System.out.println(invoke);
? }
?
? ?private static void method08(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method run = userClass.getDeclaredMethod("run",String.class,Long.class);
? ? ? ?run.setAccessible(true);
? ? ? ?run.invoke(user,"小王",200L);
? }
?
? ?private static void method07(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method run = userClass.getDeclaredMethod("run");
? ? ? ?run.setAccessible(true);
? ? ? ?run.invoke(user);
? }
?
? ?private static void method06(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method work = userClass.getMethod("work",String.class);
? ? ? ?work.invoke(user,"小明");
? }
?
? ?private static void method05(Class<User> userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
? ? ? ?User user = userClass.getDeclaredConstructor().newInstance();
? ? ? ?Method work = userClass.getMethod("work");
? ? ? ?work.invoke(user);
? }
?
? ?private static void method04(Class<User> userClass) throws NoSuchMethodException {
? ? ? ?Method run = userClass.getDeclaredMethod("run", String.class, Long.class);
? ? ? ?System.out.println(run);
? }
?
? ?private static void method03(Class<User> userClass) throws NoSuchMethodException {
? ? ? ?Method work = userClass.getMethod("work");
? ? ? ?System.out.println(work);
? }
?
? ?private static void method02(Class<User> userClass) {
? ? ? ?Method[] declaredMethods = userClass.getDeclaredMethods();
? ? ? ?for (Method declaredMethod : declaredMethods) {
? ? ? ? ? ?System.out.println(declaredMethod);
? ? ? }
? }
?
? ?private static void method01(Class<User> userClass) {
? ? ? ?Method[] methods = userClass.getMethods();
? ? ? ?for (Method method : methods) {
? ? ? ? ? ?System.out.println(method);
? ? ? }
? }
?
}