此笔记根据老师上课内容整理,并非本人100%原创
类加载
之前学的
过程
-
加载
-
通过类加载器(ClassLoader)加载class文件,加载到内存
-
在这个过程当中,会在内存中生成一个对象,这个类所对应的字节码文件对象(java.lang.Class)
-
-
链接
-
验证 : 对字节码文件正确性的校验(cafe babe 咖啡宝贝)
-
准备: 为类的静态成员分配内存, 并赋予默认初值
-
static int a = 10
-
-
解析: 把符号引用(用一组符号来描述被引用的目标)替换为直接引用(真实的内存地址)
-
-
初始化
-
执行静态代码块的内容,给静态成员赋真实的值
-
类加载器
分类
- Bootstrap ClassLoader 根类加载器 负责Java运行时核心类的加载,JDK中JRE的lib目录下rt.jar
- Extension ClassLoader 扩展类加载器 负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录
- Sysetm(App) ClassLoader 系统类加载器/应用加载器 负责加载自己定义的Java类
package _23reflect.com.cskaoyan._01introduction;
/**
* @description:
* @author: 景天
* @date: 2022/7/1 14:45
**/
public class Demo {
public static void main(String[] args) {
// 获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// 获取扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
// 获取根类加载器 为什么是null? 根类加载器不是java写的
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
// 查看系统类加载器的加载路径
System.out.println(System.getProperty("java.class.path").
replace(";", System.lineSeparator()));
// 查看扩展类加载器的加载路径
System.out.println("--------------");
System.out.println(System.getProperty("java.ext.dirs").
replace(";", System.lineSeparator()));
}
}
双亲委派模型
类加载的6大时机
-
创建类的实例(首次创建该类对象)
-
访问类的静态变量(首次)
-
调用类的静态方法(首次)
-
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
-
加载某个类的子类,会先触发父类的加载
-
直接使用java.exe命令来运行某个主类,也就是执行了某个类的main()方法
java代码的3个阶段
反射
什么是反射
获取运行时类信息的一种手段
反射技术的起点就是获取字节码文件对象
获取字节码文件对象的几种方式
-
对象.getClass()
-
类/接口名.class
-
Class.forName(String className) 全限定名
-
ClassLoader.loadClass(String name)
package _23reflect.com.cskaoyan._02cls;
/**
* @description: 获取字节码文件对象
* @author: 景天
* @date: 2022/7/1 15:54
**/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
// - 对象.getClass()
Stu stu = new Stu();
Class<? extends Stu> c1 = stu.getClass();
//- 类名.class
Class<Stu> c2 = Stu.class;
System.out.println(c1 == c2);
//- Class.forName(String className) 全限定名
Class<?> c3 = Class.forName("_23reflect.com.cskaoyan._02cls.Stu");
System.out.println(c1 == c3);
//- ClassLoader.loadClass(String name)
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class<?> c4 = systemClassLoader.loadClass("_23reflect.com.cskaoyan._02cls.Stu");
System.out.println(c1 == c4);
}
}
class Stu{}
注意:
-
无论是哪种方式获取的字节码文件对象,都是同一个
package _23reflect.com.cskaoyan._02cls;
/**
* @description:
* @author: 景天
* @date: 2022/7/1 16:00
**/
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException {
// 类名.class
//Class<A> c1 = A.class;
// Class.forName(String name)
Class<?> c2 = Class.forName("_23reflect.com.cskaoyan._02cls.A");
}
}
class A{
static {
System.out.println("static");
}
}
关于Class
Class
类的实例表示正在运行的 Java 应用程序中的类和接口
Class
没有公共构造方法。Class
对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass
方法自动构造的
配置文件(.properties)
.properties .yml .xml 配置文件
一般放的都是配置信息 数据库配置信息 第三方服务的信息
开发环境 测试环境 线上环境
Properties
Properties
类表示了一个持久的属性集。Properties
可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
构造方法
Properties() 创建一个无默认值的空属性列表。
成员方法
void | load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。 |
---|---|
void | load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 |
String | getProperty(String key) 用指定的键在此属性列表中搜索属性。 |
---|---|