JavaSE(B站黑马)学习笔记
01Java入门
02数组、方法
03面向对象&Java语法
04-1Java高级(Stream流、异常处理、日志技术)
04-2Java高级(文件处理-IO流)
04-3Java高级(多线程、网络编程)
04-4Java高级(单元测试、反射、注解、动态代理、XML)
05-1常用API
05-2常用API(集合)
前言
JavaSE(B站黑马)学习笔记 04-4Java高级(单元测试、反射、注解、动态代理、XML)
04-4Java高级(单元测试、反射、注解、动态代理、XML)
需要学会什么(这些技术都是后面学习框架的底层原理技术,现在学的可能很抽象还不好理解,我们应该着重认识它们的特点,为以后理解框架的底层源码做准备。)
单元测试
单元测试概述
- 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性。
目前测试方法是怎么进行的,存在什么问题
- 只有一个main方法,如果一个方法的测试失败了,其他方法测试会受到影响。
- 无法得到测试的结果报告,需要程序员自己去观察测试是否成功。
- 无法实现自动化测试。
![](https://i-blog.csdnimg.cn/blog_migrate/e9c9f032c334e8c0f3204249bc27cfc4.png)
Junit单元测试框架
- JUnit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用JUnit编写单元测试。
- 此外,几乎所有的IDE工具都集成了JUnit,这样我们就可以直接在IDE中编写并运行JUnit测试,JUnit目前最新版本是5。
JUnit优点
- JUnit可以灵活的选择执行哪些测试方法,可以一键执行全部测试方法。
- Junit可以生成全部方法的测试报告。
- 单元测试中的某个方法测试失败了,不会影响其他测试方法的测试。
![](https://i-blog.csdnimg.cn/blog_migrate/99b299eb751654de1d154e46d9c5807c.png)
单元测试快速入门
![](https://i-blog.csdnimg.cn/blog_migrate/1f090d21a07fc1a6ed7d32d01e1dadcc.png)
导包:
在测试方法上输入注解@Test,标红的话就还没导入Junit包,在标红处按快捷键Alt+回车选择需要导入的包即可,建议选择Junit4比较稳定,选择后在弹框OK就行(记得联网),它就会自动下载Junit4框架。
待测业务方法模拟:
编写测试方法:
断言:就是判断实际结果值是否与预期值相等,是则测试成功,否则会提示测试失败并给出提示信息
运行测试方法:在测试方法内右键运行对应测试方法或点击方法左侧的运行按钮
测试
测试成功显示
测试失败显示
可以设计多个测试方法进行测试,选择对应的方法运行即可(注意:断言是需要断言才断言,不断言就看代码有没有出bug)
如:
一键测试该类下的所有测试方法,该类内右键运行或类名左侧的运行按钮它就会自动找测试方法运行。
更强的是它可以运行某个包下的所有测试方法,对应包右键运行即可,它会取自动找该包下的测试方法运行。
单元测试常用注解
Junit常用注解(Junit 4.xxxx版本)
- 开始执行的方法:初始化资源。
- 执行完之后的方法:释放资源。
Junit常用注解(Junit 5.xxxx版本)
- 开始执行的方法:初始化资源。
- 执行完之后的方法:释放资源。
反射
反射的知识是比较抽象的,刚学一开始是无法知道它的作用的,我们应该先认识反射的基本特点,然后把它的API学会,最后再去了解它的作用。如果要深入理解反射还要依赖于后面学习的框架技术的底层源码才能进一步学习。
反射概述
- 反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。
- 在运行时,可以直接得到这个类的构造器对象:Constructor
- 在运行时,可以直接得到这个类的成员变量对象:Field
- 在运行时,可以直接得到这个类的成员方法对象:Method
- 这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。
反射的关键:
- 反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分。
类对象可以理解为人类,类的对象可以理解为人。人可以死,但人类不会灭绝
反射获取类对象
反射的第一步:获取Class类的对象,如此才可以解析类的全部成分
获取Class类的对象的三种方式
- 方式一:Class c1 = Class.forName(“全类名(全限名)”);
- 方式二:Class c2 = 类名.class
- 方式三:Class c3 = 对象.getClass();
![](https://i-blog.csdnimg.cn/blog_migrate/28658472ccc67fd26c39ac521aecb672.png)
反射获取构造器对象
使用反射技术获取构造器对象并使用
- 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
- Class类中用于获取构造器的方法
![](https://i-blog.csdnimg.cn/blog_migrate/0e3b656df4d71ec9bbef253d9743a1e1.png)
- getConstructors()
![](https://i-blog.csdnimg.cn/blog_migrate/348b1949cf711fc4f56466940e8529ff.png)
- getDeclaredConstructors()
![](https://i-blog.csdnimg.cn/blog_migrate/2f067913e841e6cc937f1ff8db405eb0.png)
- getConstructor(Class… parameterTypes)
![](https://i-blog.csdnimg.cn/blog_migrate/ca3de728103957fa535157d8c663087b.png)
- getDeclaredConstructor(Class… parameterTypes)
![](https://i-blog.csdnimg.cn/blog_migrate/40857155c5974ec736fb19f8347d05b8.png)
- 获取构造器的作用依然是初始化一个对象返回。
Constructor类中用于创建对象的方法
反射得到的构造器可以做什么?
-
依然是创建对象的
- public newInstance(Object… initargs)
-
如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
- setAccessible(boolean)
- 反射可以破坏封装性,私有的也可以执行了。
反射获取成员变量对象
使用反射技术获取成员变量对象并使用
- 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
- Class类中用于获取成员变量的方法
![](https://i-blog.csdnimg.cn/blog_migrate/8638bcfedfdae7326eed9b65f8091325.png)
获取全部成员变量:getDeclaredFields()
获取某个成员变量:getDeclaredField()
- 获取成员变量的作用依然是在某个对象中取值、赋值
Field类中用于取值、赋值的方法
明明有get方法取值和set方法赋值,为什么还要用这种方法赋值取值 ?
先别管,它是有特殊用途的,简单理解一下就是之前是对象追着给变量赋值,现在是变量追着对象让赋值,关系反转了。
反射得到成员变量可以做什么?
-
依然是在某个对象中取值和赋值。
- void set(Object obj, Object value):
- Object get(Object obj)
-
如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
- setAccessible(boolean)
反射获取方法对象
使用反射技术获取方法对象并使用
- 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
- Class类中用于获取成员方法的方法
![](https://i-blog.csdnimg.cn/blog_migrate/ef4bf3517a0bf613d122c6d2a21ae131.png)
- 获取成员方法的作用依然是在某个对象中进行执行此方法
Method类中用于触发执行的方法
获得类中的所有成员方法对象:getDeclaredMethods()
获取某个方法对象:getDeclaredMethod()
反射得到成员方法可以做什么?
-
依然是在某个对象中触发该方法执行。
- Object invoke(Object obj, Object… args)
-
如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
- setAccessible(boolean)
反射的作用-绕过编译阶段为集合添加数据
反射的作用-绕过编译阶段为集合添加数据
- 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的。
![](https://i-blog.csdnimg.cn/blog_migrate/135807c4ed3759e0cff5f5fafdcc6d06.png)
- 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。
泛型的类型约束是在写代码时(编译时)检测,使用反射是暴力通过地址塞数据。泛型是用来约束程序员别出错的,计算机不管。所以虽然new了两个ArrayList对象并使用了泛型,但通过反射直接获取它的类对象都是同一个,这就解释了编译后对泛型进行了擦除。
![](https://i-blog.csdnimg.cn/blog_migrate/62b5104c60bdc223fc56ee72ce96f7cc.png)
反射为何可以给约定了泛型的集合存入其他类型的元素?
- 编译成Class文件进入运行阶段的时候,泛型会自动擦除。
- 反射是作用在运行时的技术,此时已经不存在泛型了。
反射的作用-通用框架的底层原理
![](https://i-blog.csdnimg.cn/blog_migrate/6fac43959f29800a40fad6df436e783d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/669d461d2444b18b3045b4783eccc4bc.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3906f1c3bd0e0770ddd3605522f5b86b.png)
写入data.txt文件工具类
存入不同类型的数据到文件内
我们无法确定传进来的对象是哪个对象,也无法知道这个对象里有多少字段,但使用反射直接获取Class对象就可以直接获取这是哪个对象,有哪些字段。只有反射能解决这个问题,所以反射是做通用技术(比如框架)最好的方案之一。
总结:反射的作用
- 可以在运行时得到一个类的全部成分然后操作。
- 可以破坏封装性。(很突出)
- 也可以破坏泛型的约束性。(很突出)
- 更重要的用途是适合:做Java高级框架
- 基本上主流框架都会基于反射设计一些通用技术功能。
之前学习的时候说私有属性只有当前类可以访问,泛型是只能添加规定类型的数据,而使用反射后全都打破了这些规则,Java是没有底线的语言😏。(弹幕说:设计师也没有办法, 因为市场已有的项目已经很多了, 所以必须要兼容之前的项目, 要不然所有的项目都得改,说白了这个是历史遗留问题)
注解
注解概述
注解概述、作用
- Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
- Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。
![](https://i-blog.csdnimg.cn/blog_migrate/1a651cf6fe082003b269169e82d97506.png)
注解的作用是什么呢?
- 对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。
- 例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。
自定义注解
自定义注解 — 格式
- 自定义注解就是自己做一个注解来使用。
特殊属性
- value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!!
- 但是如果有多个属性, 且多个属性没有默认值,那么value名称是不能省略的。
只有一个value属性可以省略不写
多个属性且没有默认值value名称是不能省略的
元注解
- 元注解:注解注解的注解。 (放在注解上的注解,套娃)
元注解有两个:
- @Target: 约束自定义注解只能在哪些地方使用,
- @Retention:申明注解的生命周期
@Target中可使用的值定义在ElementType枚举类中,常用值如下
- TYPE,类,接口
- FIELD, 成员变量
- METHOD, 成员方法
- PARAMETER, 方法参数
- CONSTRUCTOR, 构造器
- LOCAL_VARIABLE, 局部变量
@Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下
- SOURCE: 注解只作用在源码阶段,生成的字节码文件中不存在
- CLASS: 注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值.
- RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)
![](https://i-blog.csdnimg.cn/blog_migrate/15df32084154be378b9dfc37d164cf4c.png)
注解解析
- 注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容。
与注解解析相关的接口
- Annotation: 注解的顶级接口,注解都是Annotation类型的对象
- AnnotatedElement:该接口定义了与注解解析相关的解析方法
![](https://i-blog.csdnimg.cn/blog_migrate/4ce4fb71d3e6c0067dabeb911cad810b.png)
- 所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口他们都拥有解析注解的能力
解析注解的技巧
- 注解在哪个成分上,我们就先拿哪个成分对象。
- 比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解
- 比如注解作用在类上,则要该类的Class对象,再来拿上面的注解
- 比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解
注解的应用场景一:junit框架
![](https://i-blog.csdnimg.cn/blog_migrate/3f390468692de96f4cc0d1842036837a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/f955c57387a77cb0ec756d3cb8c44ad8.png)
动态代理(设计模式:代理模式)
设计模式(代理模式(动态代理))
XML
需要学会什么?
XML
XML概述
- XML是可扩展标记语言(eXtensible Markup Language)的缩写,它是是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据。
![](https://i-blog.csdnimg.cn/blog_migrate/1b1e01070c7d5d0066e2d7a16bb3251b.png)
XML的几个特点和使用场景
- 一是纯文本,默认使用UTF-8编码;二是可嵌套;
- 如果把XML内容存为文件,那么它就是一个XML文件。
- XML的使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息。
![](https://i-blog.csdnimg.cn/blog_migrate/9159af6367bbe934acfac8f19fed2777.png)
XML的创建、语法规则
XML的创建
- 就是创建一个XML类型的文件,要求文件的后缀必须使用xml,如hello_world.xml
IDEA创建XML文件的操作步骤
XML的语法规则
- XML文件的后缀名为:xml
- 文档声明必须是第一行
![](https://i-blog.csdnimg.cn/blog_migrate/dacc2c607759d899b1b56828883e12c6.png)
XML的标签(元素)规则
- 标签由一对尖括号和合法标识符组成:
<name></name>
,必须存在一个根标签,有且只能有一个。 - 标签必须成对出现,有开始,有结束:
<name></name>
- 特殊的标签可以不成对,但是必须有结束标记,如:
<br/>
- 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来
<student id = “1"></name>
- 标签需要正确的嵌套
![](https://i-blog.csdnimg.cn/blog_migrate/58784429415f8c47af12c5231c4557cd.png)
XML的其他组成
XML文件中可以定义注释信息:<!– 注释内容 -->
XML文件中可以存在以下特殊字符
XML文件中可以存在CDATA区: <![CDATA[ …内容… ]]>
XML文档约束方式一-DTD约束[了解]
什么是文档约束?
![](https://i-blog.csdnimg.cn/blog_migrate/58ac5f8cd97179c6241283701a8d81bc.png)
问题:由于XML文件可以自定义标签,导致XML文件可以随意定义,程序在解析的时候可能出现问题。
- 文档约束:是用来限定xml文件中的标签以及属性应该怎么写。(以此强制约束程序员必须按照文档约束的规定来编写xml文件。)
文档约束的分类
- DTD
- schema
![](https://i-blog.csdnimg.cn/blog_migrate/f5ecbffca0084967b79f82e96c895ab7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/efdfce31b83495f55a6db307aa436322.png)
XML的文档约束-DTD的作用和问题?
- 可以约束XML文件的编写。
- 不能约束具体的数据类型。
XML文档约束方式二-schema约束[了解]
文档约束-schema
- schema可以约束具体的数据类型,约束能力上更强大。
- schema本身也是一个xml文件,本身也受到其他约束文件的要求,所以编写的更加严谨
XML的文档约束-schema的优点?
- 可以约束XML文件的标签内容格式,以及具体的数据类型。
- 本身也是xml文件,格式更严谨。
XML解析技术
XML解析技术概述
XML的数据的作用是什么,最终需要怎么处理?
- 存储数据、做配置信息、进行数据传输。
- 最终需要被程序进行读取,解析里面的信息。
什么是XML解析
- 使用程序读取XML中的数据
两种解析方式
- SAX解析
- DOM解析
![](https://i-blog.csdnimg.cn/blog_migrate/b3aedceca9650befb2c141bad5651e85.png)
Dom常见的解析工具
DOM解析解析文档对象模型
Dom4J解析XML文件
![](https://i-blog.csdnimg.cn/blog_migrate/b3f0165fe3aba1ffba33ab0894cd5d1a.png)
1、官网下载Dom4j框架:https://dom4j.github.io/ (下载核心jar包就行)
2、在项目中导入核心jar包
待解析xml文件
Dom4j解析XML-得到Document对象
SAXReader类
Document类
![](https://i-blog.csdnimg.cn/blog_migrate/65176e856743ed683cfc33268881ba75.png)
Dom4J解析XML文件中的各种节点(元素、属性、文本)
Dom4J解析XML文件-案例实战
![](https://i-blog.csdnimg.cn/blog_migrate/3be8c6c43140178b8b843c07ef89f4ac.png)
Dom4J的解析后的数据形式。
- 通常数据会封装成Java的对象,如单个对象,或者集合对象形式
XML检索技术:Xpath
如果需要从XML文件中检索需要的某个信息(如name)怎么解决?
- Dom4j需要进行文件的全部解析,然后再寻找数据。
- Xpath技术更加适合做信息检索。
XPath介绍
- XPath在解析XML文档方面提供了一独树一帜的路径思想,更加优雅,高效
- XPath使用路径表达式来定位XML文档中的元素节点或属性节点。
示例
- /元素/子元素/孙元素
- //子元素//孙元素
![](https://i-blog.csdnimg.cn/blog_migrate/24435169c7a8fd5c6ead3001c81c4e61.png)
导入dom4j和jaxen的jar包
Xpath的四大检索方案
- 绝对路径
- 相对路径
- 全文检索
- 属性查找
XPath:绝对路径
- 采用绝对路径获取从根节点开始逐层的查找/contactList/contact/name节点列表并打印信息
XPath:相对路径
- 先得到根节点contactList
- 再采用相对路径获取下一级contact 节点的name子节点并打印信息
XPath:全文搜索
- 直接全文搜索所有的name元素并打印
XPath:属性查找
- 在全文中搜索属性,或者带属性的元素
注:
该内容是根据B站黑马程序员学习时所记,相关资料可在B站查询:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)