1 日志
1.1 概述
- 程序中的日志就好比日记。可以记录你生活的点点滴滴。
- 生活中的日志可以用来记录程序在运行的时候点点滴滴。并可以进行永久存储。
- 日志与输出语句的区别
| 输出语句 | 日志技术 |
---|
取消日志 | 需要修改代码,灵活性比较差 | 不需要修改代码,灵活性比较好 |
输出位置 | 只能是控制台 | 可以将日志信息写入到文件或者数据库中 |
多线程 | 和业务代码处于一个线程中 | 多线程方式记录日志,不影响业务代码的性能 |
- 日志技术的特点
- 通过使用logback,我们可以控制日志信息输送的目的地是控制台、文件等位置。
- 我们也可以控制每一条日志的输出格式*。
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
- 最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
1.2 日志体系结构和logback
- 体系结构
- logback
- logback是基于slf4j的日志规范实现的框架,性能比之前使用的log4j要好
- 官方网站:https://logback.qos.ch/index.html
- logback主要分为三个技术模块
- logback-core:该模块为其他两个模块提供基础代码,必须有
- logback-clasic:完整实现了slf4j API的模块
- logback-access:模块与Tomcat和Jeffy等Servlet容器集成,以提供HTTP访问日志功能
1.3 入门案例
- 使用步骤
- 导入logback的相关jar包
- 编写logback配置文件
- 在代码中获取日志的对象
- 按照级别设置记录日志信息
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern>
</encoder>
</appender>
<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>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE" />
</root>
</configuration>
public class Test01 {
private static final Logger LOGGER = LoggerFactory.getLogger(Test01.class);
public static void main(String[] args) {
LOGGER.debug("debug级别的日志");
LOGGER.info("info级别的日志");
LOGGER.warn("warn级别的日志");
LOGGER.error("error级别的日志");
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;
public class LogDemo {
private static final Logger LOGGER = LoggerFactory.getLogger(LogDemo.class);
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入您的姓名");
LOGGER.debug("用户开始输入信息了");
String name = sc.nextLine();
LOGGER.info("用户输出录入姓名为:" + name);
System.out.println("请输入您的年龄");
String age = sc.nextLine();
try {
int ageInt = Integer.parseInt(age);
LOGGER.info("用户输入的年龄格式正确" + age);
} catch (NumberFormatException e) {
LOGGER.info("用户输入的年龄格式错误" + age);
}
}
}
1.4 日志的六种级别
- 级别程度依次为:
- TRACE<DEBUG<INFO<WARN<ERROR<FATAL
- 默认级别
- 默认级别是DEBUG(忽略大小写)
- LOGGER.error("error级别的日志’);
- 作用
- 将开发中不同的日志信息进行分类,只输出大于等于该级别的日志信息
- 如我现在设置的等级为INFO
- INFO、WARN、ERROR、FATAL该四个等级会输出
- TRACE、DEBUG这两个等级不会输出
- ALL和OFF分别是打开全部日志信息,及关闭全部日志信息
1.5 logback配置文件详解
- 总体上可以分为三个部分:
- < appender >
- 针对控制台的设置
- < target >:控制台以输出语句形式来打印
- < pattern >:在控制台打印的格式
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern>
</encoder>
</appender>
- < appender >
- 针对File文件的设置
- < pattern >:在文件中打印的格式
- < charset >:编码表
- < 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>
- < root >
- 表示的是日志的开关
- level:表示日志级别
- CONSOLE:可以打印在控制台
- FILE:可以保存在文件中
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE" />
</root>
2 枚举
2.1概述
- 为了间接的表示一些固定的值,Java就给我们提供了枚举
- 是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内
2.2 定义格式
public enum s {
枚举项1,枚举项2,枚举项3;
}
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}
2.3 枚举的特点
- 特点
- 所有枚举类都是Enum的子类
- 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
- 每一个枚举项其实就是该枚举的一个对象
- 枚举也是一个类,也可以去定义成员变量
- 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
- 枚举类可以有构造器,但必须是private的,它默认的也是private的。
枚举项的用法比较特殊:枚举(“”); - 枚举类也可以有抽象方法,但是枚举项必须重写该方法
public enum Season {
SPRING("春") {
@Override
public void show() {
System.out.println(this.name);
}
},
SUMMER("夏") {
@Override
public void show() {
System.out.println(this.name);
}
},
AUTUMN("秋") {
@Override
public void show() {
System.out.println(this.name);
}
},
WINTER("冬") {
@Override
public void show() {
System.out.println(this.name);
}
};
public String name;
private Season(String name) {
this.name = name;
}
public abstract void show();
}
public class EnumDemo {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SUMMER);
System.out.println(Season.AUTUMN);
System.out.println(Season.WINTER);
Season spring = Season.SPRING;
}
}
2.4 枚举的方法
-
方法介绍
方法名 | 说明 |
---|
String name() | 获取枚举项的名称 |
int ordinal() | 返回枚举项在枚举类中的索引值 |
int compareTo(E o) | 比较两个枚举项,返回的是索引值的差值 |
String toString() | 返回枚举常量的名称 |
static < T > T valueOf(Class< T > type,String name) | 获取指定枚举类中的指定名称的枚举值 |
values() | 获得所有的枚举项 |
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
public class EnumDemo {
public static void main(String[] args) {
String name = Season.SPRING.name();
System.out.println(name);
System.out.println("-----------------------------");
int index1 = Season.SPRING.ordinal();
int index2 = Season.SUMMER.ordinal();
int index3 = Season.AUTUMN.ordinal();
int index4 = Season.WINTER.ordinal();
System.out.println(index1);
System.out.println(index2);
System.out.println(index3);
System.out.println(index4);
System.out.println("-----------------------------");
int result = Season.SPRING.compareTo(Season.WINTER);
System.out.println(result);
System.out.println("-----------------------------");
String s = Season.SPRING.toString();
System.out.println(s);
System.out.println("-----------------------------");
Season spring = Enum.valueOf(Season.class, "SPRING");
System.out.println(spring);
System.out.println(Season.SPRING == spring);
System.out.println("-----------------------------");
Season[] values = Season.values();
for (Season value : values) {
System.out.println(value);
}
}
}
3 类加载器
3.1 类加载器
- 负责将.class文件(存储的物理文件)加载在到内存中
3.2 类加载的过程
- 类加载时机
- 创建类的实例(对象)
- 调用类的类方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
- 用到了就加载,不用不加载
- 类加载过程
- 加载
- 通过包名 + 类名,获取这个类,准备用流进行传输
- 在这个类加载到内存中
- 加载完毕创建一个class对象
-
链接
- 验证
- 确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全
(文件中的信息是否符合虚拟机规范有没有安全隐患)
- 准备
- 负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值
(初始化静态变量)
- 解析
- 将类的二进制数据流中的符号引用替换为直接引用
(本类中如果用到了其他类,此时就需要找到对应的类)
-
初始化
- 根据程序员通过程序制定的主观计划去初始化类变量和其他资源
(静态变量赋值以及初始化其他资源)
-
小结
- 当一个类被使用的时候,才会加载到内存
- 类加载的过程: 加载、验证、准备、解析、初始化
3.3 类加载的分类
- 分类
- 启动类加载器:
- Bootstrap classloader:虚拟机的内置类加载器,通常表示为null ,并且没有父null
- 平台类加载器
- Platform classloader:负责加载JDK中一些特殊的模块
- 系统类加载器
- System classloader:负责加载用户类路径上所指定的类库
- 类加载器的继承关系
- System的父加载器为Platform
- Platform的父加载器为Bootstrap
public class ClassLoaderDemo1 {
public static void main(String[] args) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
ClassLoader classLoader1 = systemClassLoader.getParent();
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println("系统类加载器" + systemClassLoader);
System.out.println("平台类加载器" + classLoader1);
System.out.println("启动类加载器" + classLoader2);
}
}
3.4 双亲委派模型
- 介绍
- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式
3.5 ClassLoader 中的两个方法
方法名 | 说明 |
---|
public static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
public InputStream getResourceAsStream(String name) | 加载某一个资源文件 |
public class ClassLoaderDemo2 {
public static void main(String[] args) throws IOException {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties prop = new Properties();
prop.load(is);
System.out.println(prop);
is.close();
}
}
4 反射
4.1 反射的概述
- 反射机制
- 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意属性和方法;
- 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void study() {
System.out.println("学生在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Teacher {
private String name;
private int age;
public Teacher() {
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void teach() {
System.out.println("老师在上课");
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Worker {
private String name;
private int age;
public Worker() {
}
public Worker(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void work() {
System.out.println("工人在工作");
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
prop.properties文件
className=com.itheima.myreflect1.Worker
methodName=work
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectDemo1 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("prop.properties");
Properties prop = new Properties();
prop.load(is);
is.close();
Class clazz = Class.forName(prop.getProperty("className"));
Constructor constructor = clazz.getConstructor();
Object o = constructor.newInstance();
Method method = clazz.getMethod(prop.getProperty("methodName"));
method.invoke(o);
}
}
- 反射机制小总结:
- 利用反射可以无视修饰符获取类里面所有的属性和方法
- 先获取配置文件中的信息,动态获取信息并创建对象和调用方法
4.2 获取Class类对象的三种方式
- 三种方式分类
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void study() {
System.out.println("学生在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect2.Student");
System.out.println(clazz);
Class clazz2 = Student.class;
System.out.println(clazz2);
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
System.out.println(clazz == clazz2);
System.out.println(clazz2 == clazz3);
}
}
4.3 反射获取构造方法并使用
4.3.1 Class类获取构造方法对象的方法
方法名 | 说明 |
---|
Constructor< ? >[ ] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor< ? >[ ] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor< T > getConstructor(Class<?>… parameterTypes) | 返回单个公共构造方法对象 |
Constructor< T > getDeclaredConstructor(Class<?>… parameterTypes) | 返回单个构造方法对象 |
public class Student {
private String name;
private int age;
private Student(String name) {
System.out.println("name的值为:" + name);
System.out.println("private...Student...有参构造方法");
}
public Student() {
System.out.println("public...Student...无参构造方法");
}
public Student(String name, int age) {
System.out.println("name的值为:" + name + "age的值为:" + age);
System.out.println("public...Student...有参构造方法");
}
}
import java.lang.reflect.Constructor;
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getDeclaredConstructor(String.class);
System.out.println(constructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor1 = clazz.getConstructor();
System.out.println(constructor1);
Constructor constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
Constructor constructor3 = clazz.getConstructor(int.class);
System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor[] constructors = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
private static void method1() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
4.3.2 Constructor类用于创建对象的方法
方法名 | 说明 |
---|
T newInstance(Object…initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
public class Student {
private String name;
private int age;
private Student(String name) {
System.out.println("name的值为:" + name);
System.out.println("private...Student...有参构造方法");
}
public Student() {
System.out.println("public...Student...无参构造方法");
}
public Student(String name, int age) {
System.out.println("name的值为:" + name + "age的值为:" + age);
System.out.println("public...Student...有参构造方法");
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("zhangsan");
System.out.println(student);
}
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Student student = (Student) clazz.newInstance();
System.out.println(student);
}
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getConstructor(String.class, int.class);
Student student = (Student) constructor.newInstance("zhangsan", 23);
System.out.println(student);
}
}
4.3.3 小结
- 获取class对象
- 三种方式:
- Class.forName(“全类名”)
- 类名.class,
- 对象名.getClass()
- 获取里面的构造方法对象
- getConstructor (Class<?>… parameterTypes)
- getDeclaredConstructor (Class<?>… parameterTypes)
- getConstructor(Class<?>… parameterTypes)
- getDeclaredConstructor(Class<?>… parameterTypes)
- 如果是public的,直接创建对象
- newInstance(Object… initargs)
- 如果是非public的,需要临时取消检查,然后再创建对象
- setAccessible(boolean) 暴力反射
4.4反射获取成员变量并使用
4.4.1 Class类获取成员变量对象的方法
方法名 | 说明 |
---|
Field[ ] getFields() | 返回所有公共成员变量对象的数组 |
Field[ ] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
public class Student {
public String name;
public int age;
public String gender;
private int money = 300;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", money=" + money +
'}';
}
}
import java.lang.reflect.Field;
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
}
private static void method4() throws ClassNotFoundException, NoSuchFieldException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getDeclaredField("money");
System.out.println(field);
}
private static void method3() throws ClassNotFoundException, NoSuchFieldException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getField("money");
System.out.println(field);
}
private static void method2() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
}
private static void method1() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
}
4.4.2 Field类用于给成员变量赋值的方法
方法名 | 说明 |
---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
public class Student {
public String name;
public int age;
public String gender;
private int money = 300;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", money=" + money +
'}';
}
}
import java.lang.reflect.Field;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
}
private static void method2() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getDeclaredField("money");
field.setAccessible(true);
Student student = (Student) clazz.newInstance();
Object o = field.get(student);
System.out.println(o);
}
private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getField("name");
Student student = (Student) clazz.newInstance();
field.set(student, "zhangsan");
System.out.println(student);
}
}
4.5 反射获取成员方法并使用
4.5.1 Class类获取成员方法对象的方法
方法名 | 说明 |
---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象 |
public class Student {
private void show() {
System.out.println("私有的show方法,无参无返回值");
}
public void function1() {
System.out.println("function1方法,无参无返回值");
}
public void function2(String name) {
System.out.println("function2方法,有参无返回值,参数为" + name);
}
public String function3() {
System.out.println("function3方法,无参有返回值");
return "aaa";
}
public String function4(String name) {
System.out.println("function4方法,有参有返回值,参数为" + name);
return "aaa";
}
}
import java.lang.reflect.Method;
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
}
private static void method5() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method method = clazz.getDeclaredMethod("show");
System.out.println(method);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method method = clazz.getMethod("function2", String.class);
System.out.println(method);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method method1 = clazz.getMethod("function1");
System.out.println(method1);
}
private static void method2() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
private static void method1() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
4.5.2 Method类用于执行方法的方法
方法名 | 说明 |
---|
Object invoke(Object obj, Object… args) | 运行方法 |
- 参数一: 用obj对象调用该方法
- 参数二: 调用方法的传递的参数(如果没有就不写)
- 返回值: 方法的返回值(如果没有就不写)
public class Student {
private void show() {
System.out.println("私有的show方法,无参无返回值");
}
public void function1() {
System.out.println("function1方法,无参无返回值");
}
public void function2(String name) {
System.out.println("function2方法,有参无返回值,参数为" + name);
}
public String function3() {
System.out.println("function3方法,无参有返回值");
return "aaa";
}
public String function4(String name) {
System.out.println("function4方法,有参有返回值,参数为" + name);
return "aaa";
}
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method method = clazz.getMethod("function4", String.class);
Student student = (Student) clazz.newInstance();
Object result = method.invoke(student, "zhangsan");
System.out.println(result);
}
}
5 日志扩展Log4J
- Log4J
- Log4j是Apache的一个开源项目。
- 通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件等位置。
- 我们也可以控制每一条日志的输出格式。
- 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
- 最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
5.1 入门案例
- 使用步骤
- 导入log4j的相关jar包
- 编写log4j配置文件
- 在代码中获取日志的对象
- 按照级别设置记录日志信息
log4j.rootLogger=debug,my,fileAppender
### direct log messages to my ###
log4j.appender.my=org.apache.log4j.ConsoleAppender
log4j.appender.my.ImmediateFlush = true
log4j.appender.my.Target=System.out
log4j.appender.my.layout=org.apache.log4j.PatternLayout
log4j.appender.my.layout.ConversionPattern=%d %t %5p %c{1}:%L - %m%n
# fileAppenderÑÝʾ
log4j.appender.fileAppender=org.apache.log4j.FileAppender
log4j.appender.fileAppender.ImmediateFlush = true
log4j.appender.fileAppender.Append=true
log4j.appender.fileAppender.File=D:/log4j-log.log
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=%d %5p %c{1}:%L - %m%n
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4JTest01 {
private static final Logger LOGGER = LoggerFactory.getLogger(Log4JTest01.class);
public static void main(String[] args) {
LOGGER.debug("debug级别的日志");
LOGGER.info("info级别的日志");
LOGGER.warn("warn级别的日志");
LOGGER.error("error级别的日志");
}
}
5.2 配置文件详解
- 三个核心
- Loggers(记录器) 日志的级别
- Loggers组件在此系统中常见的五个级别:DEBUG、INFO、WARN、ERROR 和 FATAL。
- DEBUG < INFO < WARN < ERROR < FATAL。
- Log4j有一个规则:只输出级别不低于设定级别的日志信息。
- Appenders(输出源) 日志要输出的地方
- 把日志输出到不同的地方,如控制台(Console)、文件(Files)等。
- org.apache.log4j.ConsoleAppender(控制台)
- org.apache.log4j.FileAppender(文件)
- Layouts(布局) 日志输出的格式
- 可以根据自己的喜好规定日志输出的格式
- 常用的布局管理器:
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
- 配置根Logger
- 格式
- log4j.rootLogger=日志级别,appenderName1,appenderName2,…
- 日志级别
- OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。
- appenderName1
- 就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。
- 例如:log4j.rootLogger=INFO,ca,fa
- ConsoleAppender常用的选项
- ImmediateFlush=true
- 表示所有消息都会被立即输出,设为false则不输出,默认值是true。
- Target=System.err
- FileAppender常用的选项
- ImmediateFlush=true
- 表示所有消息都会被立即输出。设为false则不输出,默认值是true
- Append=false
- true表示将消息添加到指定文件中,原来的消息不覆盖。
- false则将消息覆盖指定的文件内容,默认值是true。
- File=D:/logs/logging.log4j
- PatternLayout常用的选项