Java基础 Day27

一、日志

1、简介

程序中的日志,用来记录应用程序的运行信息、状态信息、错误信息等

便于数据追踪、性能优化、问题排查、系统监控

2、日志框架

JUL:这是JavaSE平台提供的官方日志框架,也被称为JUL;配置相对简单,但不够灵活,性能较差

Log4j:一个流行的日志框架,提供了灵活的配置选项,支持多种输出目标

Logback(常用):基于Log4j升级而来,提供了更多的功能和配置选项,性能优于Log4j

Slf4j(Simple Logging Facade for Java):简单日志门面,提供了一套日志操作的标准接口及抽象类,允许应用程序使用不同的底层日志框架

3、配置文件

Logback 配置文件 logback.xml

该配置文件是对Logback日志框架输出的日志进行控制的,可以来配置输出的格式、位置及日志开关等。

常用的两种输出日志的位置:控制台、系统文件

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--
        CONSOLE :表示当前的日志信息是可以输出到控制台的。
    -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--输出流对象 默认 System.out 改为 System.err-->
        <target>System.out</target>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
                %msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level]  %c [%thread] : %msg%n</pattern>
        </encoder>
    </appender>

    <!-- File是输出的方向通向文件的 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!--日志输出路径-->
        <file>C:/code/itheima-data.log</file>
        <!--指定日志文件拆分和压缩规则-->
        <rollingPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--通过指定压缩文件名称,来确定分割文件方式-->
            <fileNamePattern>C:/code/itheima-data2-%d{yyyy-MMdd}.log%i.gz</fileNamePattern>
            <!--文件拆分大小-->
            <maxFileSize>1MB</maxFileSize>
        </rollingPolicy>
    </appender>

    <!--

    level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
,默认debug
    <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制
    -->
    <root level="ALL">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE" />
    </root>
</configuration>

4、日志级别

日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级由低到高)

|-------|---------------------------------|------------------|
| trace | 追踪,记录程序运行轨迹(不常用) | log.trace("...") |
| debug | 调试,记录程序调试过程中的信息,实际应用中一般将其视为最低级别 | log.debug("...") |
| info | 记录程序运行的重要信息,如:数据库连接、网络连接、io操作 | log.info("...") |
| warn | 警告信息,可能会发生问题 | log.warn("...") |
| error | 错误信息 | log.error("...") |

可以在配置文件中,灵活控制输出哪些类型的日志,大于等于指定日志级别的才会输出

二、枚举

1、简介

枚举是 Java 中的一种特殊类型,一般用来做信息的标志和分类

相比于直接使用常量,枚举代码可读性更高,入参约束严谨,代码优雅

2、格式

修饰符 enum 枚举类名 {

枚举项1, 枚举项2, 枚举项3... ;

}

3、特点

每一个枚举项其实就是该枚举的一个对象

通过枚举类名去访问指定的枚举项

所有枚举类都是 Enum 的子类

枚举也是类, 可以定义成员变量(不常用)

枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的

但是如果枚举类有其他的东西,这个分号就不能省略(建议不要省略)

枚举类可以有构造器,但必须是 private 的,它默认也是 private(不常用)

枚举类也可以有抽象方法,但是枚举项必须重写该方法(不常用)

三、类加载器

1、简介

类加载器负责将类的字节码文件加载到内存的方法区

加载的时机:用到就加载

例如创建类的对象,调用类的静态成员,初始化继承体系等

2、加载过程

(1)加载

通过全类名(包名 + 类名)获取这个类,准备用流进行传输

将类加载到内存中

加载完毕创建一个 class 对象

(2)链接

验证:验证类是否符合 JVM 虚拟机规范,安全性检查

准备:为静态变量分配空间,设置默认值

解析:将常量池中的符号引用解析为直接引用

(3)初始化

根据程序员编码指定的主观计划去初始化类变量和其他资源

3、类加载器的分类

系统类加载器的上级是平台类加载器,平台类加载器的上级是启动类加载器

(1)Bootstrap classLLoade(启动类加载器)r:虚拟机的内置类加载器,通常表示为null

C++ 实现, 获取到的只能是 null

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

负责加载 lib\modules 内部的类

JDK9 之前是(Extension Class Loader) 扩展类加载器

负责加载 jre\lib\ext 目录下的类

(3)Application classLoader(系统类加载器):负责加载自己写的类

(4)自定义类加载器:上级为 Application,目前不做了解

4、常用方法

public ClassLoader getClassLoader() 获取该类的类加载器对象

5、双亲委派模式

如果一个类加载器收到了类加载请求,它并不会自己先去加载

先判断是否已经加载过,如果没有,就委托给父类

如果父类加载器还存在其父类加载器,则判断后进一步向上委托,依次递归

请求最终将到达顶层的启动类加载器

如果父类加载器可以完成类加载任务,就成功返回

倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式

双亲委派模式可以避免类的重复加载

6、ClassLoader 的成员方法

|----------------------------------------------------------|-----------|
| public static ClassLoader getSystemClassLoader () | 获取系统类加载器 |
| public InputStream getResourceAsStream (String name) | 加载某一个资源文件 |

对于 src 下的文件,name 可以直接传入文件名而不用写路径

四、反射

1、简介

框架技术的灵魂

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

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

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

2、获取类的字节码对象

java 复制代码
// 法一:使用Class的静态方法forName
Class<?> class1 = Class.forName("com.example.Student");
// 法二:类名.class
Class<Student> class2 = Student.class;
// 法三:Object类中的getClass方法
Class<? extends Student> class3 = new Student().getClass();

注意:类的字节码对象只有一份

3、反射某个类的构造方法

Java 将构造方法封装成了一个类 Constructor<T>

|----------------------------------------------------------------------------|-----------------|
| Constructor<?>[] getConstructors () | 返回所有公共构造方法对象的数组 |
| Constructor<?>[] getDeclaredConstructors () | 返回所有构造方法对象的数组 |
| Constructor<T> getConstructor (Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
| Constructor<T> getDeclaredConstructor (Class<?>... parameterTypes) | 返回单个构造方法对象 |

Constructor类用于创建对象的方法:

|---------------------------------------|------------------|
| T newInstance (Object...initargs) | 根据指定的构造方法创建对象 |
| setAccessible (boolean flag) | 设置为true,表示取消访问检查 |

java 复制代码
Constructor<?> myConstructor = class1.getDeclaredConstructor(String.class, int.class);
System.out.println(myConstructor);
myConstructor.setAccessible(true);
Student stu1 = (Student) myConstructor.newInstance("aaa", 21);
System.out.println(stu1);

输出:
public com.example.Student(java.lang.String,int)
Student{name = aaa, age = 21}

4、反射某个类的成员变量

Java 将成员变量封装成了一个类 Field

|------------------------------------------|-----------------|
| Field[] getFields () | 返回所有公共成员变量对象的数组 |
| Field[] getDeclaredFields () | 返回所有成员变量对象的数组 |
| Field getField (String name) | 返回单个公共成员变量对象 |
| Field getDeclaredField (String name) | 返回单个成员变量对象 |

name 传入成员变量名

Tips:shift + F6 可以同时修改各处的同一变量的名称

Field类的设置和获取方法:

|-----------------------------------------|-----|
| void set (Object obj, Object value) | 赋值 |
| Object get (Object obj) | 获取值 |

java 复制代码
Field nameField = class1.getDeclaredField("name");
nameField.setAccessible(true);
Field ageField = class1.getDeclaredField("age");
ageField.setAccessible(true);
nameField.set(stu1, "ccc");
ageField.set(stu1, 23);
System.out.println(nameField.get(stu1));
System.out.println(ageField.get(stu1));

输出:
ccc
23

5、反射某个类的成员方法

Java 将成员方法封装成了一个类 Method

|--------------------------------------------------------------------------|-----------------------|
| Method[] getMethods () | 返回所有公共成员方法对象的数组,包括继承的 |
| Method[] getDeclaredMethods () | 返回所有成员方法对象的数组,不包括继承的 |
| Method getMethod (String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
| Method getDeclaredMethod (String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |

Method 类用于执行方法的方法

|------------------------------------------------|------|
| Object invoke (Object obj, Object... args) | 运行方法 |

Tips:Java 中的泛型是伪泛型,只在编译的时候有效,字节码文件中没有泛型

相关推荐
Bruk.Liu11 分钟前
《IDEA 高效开发:自定义类/方法注释模板详解》
java·ide·intellij-idea·注释
叶 落15 分钟前
[Java 基础]选英雄(配置 IDEA)
java·ide·intellij-idea
陈丹阳(滁州学院)16 分钟前
解决idea编译运行项目时间长的问题
java·intellij-idea·idea
小伍_Five1 小时前
Spark实战能力测评模拟题精析【模拟考】
java·大数据·spark·scala·intellij-idea
阿蒙Amon1 小时前
C#获取磁盘容量:代码实现与应用场景解析
开发语言·c#
橘子青衫1 小时前
Java多线程编程:深入探索线程同步与互斥的实战策略
java·后端·性能优化
界面开发小八哥1 小时前
VS代码生成工具ReSharper v2025.1——支持.NET 10和C# 14预览功能
开发语言·ide·c#·.net·visual studio·resharper
胡西风_foxww2 小时前
Python 入门到进阶全指南:从语言特性到实战项目
开发语言·python·快速入门
bubiyoushang8882 小时前
matlab实现高斯烟羽模型算法
开发语言·算法·matlab
CN.LG2 小时前
C# 从 ConcurrentDictionary 中取出并移除第一个元素
java·开发语言·c#