Java基础进阶01-类加载器,反射

目录

一、类加载器

1.概述

2.过程

(1)类加载时机

(2)类加载过程

加载

验证

准备

解析

初始化

3.分类

(1)启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器,底层是c++,最顶层

(2)平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块

(3)系统类加载器(System Classloader):负责加载用户类路径上所指定的类库,也称为应用程序类加载器

(4)自定义类加载器(这是自定的,用的不多)

4.双亲委派模型

5.常用方法

二、反射

1.概述

2.作用

3.反射的操作

(1)获取Class对象

(2)class对象的内部结构

(3)Class类中的常用方法

(4)获取Constructor对象

(5)Constructor类常用方法

(6)利用其构造对象创建User对象

(7)Filed类中常用方法

(8)通过反射获取成员变量

(9)Method类的常用方法

(10)通过反射获取成员方法并运行


一、类加载器

1.概述

类加载器:负责将.class文件(存储的物理文件)加载在到内存中

2.过程

(1)类加载时机

类在什么时候会被加载到内存中?

  • 创建类的实例(对象)

  • 调用类的类方法(静态方法)

  • 访问类/接口的类变量,或者为该类变量赋值(静态变量)

  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

  • 初始化某个类的子类

  • 直接使用java.exe命令来运行某个主类

总结:用到就加载,不用不加载

(2)类加载过程
  • 加载:

  • 验证:

  • 准备

  • 解析

  • 初始化

Java基础进阶01-类加载器,反射_第1张图片

加载
  • 通过一个类的全限定名来获取此类的二进制字节流(通过包名+类名【全限定名】,获取这个类,准备用流进行传输)

  • 将这个字节流所代表的静态存储结构转化为运行时数据结构(通过上步得到的流,将其字节码文件加载到内存中)

  • 在内存中生成一个代表这个类的java.lang.Class对象(类加载到内存之后,虚拟机会创建一个该类的class对象来存储类中对应的内容)

任何类被使用时,系统都会为之建立一个java.lang.Class对象

验证
  • 确保Class文件字节流中包含的信息符合当前虚拟机的要求,且不会危害虚拟机本身(检查文件中的信息是否符合虚拟机的规范,有没有安全隐患)

准备
  • 负责为类的类变量(static修饰的变量)分配内存,并设置默认初始化值(初始化静态变量)

解析
  • 将类的二进制数据流中的符号引用替换为直接引用(如果本类中用到了其他的类,此时需要找到其对应的类)

初始化
  • 根据程序员通过程序制定的主观计划去初始化类变量和其他资源(静态变量赋值以及初始化其他资源)

3.分类

(1)启动类加载器(Bootstrap ClassLoader):虚拟机内置的类加载器,底层是c++,最顶层
(2)平台类加载器(Platform Classloader):负责加载JDK中一些特殊的模块
(3)系统类加载器(System Classloader):负责加载用户类路径上所指定的类库,也称为应用程序类加载器
(4)自定义类加载器(这是自定的,用的不多)

4.双亲委派模型

类加载器之间的层次关系,称之为类加载器的双亲委派模型

在这个模型当中,要求除了顶层的启动类加载器之外,其余的类加载器都应该有自己的父类加载器

这里的父子关系是逻辑上的继承,如想用自定义类加载器加载一个字节码文件,首先,它不会自己去尝试加载,而是将加载任务委派给其父类加载器去完成

一直委托到最顶层,这些加载器都有其各自的加载范围,当父类加载器无法完成这个加载请求的时候,它就会一层一层的往下返回,直到返回到能完成加载

的类加载器中,完成加载请求

Java基础进阶01-类加载器,反射_第2张图片

//获取系统类加载器
classLoader systemclassLoader = classLoader.getSystemclassLoader():
//获取系统类加载器的父加载器,平台类加载器
ClassLoader classLoader1 = systemClassLoader.getParent();
//获取平台类加载器的父加载器 --- 启动类加载器
ClassLoader classLoader2 = classLoader1.getparent();
system.out.println("系统类加载器+ systemClassLoader);
system.out.printIn("平台类加载器”+ classLoader1);
System.out.printIn("系统类加载器”+ classLoader2);

5.常用方法

方法名 说明
static ClassLoader getSystemClassLoader() 获取系统类加载器
InputStream getResourceAsStream(String name) 加载某一个资源文件 参数:文件路径 返回值:字节流对象

二、反射

1.概述

Java反射机制:

  • 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法

  • 对于任意一个对象都能够调用它的任意属性和方法;

  • 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制

Java反射机制(简洁说明):

  • 无视修饰符获取类里面所有的属性和方法先获取配置文件中的信息

  • 动态获取信息并创建对象和调用方法

2.作用

普通方式创建对象

  • 无法访问私有属性和方法

用反射创建对象

  • 反射调用私有属性:能无视权限修饰符

  • 反射调用私有方法:能无视权限修饰符

总结:利用反射调用它类中的属性和方法时,能无视修饰符

举例:

如果用户有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,写好特定方法

然后写一个配置文件

配置文件:

  • 要创建对象的全类名(全限定名)

  • 要调用的方法名

在主方法中读取配置文件的信息,读到什么就创建什么对象,读到什么方法就调用什么方法

用户更改需求时,不需要更改主方法中的代码,修改配置文件即可

总结:灵活

3.反射的操作

利用class对象来创建的

(1)获取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);
​
    }
}

(2)class对象的内部结构

Java基础进阶01-类加载器,反射_第3张图片

(3)Class类中的常用方法
方法名 返回值类型 说明
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 返回单个成员方法对象

(4)获取Constructor对象

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 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]);
        }
    }
}

(5)Constructor类常用方法
方法名 返回值类型 说明
T newInstance(Object... initargs) 创建出来的对象 根据指定的构造方法创建对象

(6)利用其构造对象创建User对象
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);
    }
}

(7)Filed类中常用方法
方法名 返回值类型 说明
set(Object object,Object value) void 给指定对象的成员变量赋值
get(Object obj) Object 返回指定对象的Field的值

(8)通过反射获取成员变量

  • 获取class对象

  • 获得Field对象

  • 赋值或获取值

public class Reflection04 {
    public static void main(String[] args) throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        Class userClass = User.class;
//        method01(userClass);
//        method02(userClass);
//        method03(userClass);
//        method04(userClass);
//        method05(userClass);
        method06(userClass);
​
​
    }
​
    private static void method06(Class 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 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 userClass) throws NoSuchFieldException {
        final Field name = userClass.getDeclaredField("name");
        System.out.println(name);
    }
​
    private static void method03(Class 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);
        }
    }
}

(9)Method类的常用方法
方法名 返回值类型 说明
invoke(Object o,Object... args) 参数一:用o对象调用该方法 参数二:调用方法的传递的参数(如果没有就不用写) Object 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。 调用方法

(10)通过反射获取成员方法并运行

  • 获取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 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 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 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 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 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 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 userClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        User user = userClass.getDeclaredConstructor().newInstance();
        Method work = userClass.getMethod("work");
        work.invoke(user);
    }
​
    private static void method04(Class userClass) throws NoSuchMethodException {
        Method run = userClass.getDeclaredMethod("run", String.class, Long.class);
        System.out.println(run);
    }
​
    private static void method03(Class userClass) throws NoSuchMethodException {
        Method work = userClass.getMethod("work");
        System.out.println(work);
    }
​
    private static void method02(Class userClass) {
        Method[] declaredMethods = userClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
    }
​
    private static void method01(Class userClass) {
        Method[] methods = userClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
​
}

你可能感兴趣的:(笔记,java,笔记)