1.类加载器
1.1 类加载器
作用:负责将.class文件(存储的物理文件)加载在到内存中。
1.2类加载的过程
- 类加载时机
创建类的实例(对象)
调用类的类方法
访问类或者接口的类变量,或者为该类变量赋值
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
类加载过程
-
加载
通过包名 + 类名,获取这个类,准备用流进行传输
在这个类加载到内存中
加载完毕创建一个class对象
-
链接
- 验证
确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全(文件中的信息是否符合虚拟机规范有没有安全隐患)
- 准备
负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值(初始化静态变量)
- 解析
将类的二进制数据流中的符号引用替换为直接引用(本类中如果用到了其他类,此时就需要找到对应的类)
- 初始化
根据程序员通过程序制定的主观计划去初始化类变量和其他资源
(静态变量赋值以及初始化其他资源)
小结
- 当一个类被使用的时候,才会加载到内存
- 类加载的过程: 加载、验证、准备、解析、初始化
1.3 类加载的分类
- 分类
Bootstrap class loader:虚拟机的内置类加载器,通常表示为null ,并且没有父null
Platform class loader:平台类加载器,负责加载JDK中一些特殊的模块
System class loader:系统类加载器,负责加载用户类路径上所指定的类库 - 类加载器的继承关系
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);
}
}
1.4双亲委派模型
介绍
如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
1.5 ClassLoader 中的两个方法
方法介绍
方法名 | 说明 |
---|---|
public static ClassLoader getSystemClassLoader() | 获取系统类加载器 |
public InputStream getResourceAsStream(String name) | 加载某一个资源文件 |
public class ClassLoaderDemo2 {
public static void main(String[] args) throws IOException {
//static ClassLoader getSystemClassLoader() 获取系统类加载器
//InputStream getResourceAsStream(String name) 加载某一个资源文件
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader()
//利用加载器去加载一个指定的文件
//参数:文件的路径(放在src的根目录下,默认去那里加载)
//返回值:字节流。
InputStream is = systemClassLoader.getResourceAsStream("prop.properties");
Properties prop = new Properties();
prop.load(is);
System.out.println(prop);
is.close();
}
}
2.反射
2.1 反射的概述
- 反射机制
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意属性和方法; 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
2.2获取Class类对象的三种方式
三种方式分类
- 类名.class属性
- 对象名.getClass()方法
- Class.forName(全类名)方法
2.3 反射获取构造方法并使用
2.3.1 Class类获取构造方法对象的方法
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor getConstructor(Class<?>… parameterTypes) | 返回单个公共构造方法对象 |
Constructor getDeclaredConstructor(Class<?> …parameterTypes) | 返回单个构造方法对象 |
2.3.2 Constructor类用于创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object…initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
2.3.3小结
- 获取class对象
三种方式: Class.forName(“全类名”), 类名.class, 对象名.getClass() - 获取里面的构造方法对象
getConstructor (Class<?>... parameterTypes) getDeclaredConstructor (Class<?>… parameterTypes) - 如果是public的,直接创建对象
newInstance(Object… initargs) - 如果是非public的,需要临时取消检查,然后再创建对象
setAccessible(boolean) 暴力反射
2.4 反射获取成员变量并使用
2.4.1 Class类获取成员变量对象的方法
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
2.4.2 Field类用于给成员变量赋值的方法
方法名 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
2.5反射获取成员方法并使用
2.5.1 Class类获取成员方法对象的方法
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>…parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>…parameterTypes) | 返回单个成员方法对象 |
2.5.2Method类用于执行方法的方法
方法名 | 说明 |
---|---|
Object invoke(Object obj, Object… args) | 运行方法 |
参数一: 用obj对象调用该方法
参数二: 调用方法的传递的参数(如果没有就不写)
返回值: 方法的返回值(如果没有就不写)
3.http服务器改写
3.1 静态资源和动态资源
静态资源
在服务器提前准备好的文件。(图片,文本)
动态资源
当用户点击了浏览器上的按钮。 本质上访问的就是服务端的某一个类中的某一个方法。 在方法中,可以写一些判断代码和逻辑代码,让响应的内容,有可能不一样了。 那么,服务端所对应的这个类我们常常将其称之为“动态资源”
3.2多个动态资源
-
多个动态资源
针对每一个业务操作,我们都会去定义一个对应的Servlet来完成。 就会在服务端产生很多个Servlet
-
实现步骤
定义一个接口HttpServlet,接口中定义service方法。
针对于每一种业务,都定义一个servlet类与之对应,该类实现HttpServlet接口
获取请求的uri,进行判断,调用不同的servlet类中的service方法
4.xml
4.1 概述
- 万维网联盟(W3C)
万维网联盟(W3C)创建于1994年,又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。 建立者: Tim Berners-Lee (蒂姆·伯纳斯·李)。 是Web技术领域最具权威和影响力的国际中立性技术标准机构。到目前为止,W3C已发布了200多项影响深远的Web技术标准及实施指南, -
- 如广为业界采用的超文本标记语言HTML(标准通用标记语言下的一个应用)、
-
- 可扩展标记语言XML(标准通用标记语言下的一个子集)
-
- 以及帮助残障人士有效获得Web信息的无障碍指南(WCAG)等
- xml概述
XML的全称为(EXtensible Markup Language),是一种可扩展的标记语言 标记语言: 通过标签来描述数据的一门语言(标签有时我们也将其称之为元素) 可扩展:标签的名字是可以自定义的,XML文件是由很多标签组成的,而标签名是可以自定义的 - 作用
用于进行存储数据和传输数据
作为软件的配置文件 - 作为配置文件的优势
可读性好
可维护性高
4.2 语法规则
语法规则
- XML文件的后缀名为:xml
- 文档声明必须是第一行第一列
encoding:该属性不是必须的
打开当前xml文件的时候应该是使用什么字符编码表(一般取值都是UTF-8)
standalone: 该属性不是必须的,描述XML文件是否依赖其他的xml文件,取值为yes/no
- 必须存在一个根标签,有且只能有一个
- XML文件中可以定义注释信息
- XML文件中可以存在以下特殊字符
- XML文件中可以存在CDATA区 <![CDATA[ …内容… ]]>
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 引号
4.3 xml解析
-
概述
xml解析就是从xml中获取到数据 -
常见的解析思想
DOM(Document Object Model)文档对象模型:就是把文档的各个组成部分看做成对应的对象。 会把xml文件全部加载到内存,在内存中形成一个树形结构,再获取对应的值
-
常见的解析工具
JAXP: SUN公司提供的一套XML的解析的API
JDOM: 开源组织提供了一套XML的解析的API-jdom
DOM4J: 开源组织提供了一套XML的解析的API-dom4j,全称:Dom For Java
pull: 主要应用在Android手机端解析XML -
解析的准备工作
- 我们可以通过网站:https://dom4j.github.io/ 去下载dom4j
今天的资料中已经提供,我们不用再单独下载了,直接使用即可 - 将提供好的dom4j-1.6.1.zip解压,找到里面的dom4j-1.6.1.jar
- 在idea中当前模块下新建一个libs文件夹,将jar包复制到文件夹中
- 选中jar包 -> 右键 -> 选择add as library即可
- 需求
解析提供好的xml文件
将解析到的数据封装到学生对象中
并将学生对象存储到ArrayList集合中
遍历集合
4.4 DTD约束
- 什么是约束
用来限定xml文件中可使用的标签以及属性 - 约束的分类
DTD
schema - 编写DTD约束
步骤- 创建一个文件,这个文件的后缀名为.dtd
- 看xml文件中使用了哪些元素<!ELEMENT> 可以定义元素
- 判断元素是简单元素还是复杂元素
简单元素:没有子元素。 复杂元素:有子元素的元素;
引入DTD约束
引入DTD约束的三种方法
- 引入本地dtd
<!DOCTYPE 根元素名称 SYSTEM ‘DTD文件的路径'>
- 在xml文件内部引入
<!DOCTYPE 根元素名称 [ dtd文件内容 ]>
- 引入网络dtd
<!DOCTYPE 根元素的名称 PUBLIC "DTD文件名称" "DTD文档的URL">
DTD语法
-
定义元素
定义一个元素的格式为:<!ELEMENT 元素名 元素类型> 简单元素:
EMPTY: 表示标签体为空
ANY: 表示标签体可以为空也可以不为空
PCDATA: 表示该元素的内容部分为字符串
复杂元素: 直接写子元素名称. 多个子元素可以使用",“或者”|"隔开; ","表示定义子元素的顺序 ; “|”: 表示子元素只能出现任意一个 "?"零次或一次, "+"一次或多次, "*"零次或多次;如果不写则表示出现一次。
-
定义属性
格式
定义一个属性的格式为:<!ATTLIST 元素名称 属性名称 属性的类型 属性的约束> 属性的类型: CDATA类型:普通的字符串
属性的约束:
// #REQUIRED: 必须的 // #IMPLIED: 属性不是必需的 // #FIXED value:属性值是固定的
4.5 schema约束
schema和dtd的区别
- schema约束文件也是一个xml文件,符合xml的语法,这个文件的后缀名.xsd
- 一个xml中可以引用多个schema约束文件,多个schema使用名称空间区分(名称空间类似于java包名)
- dtd里面元素类型的取值比较单一常见的是PCDATA类型,但是在schema里面可以支持很多个数据类型
- schema 语法更加的复杂
编写schema约束
步骤
1,创建一个文件,这个文件的后缀名为.xsd。 2,定义文档声明 3,schema文件的根标签为: 4,在中定义属性: xmlns=http://www.w3.org/2001/XMLSchema 5,在中定义属性 : targetNamespace =唯一的url地址,指定当前这个schema文件的名称空间。 6,在中定义属性 :elementFormDefault="qualified“,表示当前schema文件是一个质量良好的文件。 7,通过element定义元素 8,判断当前元素是简单元素还是复杂元素
5.枚举
5.1概述
为了间接的表示一些固定的值,Java就给我们提供了枚举 是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内
5.2定义格式
格式
public enum s {
枚举项1,枚举项2,枚举项3;
}
注意: 定义枚举类要用关键字enum
5.3枚举的特点
特点
- 所有枚举类都是Enum的子类
- 我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
- 每一个枚举项其实就是该枚举的一个对象
- 枚举也是一个类,也可以去定义成员变量
- 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
- 枚举类可以有构造器,但必须是private的,它默认的也是private的。
- 枚举项的用法比较特殊:枚举("");
- 枚举类也可以有抽象方法,但是枚举项必须重写该方法
5.4枚举的方法
方法名 | 说明 |
---|---|
String name() | 获取枚举项的名称 |
int ordinal() | 返回枚举项在枚举类中的索引值 |
int compareTo(E o) | 比较两个枚举项,返回的是索引值的差值 |
String toString() | 返回枚举常量的名称 |
static T valueOf(Class type,String name) | 获取指定枚举类中的指定名称的枚举值 |
values() | 获得所有的枚举项 |
6.注解
6.1概述
- 概述
对我们的程序进行标注和解释 - 注解和注释的区别
注释: 给程序员看的
注解: 给编译器看的 - 使用注解进行配置配置的优势
代码更加简洁,方便
6.2自定义注解
-
格式
public @interface 注解名称 {
public 属性类型 属性名() default 默认值 ;
} -
属性类型
基本数据类型
String
Class
注解
枚举
以上类型的一维数组 -
注意
如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
6.3元注解
- 概述
元注解就是描述注解的注解
元注解介绍
元注解名 | 说明 |
---|---|
@Target | 指定了注解能在哪里使用 |
@Retention | 可以理解为保留时间(生命周期) |
@Inherited | 表示修饰的自定义注解可以被子类继承 |
@Documented | 表示该自定义注解,会出现在API文档里面。 |
7.单元测试
7.1概述
JUnit是一个 Java 编程语言的单元测试工具。JUnit 是一个非常重要的测试工具
7.2特点
JUnit是一个开放源代码的测试工具。
提供注解来识别测试方法。
JUnit测试可以让你编写代码更快,并能提高质量。
JUnit优雅简洁。没那么复杂,花费时间较少。
JUnit在一个条中显示进度。如果运行良好则是绿色;如果运行失败,则变成红色。
7.3使用步骤
使用步骤
- 将junit的jar包导入到工程中 junit-4.9.jar
- 编写测试方法该测试方法必须是公共的无参数无返回值的非静态方法
- 在测试方法上使用@Test注解标注该方法是一个测试方法
- 选中测试方法右键通过junit运行该方法
public class JunitDemo1 {
@Test
public void add() {
System.out.println(2 / 0);
int a = 10;
int b = 20;
int sum = a + b;
System.out.println(sum);
}
}
7.4相关注解
注解 | 含义 |
---|---|
@Test | 表示测试该方法 |
@Before | 在测试的方法前运行 |
@After | 在测试的方法后运行 |
8.日志
8.1概述
- 概述
程序中的日志可以用来记录程序在运行的时候点点滴滴。并可以进行永久存储。 - 日志与输出语句的区别
输出语句 | 日志技术 | |
---|---|---|
取消日志 | 需要修改代码,灵活性比较差 | 不需要修改代码,灵活性比较好 |
输出位置 | 只能是控制台 | 可以将日志信息写入到文件或者数据库中 |
多线程 | 和业务代码处于一个线程中 | 多线程方式记录日志,不影响业务代码的性能 |
8.2日志体系结构和Log4J
-
体系结构
-
Log4J
Log4j是Apache的一个开源项目。
通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件等位置。
我们也可以控制每一条日志的输出格式。
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 -
Apache基金会
Apache软件基金会(也就是Apache Software Foundation,简称为ASF),为支持开源软件项目而办的一个非盈利性组织。