JavaSE基础知识分享(十四)

瑞星  金牌会员 | 2024-8-23 17:40:04 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 861|帖子 861|积分 2583

写在前面

今天继续讲Java中的类加载器和lambda表达式的知识!
类加载器和反射

类的加载

当步伐要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、毗连、初始化三步来实现对这个类举行初始化。

  • 加载
    将 .class 文件读入内存,并为之创建一个 Class 对象。任何类被使用时系统都会创建一个 Class 对象。
  • 毗连

    • 验证:检查类的内部结构是否正确,并与其他类和谐同等。
    • 准备:为类的静态成员分配内存,并设置默认初始化值。
    • 解析:将类的二进制数据中的符号引用替换为直接引用。

  • 初始化
    执行类的静态初始化器和静态代码块。
一个类的初始化时机


  • 创建类的实例。
  • 访问类的静态变量,或者为静态变量赋值。
  • 调用类的静态方法。
  • 使用反射方式强制创建某个类或接口对应的 java.lang.Class 对象。
  • 初始化某个类的子类。
  • 直接使用 java.exe 命令运行某个主类。
类加载器

负责将 .class 文件加载到内存中,并为之生成对应的 Class 对象。了解类加载机制可以帮助更好地理解步伐的运行。
类加载器的构成


  • Bootstrap ClassLoader(根类加载器)
    负责加载 Java 核心类,如 System、String 等。它在 JDK 的 JRE lib 目录下的 rt.jar 文件中。
  • Extension ClassLoader(扩展类加载器)
    负责加载 JRE 扩展目录中的 JAR 包。在 JDK 的 JRE lib 目录下的 ext 目录中。
  • System ClassLoader(系统类加载器)
    负责加载来自 java 命令的 .class 文件,以及 classpath 环境变量所指定的 JAR 包和类路径。
Java 反射机制

Java 反射机制允许在运行时动态获取类的信息以及调用对象的方法。
通过反射获取构造方法并使用


  • 获取构造方法

    • getConstructors()
    • getDeclaredConstructors()

  • 创建对象
    1. con.newInstance("zhangsan", 20);
    复制代码
通过反射获取成员变量并使用


  • 获取所有成员

    • getFields()
    • getDeclaredFields()

  • 获取单个成员

    • getField()
    • getDeclaredField()

  • 修改成员的值
    1. field.set(obj, value);
    复制代码
通过反射获取成员方法并使用


  • 获取所有方法

    • getMethods()
    • getDeclaredMethods()

  • 获取单个方法

    • getMethod()
    • getDeclaredMethod()

  • 暴力访问
    1. method.setAccessible(true);
    复制代码
Lambda 表达式

从 JDK 1.8 开始,Lambda 表达式简化了代码开发,支持函数式编程。
写 Lambda 表达式的场景


  • 必须有相应的函数接口,函数接口是指内部有且仅有一个抽象方法的接口。
  • 编译器通过类型推断机制可以推断出参数列表的类型。
Lambda 根本语法

Lambda 表达式由 -> 操作符分隔为两部门:

  • 左侧:指定 Lambda 表达式须要的所有参数(对应接口中的形参)。
  • 右侧:指定 Lambda 体,即要执行的功能(方法体)。
Lambda 表达式的分类


  • 无参数,无返回值。
  • 有一个参数,无返回值(若只有一个参数,小括号可以省略)。
  • 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句。
  • 若 Lambda 体中只有一条语句,return 和大括号都可以省略。
  • Lambda 表达式的参数列表的数据类型可以省略,JVM 编译器通过上下文推断出数据类型。
Java 内置函数式接口


  • Predicate:断言型接口
    1. @FunctionalInterface
    2. public interface Predicate<T> {
    3.     boolean test(T t);
    4. }
    复制代码
  • Function:函数型接口
    1. @FunctionalInterface
    2. public interface Function<T, R> {
    3.     R apply(T t);
    4. }
    复制代码
  • Supplier:供给型接口
    1. @FunctionalInterface
    2. public interface Supplier<T> {
    3.     T get();
    4. }
    复制代码
  • Consumer:消费型接口
    1. @FunctionalInterface
    2. public interface Consumer<T> {
    3.     void accept(T t);
    4. }
    复制代码
Lambda 用法再简洁之方法引用


  • 对象的方法引用
    1. 对象引用::方法名
    复制代码
  • 静态方法引用
    1. 类名::静态方法名
    复制代码
  • 构造方法引用
    1. 类名::new
    复制代码
  • 数组创建引用
    1. 元素类型[]::new
    复制代码
容易形成的误区

Lambda 表达式底层被封装成了主类的一个私有方法,并通过 invokedynamic 指令举行调用,简化了匿名内部类的写法。Lambda 表达式使代码更简洁,但也大概降低可读性。
优缺点


  • 优点

    • 淘汰代码誊写,淘汰匿名内部类的创建,节流内存占用。
    • 使用时无需影象接口和抽象函数。

  • 缺点

    • 易读性较差,须要熟悉 Lambda 表达式和抽象函数中参数的类型。
    • 不方便举行调试


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表