一、泛型
使用泛型可以使集合记住集合内元素的类型,且能够达到只要编译时不出现问题,运行时就不会有异常。
泛型只作用于代码编译阶段。
泛型上限指一个操作泛型最大的操作父类,例如上限为“Number”,所能接收到的类型只能是Number和子类。
泛型下限指的是只能设置其具体的类或者父类。
package generic;
import org.junit.Test;
import java.util.*;
public class Generic {
@Test
public void test05(){
Map<Integer,String> map=new HashMap<>();
map.put(1,"lili");
map.put(2,"haha");
//泛型嵌套
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for(Map.Entry entry: entrySet){
System.out.println(entry.getKey()+"---"+entry.getValue());
}
}
@Test
public void test04(){
String[] arrays={"1","2","3"};
func(arrays,0,1);
System.out.println(Arrays.toString(arrays));
}
//泛型方法
public static <T> T[] func(T[] array,int i,int t){//T---返回类型
//交换
T temp=array[i];
array[i]=array[t];
array[t]=temp;
return array;
}
@Test
public void test03(){
Node<Number> node1=new Node<Number>(10);
Node<Integer> node2=new Node<Integer>(20);
Node<Double> node3=new Node<Double>(30.0);
// getData(node1);
// getData(node2);//node2与node类型不匹配,不能传递
// getData1(node1);
// getData1(node2);
// getUpperNumberData(node1);
// getUpperNumberData(node2);
// getDownerNumberData(node1);
// getDownerNumberData(node2);
// node3是Double类型,超出Integer类型,报错
// getDownerNumberData(node3);
}
public static void getData(Node<Number> node){
node.setData(1);
System.out.println(node.getData());
}
//使用通配符,解决类型不匹配问题
public static void getData1(Node<?> node){
// node.setData(1);//?--不知道参数是什么类型,不能进行修改
System.out.println(node.getData());
}
//设置泛型上限
public static void getUpperNumberData(Node<? extends Number> node){
System.out.println(node.getData());
}
//设置泛型下限
public static void getDownerNumberData(Node<? super Integer> node){
System.out.println(node.getData());
}
@Test
public void test02(){
Node<Integer> node1=new Node<Integer>(18);
System.out.println(node1.getData());
}
@Test
public void test01(){
List<String> list=new ArrayList<>();
list.add("周日");
// list.add(18);
// list.add(new Object());
for (int i = 0; i < list.size(); i++) {
}
}
}
//自定义泛型类
package generic;
public class Node<T>{
private T data;
public Node() {
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node(T data) {
this.data = data;
}
}
二、正则表达式
package regex;
import org.junit.Test;
import java.sql.SQLOutput;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//正则表达式
public class Regex{
@Test
public void test1(){
String s="5201314";
boolean matches = s.matches("[0-9]+");//[0-9]----表示一个字符的范围,+----表示多个字符
boolean matches1 = s.matches("\\d+");//更多匹配方法参考API文档
System.out.println(matches);
System.out.println(matches1);
}
//创建一个匹配模式
@Test
public void test(){
Pattern p=Pattern.compile("a*b");//a*-----aaaaaaaa,*---多个,其他参考API文档
Matcher matcher=p.matcher("aaaaaab");//true
// Matcher matcher1=p.matcher("aaa234bbbbhgfb");//false
boolean b=matcher.matches();
System.out.println(b);
}
}
三、枚举
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错,枚举可以让编译器在编译时就可以控制源程序赋给的非法值,使用普通变量的方式在开发阶段无法实现这一目标。
//接口
public interface Info {
public int getColor();
}
//枚举定义单例
public enum Singleton {
SINGLETON;
public void method(){
System.out.println("method方法");
}
}
//枚举
public enum Color implements Info {
RED{
@Override
public String getColor1() {
return "red";
}
},GREEN {
@Override
public String getColor1() {
return "green";
}
},BLUE {
@Override
public String getColor1() {
return "blue";
}
},BLACK(1) {
@Override
public String getColor1() {
return "black";
}
};
private int color;
Color(){
System.out.println("无参构造方法");
}//枚举构造函数不能是public型
Color(int color){
this.color=color;
System.out.println("有参构造方法");
}
public int getColor() {
return color;
}
//可以定义抽象方法
public abstract String getColor1();
}
//实现类
import org.junit.Test;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
public class EnumDemo{
public static final int RED=0x1;
public static final int GREEN=0x2;
public static final int BLUE=0x3;
public int color;
public Color colorEnum;
//使用枚举实现单例模式
@Test
public void test5(){
Singleton.SINGLETON.method();
}
@Test
public void test4(){
System.out.println(Color.RED);//依次调用每个类型
System.out.println(Color.RED.getColor());
}
@Test
public void test3(){
// EnumSet<Color> es=new EnumSet<>(){}//抽象类,需要实现方法
EnumSet<Color> es=EnumSet.allOf(Color.class);
for(Color c:es){
System.out.println(c);
}
EnumMap<Color,String> em=new EnumMap<Color, String>(Color.class);
em.put(Color.RED,"red");
}
@Test
public void test2(){
colorEnum=Color.RED;//枚举型
System.out.println(colorEnum);//RED
System.out.println(colorEnum.ordinal());//序号
Color[] values = Color.values();//枚举类型的值
System.out.println(Arrays.toString(values));
}
@Test
public void test1(){
color=RED;
color=2;
}
}
四、注解
代码里做的特殊标记,这些标记可以在编译、类加载、运行时在不改变原有逻辑的情况下,被读取,并执行相应的处理。
Annotation类似于修饰符一样被使用,可以用于包、类、构造方法、方法、成员变量、参数、局部变量的声明。
Annotation是一个接口,java.lang.Annotation接口
//系统提供的三种注解:
@Override @Deprecated @SuppressWarnings
//测试类
package annotation;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class AnnotationDemo {
@Test
public void test1(){
Cat cat=new Cat("huahua",2);
cat.printInfo();//横线,代表调用了一个已过时的方法
@SuppressWarnings("all")//消除警告信息
List list=new ArrayList();
list.add("vince");
list.add(10);
list.add(10.0);
}
}
//实体类
package annotation;
public class Cat {
private String name;
private int age;
@Override//用于验证方法是否是覆盖了父类中的方法
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Deprecated//用于标记方法已过时,不建议使用
public String printInfo(){
return "Cat{" +
"name='" + name + '\'' +
", 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 Cat(String name, int age) {
this.name = name;
this.age = age;
}
public Cat() {
}
}
自定义注解:
1.编写注解
2.在类上应用注解
3.对 应用了注解的类 进行反射 操作的类
//自定义注解
package annotation;
import java.lang.annotation.*;
import java.lang.reflect.Type;
@Documented//注解的注解,生成DOC文档时使用,注释的注解
@Retention(RetentionPolicy.RUNTIME)//作用范围在运行时,注释注解
@Target(ElementType.TYPE)//表示Annotation的应用范围(类型,方法,属性等)
@Inherited//表示Annotation可以被子类继承
public @interface MyAnnotation {
//定义变量
public String name();//变量
public int age() default 2;//定义默认值,使用注解时可以不赋值
public String[] like();//只进行定义
public Color color();//定义一个枚举类型变量
}
//测试类
package annotation;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
public class AnnotationDemo {
//反射处理注解
@Test
public void test2(){
Class<Cat> catClass = Cat.class;
//获取类上应用的指定注解
MyAnnotation annotation = catClass.getAnnotation(MyAnnotation.class);
//获取注解上的变量值
String name = annotation.name();
int age = annotation.age();
Color color = annotation.color();
String[] like = annotation.like();
//实例化对象
try {
Cat cat = catClass.newInstance();
cat.setName(name);
cat.setAge(age);
cat.setColor(color);
cat.setLike(like);
System.out.println(cat);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//枚举类
package annotation;
public enum Color {
RED,GREEN,YELLOW;
}
//实体类
package annotation;
import java.util.Arrays;
@MyAnnotation(name = "haha",like = {"111","222"},color = Color.RED)
public class Cat {
private String name;
private int age;
private String[] like;
private Color color;
public String[] getLike() {
return like;
}
public void setLike(String[] like) {
this.like = like;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", like=" + Arrays.toString(like) +
", color=" + color +
'}';
}
@Deprecated//用于标记方法已过时,不建议使用
public String printInfo(){
return "Cat{" +
"name='" + name + '\'' +
", 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 Cat(String name, int age, String[] like, Color color) {
this.name = name;
this.age = age;
this.like = like;
this.color = color;
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public Cat() {
}
}
五、XML
XML(Extensible Markup Language可扩展标记语言)
XML是一个以文本来描述数据的文档。
XML技术的用途:
- 充当显示数据(以XML充当显示层)
- 存储数据(存储层)的功能
- 以XML描述数据,并在联系服务器与系统的其余部分之间传递
从某种角度讲,XML是数据封装和消息传递技术。
掌握XML的解析方法是核心:SAX和DOM
1、SAX解析
//SAX解析
//Person.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<people>
<person personid="E01">
<name>Tony</name>
<address>10 Downing Street,London,UK</address>
<tel>98765</tel>
<fax>98765</fax>
<email>tony@everywhere.com</email>
</person>
<person personid="E02">
<name>Bill</name>
<address>White House,USA</address>
<tel>(001) 6400 98765</tel>
<fax>(001) 6400 98765</fax>
<email>bill@everywhere.com</email>
</person>
</people>
//实体类
package xml;
public class Person {
private String personid;
private String name;
private String address;
private String tel;
private String fax;
private String email;
@Override
public String toString() {
return "xml.Person{" +
"personid='" + personid + '\'' +
", name='" + name + '\'' +
", address='" + address + '\'' +
", tel='" + tel + '\'' +
", fax='" + fax + '\'' +
", email='" + email + '\'' +
'}';
}
public String getPersonid() {
return personid;
}
public void setPersonid(String personid) {
this.personid = personid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Person(String personid, String name, String address, String tel, String fax, String email) {
this.personid = personid;
this.name = name;
this.address = address;
this.tel = tel;
this.fax = fax;
this.email = email;
}
public Person() {
}
}
//SAX解析类
package xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
public class PersonHandler extends DefaultHandler {
//解析文档变成对象,两个对象使用集合存储
private List<Person> list=null;
private Person p;//当前正在解析的对象
private String tag;//用于记录当前正在解析的标签名
public List<Person> getList() {
return list;
}
//开始解析文档时调用
@Override
public void startDocument() throws SAXException {
super.startDocument();
list=new ArrayList<>();
System.out.println("开始解析文档...");
}
//XML文档解析结束时调用
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("解析文档结束!");
}
/*uri:命名空间
* localName:不带前缀的标签名<Person>
* qName:带前缀的标签名<aa:Person>
* attributes:当前标签的属性集合
* */
//解析开始元素时调用,例如标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if("person".equals(qName)){
p=new Person();
String personid = attributes.getValue("personid");
p.setPersonid(personid);
}
tag=qName;
System.out.println("startElement-----"+qName);
}
//解析结束元素时调用
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if ("person".equals(qName)) {
list.add(p);
}
tag=null;
System.out.println("startElement-----"+qName);
}
//解析文本内容时调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if(tag!=null){
if("name".equals(tag)){
p.setName(new String(ch,start,length));
}else if("address".equals(tag)){
p.setAddress(new String(ch,start,length));
}else if("tel".equals(tag)){
p.setTel(new String(ch,start,length));
}
else if("fax".equals(tag)){
p.setFax(new String(ch,start,length));
}
else if("email".equals(tag)){
p.setEmail(new String(ch,start,length));
}
System.out.println(ch);
}
}
}
//测试类
package xml;
import javafx.scene.media.VideoTrack;
import org.junit.Test;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class XMLDemo {
/*SAX解析:
1、基于事件驱动
2、顺序读取,速度快
3、不能任意读取节点,灵活性差
4、解析时占用的内存小
5、SAX更适用于性能要求更高的的设备上使用
*/
@Test
public void test1() throws ParserConfigurationException, SAXException, IOException {
// 1、创建一个SAX解析器工厂对象
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
// 2、通过工厂对象创建SAX解析器
SAXParser saxParser = saxParserFactory.newSAXParser();
// 3、创建一个数据处理器(需要我们自己编写)
PersonHandler personHandler = new PersonHandler();
// 4、开始解析
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/Person.xml");
saxParser.parse(is,personHandler);
List<Person> list = personHandler.getList();
for(Person p:list){
System.out.println(p);
}
}
}
2、DOM解析
/* DOM解析:
1、基于树形结构
2、通过解析器一次性把文档加载到内存中,比较占用内存
3、可以随机访问,更加灵活,更适合WEB开发中使用
*/
@Test
public void domParseXML() throws ParserConfigurationException, IOException, SAXException {
//1、创建一个DOM解析器工厂类对象
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//2、通过工厂对象创建解析器对象
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
//3、解析文档
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/Person.xml");
//此代码完成后,整个XML文档已经被加载到内存中,以数状形式存储
Document parse = documentBuilder.parse(is);
//4、从内存中读取数据
//获取节点名称为person的所有节点,返回节点集合
NodeList person = parse.getElementsByTagName("person");
ArrayList<Person> personArrayList = new ArrayList<>();
Person p=null;
//此循环会迭代两次
for (int i = 0; i < person.getLength(); i++) {
Node item = person.item(i);
p=new Person();
//获取节点的属性值
String personid = item.getAttributes().getNamedItem("personid").getNodeValue();
p.setPersonid(personid);
//获取当前节点的所有子节点
NodeList childNodes = item.getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
Node item1 = childNodes.item(j);
String nodeName = item1.getNodeName();
if("name".equals(nodeName)){
p.setName(item1.getFirstChild().getNodeValue());
}else if("address".equals(nodeName)){
p.setAddress(item1.getFirstChild().getNodeValue());
}else if("tel".equals(nodeName)){
p.setTel(item1.getFirstChild().getNodeValue());
}
else if("fax".equals(nodeName)){
p.setFax(item1.getFirstChild().getNodeValue());
}
else if("email".equals(nodeName)){
p.setEmail(item1.getFirstChild().getNodeValue());
}
}
personArrayList.add(p);
}
System.out.println("结果");
System.out.println(Arrays.toString(personArrayList.toArray()));
}
/*JDOM解析xml,使用jdom的jar包
1、与DOM类似,基于树形结构
2、与DOM区别:第三方开源组件,实现使用Java的Collection接口,比DOM效率快
* */
@Test
public void JDOMParseXML() throws IOException, JDOMException {
//创建JDOM解析器
SAXBuilder saxBuilder = new SAXBuilder();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/Person.xml");
org.jdom2.Document build = saxBuilder.build(is);
Element rootElement = build.getRootElement();
List<Person> list=new ArrayList<>();
Person person=null;
List<Element> children=rootElement.getChildren();
for(Element e:children){
person=new Person();
String personid = e.getAttributeValue("personid");
person.setPersonid(personid);
List<Element> children1 = e.getChildren();
for(Element ec:children1){
String name = ec.getName();
if("name".equals(name)){
person.setName(ec.getText());
}else if("address".equals(name)){
person.setAddress(ec.getText());
}else if("tel".equals(name)){
person.setTel(ec.getText());
} else if("fax".equals(name)){
person.setFax(ec.getText());
} else if("email".equals(name)){
person.setEmail(ec.getText());
}
}
list.add(person);
}
System.out.println(Arrays.toString(list.toArray()));
}
3、DOM4J解析
/*
* DOM4J解析,使用dom4j的jar包
* 1、基于树形结构,第三方组件
* 2、解析速度快,效率更高,使用的Java中的迭代器实现数据读取,在web框架中使用较多(Hibernate)
* */
@Test
public void dom4jParseXML() throws DocumentException {
SAXReader saxReader = new SAXReader();
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/Person.xml");
org.dom4j.Document read = saxReader.read(is);
org.dom4j.Element rootElement = read.getRootElement();
Iterator<org.dom4j.Element> iterator = rootElement.elementIterator();
List<Person> list=new ArrayList<>();
Person p=null;
while (iterator.hasNext()){
p=new Person();
org.dom4j.Element element = iterator.next();
p.setPersonid(element.attributeValue("personid"));
Iterator<org.dom4j.Element> iterator1 = element.elementIterator();
while (iterator1.hasNext()){
org.dom4j.Element next = iterator1.next();
String name = next.getName();
if("name".equals(name)){
p.setName(next.getText());
}else if("address".equals(name)){
p.setAddress(next.getText());
}else if("tel".equals(name)){
p.setTel(next.getText());
} else if("fax".equals(name)){
p.setFax(next.getText());
} else if("email".equals(name)){
p.setEmail(next.getText());
}
}
list.add(p);
}
System.out.println(Arrays.toString(list.toArray()));
}
4、把对象转为XML文件写入
/*把对象转为XML文件写入
* */
@Test
public void xmlEnCoder() throws FileNotFoundException {
BufferedOutputStream bufferedOutputStream =
new BufferedOutputStream(new FileOutputStream("test.xml"));
XMLEncoder xmlEncoder = new XMLEncoder(bufferedOutputStream);
Person p=new Person();
p.setPersonid("111");
p.setAddress("beijing");
p.setEmail("123456@com");
p.setFax("4567");
p.setTel("1234567890");
p.setName("haha");
xmlEncoder.writeObject(p);
xmlEncoder.close();
}
5、从XML文件中读取对象
/*从XML文件中读取对象*/
@Test
public void xmlDeCorder() throws FileNotFoundException {
BufferedInputStream bufferedInputStream =
new BufferedInputStream(new FileInputStream("test.xml"));
XMLDecoder xmlDecoder = new XMLDecoder(bufferedInputStream);
Person p = (Person)xmlDecoder.readObject();
System.out.println(p);
}
6、XStream解析
/*使用XStream组件实现XML的解析与生成,xstream和xpp3的jar包
*/
@Test
public void xStream(){
Person p=new Person();
p.setPersonid("111");
p.setAddress("beijing");
p.setEmail("123456@com");
p.setFax("4567");
p.setTel("1234567890");
p.setName("haha");
XStream xStream = new XStream(new XppDriver());
String s = xStream.toXML(p);
System.out.println(s);
//解析XML
Person person = (Person)xStream.fromXML(s);
System.out.println(person);
}