JavaSE进阶01:继承、修饰符
JavaSE进阶02:多态、抽象类、接口
JavaSE进阶03:内部类、Lambda表达式
JavaSE进阶04:API中常用工具类
JavaSE进阶05:包装类、递归、数组的高级操作、异常
JavaSE进阶06:Collection集合、迭代器、List、ArrayList、LinkedList
JavaSE进阶07:泛型、Set集合、TreeSet、二叉树、红黑树
JavaSE进阶08:HashSet、Map集合、HashMap、TreeMap、可变参数、不可变集合
JavaSE进阶09:Stream流、File类
JavaSE进阶10:IO流、字节流、字节缓冲流
JavaSE进阶11:字符流、字符缓冲流、转换流、对象操作流、Properties集合
JavaSE进阶12:多线程、线程同步、线程池
JavaSE进阶13:网络编程入门、UDP通信程序、TCP通信程序、日志、枚举
JavaSE进阶14:类加载器、反射
JavaSE进阶15:XML、注解、JUnit单元测试
JavaSE进阶扩充:JDK8 HashMap底层分析(了解)
JavaSE进阶扩充:JDK8 ArrayList线程安全问题和源码分析、集合常见面试题
Java进阶作业
万维网联盟(W3C)创建于1994年,又称W3C理事会。1994年10月在麻省理工学院计算机科学实验室成立。建立者: Tim Berners-Lee (蒂姆·伯纳斯·李)。W3C是Web技术领域最具权威和影响力的国际中立性技术标准机构
到目前为止,W3C已发布了200多项影响深远的Web技术标准及实施指南。如广为业界采用的超文本标记语言HTML(标准通用标记语言下的一个应用)。可扩展标记语言XML(标准通用标记语言下的一个子集)。 以及帮助残障人士有效获得Web信息的无障碍指南(WCAG)等
w3school网站
XML概述
作用
作为配置文件的优势
<student>
<student> student>
前边的是开始标签,后边的是结束标签
<address/>
<student id="1"> student>
这是正确的: <student id="1"><name>张三name> student>
这是错误的: <student id="1"><name>张三student>name>
语法规则
XML文件的后缀名为:xml
文档声明必须是第一行第一列
version:该属性是必须存在的,固定值1.0
encoding:该属性不是必须的,打开当前xml文件的时候应该是使用什么字符编码表(一般取值都是UTF-8)
standalone: 该属性不是必须的,描述XML文件是否依赖其他的xml文件,取值为yes/no
必须存在一个根标签,有且只能有一个
XML文件中可以定义注释信息
XML文件中可以存在以下特殊字符
< < 小于
> > 大于
& & 和号
' ' 单引号
" " 引号
XML文件中可以存在CDATA区
示例代码
<students>
<student id="1">
<name>张三name>
<age>23age>
<info>'学生'<>&的" 信息" info>
<message> &的"信息" ]]]>message>
student>
<student id="2">
<name>李四name>
<age>24age>
student>
students>
正确时,浏览器打开不报错或IDEA不标红
概述
xml解析就是从xml中获取到数据
常见的解析思想
DOM(Document Object Model)文档对象模型:就是把文档的各个组成部分看做成对应的对象。
会把xml文件全部加载到内存,在内存中形成一个树形结构,再获取对应的值
常见的解析工具
解析的准备工作
我们可以通过网站:https://dom4j.github.io/ 去下载dom4j
将dom4j-1.6.1.zip解压,找到里面的dom4j-1.6.1.jar
在idea中当前模块下新建一个libs文件夹,将jar包复制到文件夹中
选中jar包 -> 右键 -> 选择add as library即可
需求
代码实现
/*myxml\\xml\\student.xml*/
<?xml version="1.0" encoding="UTF-8" ?>
<!--注释的内容-->
<!--本xml文件用来描述多个学生信息-->
<students>
<!--第一个学生信息-->
<student id="1">
<name>张三</name>
<age>23</age>
</student>
<!--第二个学生信息-->
<student id="2">
<name>李四</name>
<age>24</age>
</student>
<aaa></aaa>
</students>
/*学生类*/
public class Student {
private String id;
private String name;
private int age;
public Student() {
}
public Student(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
/**
* 利用dom4j解析xml文件
*/
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class XmlParse {
public static void main(String[] args) throws DocumentException {
//1.获取一个解析器对象
SAXReader saxReader = new SAXReader();
//2.利用解析器把xml文件加载到内存中,并返回一个文档对象
Document document = saxReader.read(new File("MyXML\\xml\\student.xml"));
//3.获取到根标签
Element rootElement = document.getRootElement();
//4.通过根标签来获取student标签
//elements():可以获取调用者所有的子标签.会把这些子标签放到一个集合中返回.
//elements("标签名"):可以获取调用者所有的指定的子标签,
//List list = rootElement.elements();
//System.out.println(list.size());//输出3,因为xml中有2个student标签和1个aaa标签
List<Element> studentElements = rootElement.elements("student");//只获取student标签
//用来装学生对象
ArrayList<Student> list = new ArrayList<>();
//5.遍历集合,得到每一个student标签
for (Element element : studentElements) {
//element依次表示每一个student标签
//获取id这个属性
Attribute attribute = element.attribute("id");
//获取id的属性值
String id = attribute.getValue();
//获取name标签
//element("标签名"):获取调用者指定的子标签
Element nameElement = element.element("name");
//获取这个标签的标签体内容
String name = nameElement.getText();
//获取age标签
Element ageElement = element.element("age");
//获取age标签的标签体内容
String age = ageElement.getText();
//封装加入集合
Student s = new Student(id,name,Integer.parseInt(age));
list.add(s);
}
//遍历操作
for (Student student : list) {
System.out.println(student);
}
}
}
/*
Student{id='1', name='张三', age=23}
Student{id='2', name='李四', age=24}
*/
什么是约束
约束的分类
编写DTD约束
步骤
创建一个文件,这个文件的后缀名为.dtd
看xml文件中使用了哪些元素
可以定义元素判断元素是简单元素还是复杂元素
简单元素:没有子元素。
复杂元素:有子元素的元素;
引入DTD约束
引入DTD约束的三种方法
引入本地dtd
在xml文件内部引入
引入网络dtd
代码实现
DOCTYPE persons SYSTEM 'persondtd.dtd'>
<persons>
<person>
<name>张三name>
<age>23age>
person>
persons>
DOCTYPE persons [
<!ELEMENT persons (person)>
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
<persons>
<person>
<name>张三name>
<age>23age>
person>
persons>
DOCTYPE persons PUBLIC "dtd文件的名称" "dtd文档的URL">
<persons>
<person>
<name>张三name>
<age>23age>
person>
persons>
DTD语法
定义元素
定义属性
代码实现
<!ELEMENT persons (person+)>
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST person id CDATA #REQUIRED>
DOCTYPE persons SYSTEM 'persondtd.dtd'>
<persons>
<person id="001">
<name>张三name>
<age>23age>
person>
<person id = "002">
<name>张三name>
<age>23age>
person>
persons>
编写schema约束
代码实现
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.xxx.com/javase"
elementFormDefault="qualified"
>
<element name="persons">
<complexType>
<sequence>
<element name = "person">
<complexType>
<sequence>
<element name = "name" type = "string">element>
<element name = "age" type = "string">element>
sequence>
complexType>
element>
sequence>
complexType>
element>
schema>
引入schema约束
schema约束定义属性
代码示例
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.xxx.com/javase"
elementFormDefault="qualified"
>
<element name="persons">
<complexType>
<sequence>
<element name = "person">
<complexType>
<sequence>
<element name = "name" type = "string">element>
<element name = "age" type = "string">element>
sequence>
<attribute name="id" type="string" use="required">attribute>
complexType>
element>
sequence>
complexType>
element>
schema>
<persons
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itheima.cn/javase"
xsi:schemaLocation="http://www.itheima.cn/javase person.xsd"
>
<person id="001">
<name>张三name>
<age>23age>
person>
persons>
注解概述:对我们的程序进行标注和解释
注解和注释的区别
使用注解进行配置配置的优势:代码更加简洁、方便
注解分类
注解名 | 说明 |
---|---|
@Override | 描述子类重写父类的方法 |
@Deprecated | 描述方法过时 |
@SuppressWarnings | 压制警告 |
格式
public @interface 注解名称 {
public 属性类型 属性名() default 默认值 ;
}
属性类型
代码演示
/*注解类*/
public @interface Anno2 {
}
/*枚举类*/
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}
/*注解类Anno1 */
public @interface Anno1 {
//定义一个基本类型的属性
public int a() default 23;
//定义一个String类型的属性
//public String name();
//定已一个Class类型的属性
public Class clazz() default Anno2.class;
//定义一个注解类型的属性
public Anno2 anno() default @Anno2;
//定义一个枚举类型的属性
public Season season() default Season.SPRING;
//以上类型的一维数组
//如:int数组
public int[] arr() default {1,2,3,4,5};
//如:枚举数组
public Season[] seasons() default {Season.SPRING,Season.SUMMER};
//value当后期我们在使用注解的时候,如果我们只需要给注解的value属性赋值,那么value=就可以省略
public String value();
}
/*枚举测试类*/
//在使用注解的时候如果注解里面的属性没有指定默认值,那么我们就需要手动给出注解属性的设置值。
//@Anno1(name="123",value="abc")
@Anno1("abc")//只需要给注解的value属性赋值时,那么value=就可以省略 ,只有value这个单词可以
public class AnnoDemo {
}
自定义注解案例
需求
自定义一个注解@Test,用于指定类的方法上,如果某一个类的方法上使用了该注解,就执行该方法
实现步骤
代码实现
/*注解类*/
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(value = RetentionPolicy.RUNTIME)//此为元注解:表示Test这个注解的存活时间
public @interface Test {
}
/*对象类*/
public class UseTest {
//没有使用Test注解
public void show(){
System.out.println("UseTest....show....");
}
//使用Test注解
@Test
public void method(){
System.out.println("UseTest....method....");
}
//没有使用Test注解
public void function(){
System.out.println("UseTest....function....");
}
}
/*测试类*/
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class AnnoDemo2 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
//1.通过反射获取UseTest类的字节码文件对象
Class clazz = Class.forName("UseTest");
//创建对象
Constructor constructor = clazz.getConstructor();
UseTest useTest = (UseTest) constructor.newInstance();
//2.通过反射获取这个类里面所有的方法对象
Method[] methods = clazz.getDeclaredMethods();
//3.遍历数组,得到每一个方法对象
for (Method method : methods) {//method依次表示每一个方法对象。
//isAnnotationPresent(Class extends Annotation> annotationClass)
//判断当前方法上是否有指定的注解。
//参数:注解的字节码文件对象
//返回值:布尔结果。 true 存在 false 不存在
if(method.isAnnotationPresent(Test.class)){
method.invoke(useTest);//invoke执行方法需要调用者
}
}
}
}
/*
UseTest....method....
*/
概述
元注解就是描述注解的注解
元注解介绍
元注解名 | 说明 |
---|---|
@Target | 指定了注解能在哪里使用 |
@Retention | 可以理解为保留时间(生命周期) |
@Inherited | 表示修饰的自定义注解可以被子类继承 |
@Documented | 表示该自定义注解,会出现在API文档里面。 |
/*注解类*/
import java.lang.annotation.*;
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD}) //指定注解使用的位置(成员变量,类,方法)
@Retention(RetentionPolicy.RUNTIME) //指定该注解的存活时间,若不写该注解只能存活在源码阶段即java文件时存在,class文件就不存在了
@Inherited //指定该注解可以被继承
public @interface Anno3 {
}
/*人类*/
@Anno3
public class Person {
}
/*学生类*/
public class Student extends Person{
public void show(){
System.out.println("student.......show..........");
}
}
/*测试类*/
public class StudentDemo {
public static void main(String[] args) throws ClassNotFoundException {
//获取到Student类的字节码文件对象
Class clazz1 = Class.forName("Person");
Class clazz2 = Class.forName("Student");
//获取注解,判断class是否有注解
boolean result1 = clazz1.isAnnotationPresent(Anno3.class);
boolean result2 = clazz2.isAnnotationPresent(Anno3.class);
System.out.println("Person:"+result1);
System.out.println("Student:"+result2);
}
}
/*
Person:true
Student:true
*/
都为true表示Student类已经继承了父类Person的注解Anno3。
JUnit是一个 Java 编程语言的单元测试工具,JUnit 是一个非常重要的测试工具。
下载JUnit4
使用步骤
代码示例
import org.junit.Test;
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);
}
}
此时会发现IDEA的方法可以直接测试,不再不需要创建main()方法测试。
注解说明
注解 | 含义 |
---|---|
@Test | 表示测试该方法 |
@Before | 在测试的方法前运行 |
@After | 在测试的方法后运行 |
import org.junit.After;
import org.junit.Test;
import org.junit.Before;
public class JunitDemo2 {
@Before
public void before() {
// 在执行测试代码之前执行,一般用于初始化操作
System.out.println("before");
}
@Test
public void test() {
// 要执行的测试代码
System.out.println("test");
}
@After
public void after() {
// 在执行测试代码之后执行,一般用于释放资源
System.out.println("after");
}
}
/*
before
test
after
*/
总结:单元测试会默认给File路径加上 模块名
package com.xxx.driud;
import org.junit.Test;
import java.io.File;
public class TestDemo {
public static void main(String[] args) {
File file=new File("MyModule\\src\\druid.properties");
System.out.print("main方法绝对路径1:");
System.out.println(file.getAbsolutePath());
System.out.print("main方法绝对路径2:");
new TestDemo().unitTesting();
}
@Test
public void unitTesting(){
File file=new File("MyModule\\src\\druid.properties");
System.out.println(file.getAbsolutePath());
}
}
/*
main方法绝对路径1:D:\AAAAA\IDEAWorkSpace\MyProject\MyModule\src\druid.properties
main方法绝对路径2:D:\AAAAA\IDEAWorkSpace\MyProject\MyModule\src\druid.properties
单元测试输出:D:\AAAAA\IDEAWorkSpace\MyProject\MyModule\MyModule\src\druid.properties
*/