学习Java的第三周

文章目录

前言

本篇文章仅记录自己学习Java的内容。作为小白知识浅薄等原因可能有错误的内容,待后续学习再更正。

正则表达式

1.概述

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
在线生成正则表达式的工具:http://tools.jb51.net/regex/create_reg

2.使用正则表达式的目的

  1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”): 你在填写你个人信息的时候: 例如填写手机号,会验证你手机号码是否写错,你填写的是否符合一个合法手机号的格式
  2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。 例如:爬虫 读取网络中数据,获取到我们想要的部分

3.正则表达式中的符号

在这里插入图片描述

4.创建匹配器Matcher类

Pattern p = Pattern.compile("正则表达式");
Matcher m = p.matcher("需要匹配的字符串"); 
boolean b = m.matches(); 
以上三句代码的简写方式: 
boolean b = Pattern.matches("正则表达式", "需要匹配的字符串");

5.Matcher类方法

1.matches方法尝试将整个输入序列与模式进行匹配。

Pattern p=Pattern.compile("foo"); 
Matcher m=p.matcher("foooooooooooooooooooooo");
boolean flag=m.matches(); 
System.out.println(flag);//false

2.lookingAt方法尝试将起始于输入序列的输入序列与模式进行匹配

Pattern p2=Pattern.compile("foo"); 
Matcher m2=p2.matcher("foooooooooooooooooooooo"); 
boolean flag2=m2.lookingAt(); 
System.out.println(flag2);//true

3.find方法扫描输入序列,寻找匹配模式的下一个子序列
start找到的子序列开始索引
endend找到的子序列的结束索引+1
group找到的子字符串
groupCount获取分组的个数

 //创建模式
        Pattern p = Pattern.compile("([a-zA-Z]+)(\\d+)([\\u4e00-\\u9fa5])");
        //创建匹配器
        Matcher m = p.matcher("a1_hjk666好W676_w64");
         /*
            例如: ((A)(B(C))) 有4个分组,
            分组编号从1开始
            ((A)(B(C)))第1组
            (A)第2组
            (B(C))第3组
            (C) 第4组
             */
        while (m.find()){
            //System.out.println("m.group(0) = " + m.group(0));//hjk666好
            System.out.println("m.group(1) = " + m.group(1));//hjk
            System.out.println("m.group(2) = " + m.group(2));//666
            System.out.println("m.group(3) = " + m.group(3));//好
            System.out.println("组个数:" + m.groupCount());//3
        }

异常处理

1.异常的概述

1.异常的继承体系

Exception类及其子类都是Throwable的一种形式
Exception 代表 的是 java程序中可能会产生的异常,并要求对产生的异常进行合理的异常处理。
整个异常的体系结构:
在这里插入图片描述

2.常见异常

1>运行时异常RuntimeException
1.ArithmeticException 算术异常
System.out.println(10/0);
2.ArrayStoreException 数组存储异常
Object x[] = new Dog[3]; //存Dog对象的数组
x[0] = new Cat(); //尝试往数组中存储Cat对象
3.ClassCastException 类型转换异常
Object obj=new Dog(); Cat c=(Cat)obj;
4.NullPointerException 空指针异常
5.NegativeArraySizeException 负数组大小异常
int[] arr=new int[-100];//尝试负数大小的数组
6.NumberFormatException 数字格式化异常
String s=“abc”; //将字符串转换为其中一个数字类型,但该字符串不具有相应的格式
int num=Integer.parseInt(s);
System.out.println(num);
7.InputMismatchException 输入不匹配异常
Scanner sc = new Scanner(System.in);
// 由 Scanner抛出,表示 Scanner到与预期类型的模式不匹配
//或超出预期类型的范围。 byte num = sc.nextByte(); // -128~127
8.IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException索引越界异常
2>非运行时异常(检查异常)在编译期就显式的通知程序员必须处理
1.ClassNotFoundException类未找到异常
2. IOExceptionIO异常
3. FileNotFoundException 文件找不到异常

3.异常和错误的区别

异常:指程序在编译,运行期间发生了某种异常(xxxxxxxException),我们可以对异常进行具体的处理,若不处理程序就会结束运行。
错误: 指程序在运行期间发生了某种错误(XXXXXError),Error错误通常没有具体的处理方式 程序将会结束运行,Error错误发生往往是系统级别的问题例如JVM所在系统发生的 并且反馈给JVM,我们无法针对处理,只能修改代码

4.异常产生的过程

在这里插入图片描述

5.throw抛出异常对象

throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行 throw 一定是抛出了某种异常。
格式: throw new XXXXXException(“填写异常产生的原因”);
throw 关键字 必须写在方法的内部
throw 关键字 后面 new 对象必须是 Exception 或者 Exception的子类

6.throws声明异常

如果方法内通过throw抛出了编译时异常,而没有捕获处理,那么必须通过throws进行声明,让调用者去处理。
格式: public 返回值类型 方法名(参数列表) throws AaaaaException,BbbbbException{
throw new AaaaaException(“产生原因”);
throw new BbbbbException(“产生原因”);}
throws 关键字 必须写在方法的声明处 throws 关键字 后面必须是 Exception 或者 Exception 子类 方法内部如果抛出了多个异常对象,那么 throws 后面也必须声明多个异常对象 如果抛出多个异常对象存在父子关系,那么直接抛出父异常就可以

7.捕获异常try…catch…finally

try 存放是可能会出现异常的代码,异常有0个或者n个
catch 用来进行某种异常的捕获,实现对捕获的异常对象进行处理 一个try可以匹配多个catch,catch是有顺序要求的
1 若多个catch的异常类之间没有继承关系,则顺序随便
2若多个catch的异常类之间有继承关系,则子类异常必须在父类异常的上面
3. finally: 不论是否有异常都会执行

8.异常在方法重写中细节

1.子类重写父类的方法时,如果父类的方法声明了异常,子类重写的方法 只能声明父类异常或者该异常的子类 或者选择不声明任何异常。
2.父类的方法没有抛出异常,子类重写父类的方法时也不要抛出异常 若子类产生了检查异常,则自己在方法内部try…catch处理,不要抛出,若子类产生了运行时异常,则不用处理,因为JVM会处理

9.Throwable 类中常用方法
  1. String getMessage() 返回异常信息 / by zero
  2. void printStackTrace() 使用红色字体打印错误信息(异常名称,错误信息,位置) java.lang.ArithmeticException: / by zero
    at com.override.Demo.main(Demo.java:7)
  3. String toString() 使用简短的字符串描述错误
    java.lang.ArithmeticException: / by zero

2.自定义异常

//格式:
public class 自定义异常类名 extends Exception{ //Exception 或者 Exception 的子类 
//若继承的是RuntimeException,则子类就是一个运行 时异常 
public 自定义异常类名(){ 
super();//分别调用对应的父类的构造函数 
}
public 自定义异常类名(String s){
 super(s); //调用父类的有参构造函数
 }

集合

1.集合继承关系图

在这里插入图片描述

2.Collection接口中的方法

在这里插入图片描述

3.迭代器

1>迭代器的概述

Collection集合在遍历数据的时候 在取元素之前判断集合中有没有元素 如果有,就把这个元素取出来,继续 再判断,是否有下一个元素, 如果还有,再取出来, 像这种方式专业术语------- 迭代

2>迭代器常用方法

boolean hasNext() 如果迭代具有更多元素,则返回 true 。
E next() 返回迭代中的下一个元素。
default void remove() 从底层集合中删除此迭代器返回的最后一个元素(可选操作)

3>代码示例
ArrayList<String> list = new ArrayList<>(); 
list.add("zhangsan"); 
list.add("jack"); 
list.add("tom"); 
// Iterator<E> iterator() 返回此集合中的元素的迭代器。 
Iterator<String> itors = list.iterator(); 
//判断一个 
while(itors.hasNext()) { 
//取一个 
String s=itors.next();
 System.out.println(s); 
 }

4.foreach

public interface Collection<E> extends Iterable<E> 
//实现此Iterable接口允许对象成为“for-each loop”语句的目标 
//代表 集合 可以使用 foreach语句遍历 
//语法: 
for(数据类型 自定义变量名:集合对象){
 System.out.println(自定义变量名); // 变量名存储的值就是集合中的元素 
 } 
 好处:代码少了,可以遍历数组和集合
  弊端:因为没有索引,不能通过索引操作元素

5.List接口

1>List接口概述

有序的Collection (列表) 存储顺序 实现了此接口的实现类,可以对列表中每一个元素的插入位置进行精确的控制 (用户可以通过索引来访问列表中的元素)
列表允许重复的元素

2>List接口常用实现类区别

在这里插入图片描述

3>List接口中常用方法

在这里插入图片描述
在这里插入图片描述

4>List集合存储数据的结构

栈 一种特殊线性表,特点 先进后出 栈底,栈顶, 入栈 ,出栈
队列 一种特殊线性表,特点 先进先出 一端进队列,另一端出队列
数组 特点:存储相同类型固定元素,方便查找元素,不方便添加新元素和删除元素
链表 特点: 方便 增删, 查询速度慢
单链表 数据域|指针域
双线链表 左链域 数据域 右链域

6.Set接口

1>Set接口概述

无序(不是按照存储顺序存储的) 不可重复(底层会调用equals方法,若返回true则不能存入相同的元素) Set集合存入自定义类型,则必须要重写 equals和hashCode方法

2>HashSet

HashSet集合,采用哈希表数据结构存储数据,保证元素的唯一性依赖的方法 equals() 和 hashCode()

3>LinkedHashSet

HashSet 保证元素的唯一性,可以元素放进去是没有顺序的, 那么我们有一个需求,需要保存这个元素放进去的顺序怎么办? – LinkedHashSet就可以帮我们完成这个需求 它的底层: 链表+ hash表 组合一种数据结构

4>TreeSet

TreeSet 存储的元素, 元素的数据类型必须实现 Comparable 接口 比较器
特点: 底层会调用这个接口中比较的方法 compareTo方法进行比较排序 会对元素进行排序

7.Map接口

1.Map接口概述

Collection (单列集合,单身) 一个元素
Map(双列集合,情侣) 元素成对出现 ,每个元素由键和值两个部分组成
Map存储是键值对键
key不可以重复值
value 可以重复

2.Map接口常用集合

<1> HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。底层采用哈希表+链表+红黑树实现
<2> Hashtable<K,V>:
类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。
为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。
<3> LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
<4> TreeMap<K,V>: 需要对存储的数据进行自定义排序

3.Map接口中常用方法

在这里插入图片描述

4.HashMap、Hashtable区别

相同点:
实现原理相同,功能相同,底层都是哈希表的结构 同样每个元素都是key-value,其内部也是通过链表 解决冲突问题,当容量不足时,也会自动增长。 查看速度快
不同点:
1 JDK1.0版本 Hashtable 早与 JDK1.2 HashMap 出现 // 虽然Hashtable比HashMap出现的早,但是Hashtable已经废弃,大多数情况下 // 都使用HashMap
2 Hashtable 继承 Dictionary类 // Dictionary类,抽象类,此类已过时。 // 新的实现应该实现Map接口,而不是扩展这个类 HashMap 实现了Map接口
3 Hashtable 线程安全 HashMap线程非安全,只是用于单线程环境 如果多线程环境下,也想用HashMap 可以采用concurrent并发包下 ConcurrentHashMap
4 Hashtable 不允许存储null键和null值,会抛出NullPointerException HashMap中允许存储null键和null值
5 Hashtable 比 HashMap 多一种枚举的遍历

8.Collections集合工具类

<1> public static void sort(List list) // 集合元素排序
<2> public static void shuffle(List<?> list) // 集合元素存储位置打乱

泛型

没有泛型的问题

//集合中可以存放任意数据类型的对象。 只要把对象存入到集合中,底层会把对象的数据类型自动转换成Object 
//当我们在取每一个对象的时候,想要调用这个对象里面的方法,发现我们需要将Object转成对应的对象数据类型
//(必须向下转型) 可能会出现 ClassCastException异常  
List list=new ArrayList(); 
list.add("jack"); 
list.add("rose"); 
list.add(1); //Integer类型不能转换成String类型 
//由于集合没有做任何的限定,任何类型都可以存入集合中 
//相当于: Object obj=new String("jack"); 
// Object obj=new Integer("1"); 
//迭代集合 
Iterator itor=list.iterator(); 
while(itor.hasNext()) {
 Object obj=itor.next(); 
 //直接向下转型成为
 String String s1=(String)obj; 
 //String 和 Integer不存在继承关系,所以发生ClassCastException类型转换异常 
 System.out.println(s1.length());//获取字符串个数 
}

泛型的定义和使用

//JDK1.5版本以后引入泛型的概念 
//JDK1.5版本出现新的安全机制,保证程序的安全性 
//泛型: 指明了集合中存储数据的类型 <引用数据类型> 
 List<String> list=new ArrayList<>(); 
 list.add("jack"); l
 ist.add("rose"); 
 //list.add(1); // 提示错误,因为在编译阶段就防止你存入不合理的数据 
 //泛型为什么称为伪泛型 
 //泛型只在编译阶段出现,在运行阶段是没有的 
 Iterator<String> itor=list.iterator(); 
 while(itor.hasNext()) { 
 String s=itor.next(); //使用泛型以后,就不需要数据类型转换 
 System.out.println(s.length()); 
 }

java中的伪泛型

泛型只在编译时存在,编译后就被擦除了,在编译之前我们可以限制集合的元素的类型
在这里插入图片描述

泛型的使用

泛型类

//泛型类型用于类的定义中,被称为 “泛型类”
//定义的格式:public class 类名<泛型标识>{ }
//例如: 集合的ArrayList类就是一个泛型类

//创建这个类的对象的时候我们需要指定泛型的数据类型 
// 泛型的数据类型必须是引用数据类型 
public class ArrayList<E>{ } 
//此处T可以随便写为任意标识 常见: T E K V 
public class Generic<T> {//泛型类 
private T x; // 代表这个x是T类型 
public Generic() {}
 public Generic(T x) {this.x = x;} 
 public static void main(String[] args) { 
 // 创建对象时,确定泛型的类型 
 Generic obj1 = new Generic(); // 不指定T的类型 会有黄色警告 
 Generic<String> obj2 = new Generic<>("abc"); 
 Generic<Boolean> obj3=new Generic<>(true); 
 }
}
泛型方法

泛型: 方法上面添加泛型 泛型方法可以出现在任何地方和任何场景中。
例如: ArrayList类中有泛型方法 T[] toArray(T[] a)
例如: 修饰符 返回值类型 方法名(参数列表){ }

泛型接口

定义格式: public interface 接口名<泛型标识>{ }
例如:集合中List接口,就是一个泛型接口 public interface List extends Collection{ }
在这里插入图片描述

泛型的好处

1 将运行时期的ClassCastException转移到了编译阶段,如果存储不符合指定的类型的数据则不能通过编译
2 避免了类型转换的麻烦
3 提高程序的安全性保证代码质量

泛型的通配符

在泛型中看到 <?> 匹配所有数据类型

泛型的限定
1 ? extends? super 不能在声明处使用,只能创建对象的时候使用 
<? extends T> ? extends T 表示一个特定的类,这个类可能是T,也可能是T的任意子类 
<? super T> ? super T 表示一个特定的类,这个类可能是T,也可能是T的父类或者超类,甚至Object类。

IO流:就是以流的方式进行输入输出操作(读写操作) 流:从发送端 —> 接收端 的有序数据
分类:
<1> 流向 : 输入流(读) 和 输出流(写)
<2> 处理数据类型: 字节流 和 字符流 (每次读写一个byte) (每次读写一个char)
<3> 查看构造函数: 低级流(节点流) 和 高级流(处理流) 若构造函数的参数又是一个流,这个流就是高级流 例如: BufferedReader(Reader in) 参数又是一个Reader
<4> 按照操作的数据源不同

在这里插入图片描述

字节流

FileOutputStream

向一个文件中写入数据,每次写入一个字节的数据

构造方法

//File代表一个文件或者目录,此时这里只能是文件
FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。写入数据,会覆盖原有的文件
FileOutputStream(File file, boolean append) 创建文件输出流以指定的名称写入文件。如果值true,就会在文件末位继续添加。
FileOutputStream(String name)
FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。

方法

在这里插入图片描述

FileInputStream

把文件中的数据读到程序中

构造方法

FileInputStream(File file)
FileInputStream(String name)

方法

在这里插入图片描述

字节流拷贝文件
try {
//源文件 
File src=new File("src/LoveStory.mp3"); 
//目标文件 
File dest=new File("d:/LoveStory.mp3"); 
//步骤1:使用FileInputStream指向源文件 
FileInputStream fis=new FileInputStream(src); 
//步骤2:使用FileOutputStream指向目标文件 
FileOutputStream fos=new FileOutputStream(dest); 
//步骤3:一边读一边写 
int len=-1; //判断是否读完了 
byte[] arr=new byte[1024]; 
//存储读取的数据 
while((len=fis.read(arr)) !=-1) { 
fos.write(arr,0,len); 
}
//先关闭fos (先定义的后关闭原则) 
fos.close(); 
//再关闭fis 
fis.close(); 
} catch (Exception e) {
 e.printStackTrace(); 
 }

字符流

字节流每次读写都是一个字节 byte
字符流每次读写都是一个字符 char

字符编码

ASCII GBK utf-8 ISO-8859-1 unicode base64
能支持中文: utf-8 GBK
对于我们开发而言:常见的编码 GBK UTF-8 ISO-8859-1(单字节编码)
有些方法涉及到编码格式:
String(byte[] bytes, String charsetName) //涉及编码格式 byte[] getBytes(String charsetName) //涉及编码格式

字符输入流FileReader
构造函数

FileReader(File file)
FileReader(String fileName)

方法

int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。

字符输出流FileWriter
构造函数

(File file) FileWriter(File file, boolean append)
FileWriter(String fileName)
FileWriter(String fileName, boolean append)

方法

void write(int c) 写一个字符
void write(String str) 写一个字符串
void write(String str, int off, int len)

flush() 和 close()区别

flush 刷新,将流中的缓冲区的数据刷新到目的地中 刷新后流可以继续使用
close 关闭流,流就不可以使用了
在一般操作大量的数据的时候,我们一般都是 一边读一边写一边刷新,全部的操作执行完后 最后关闭流。

转换流

InputStreamReader(使用率高)

字节流 变成 字符流

//字节流 
FileInputStream fis=new FileInputStream("src/demo.txt"); 
//桥梁:转换流 
InputStreamReader isr=new InputStreamReader(fis); 
// 字符流 
BufferedReader br=new BufferedReader(isr);
 // BufferedReader中有一个方法 String readLine() 高效的读取1行数据
OutputStreamWriter (使用率低)

字节流 变成 字符流

 //字节流
FileOutputStream fos=new FileOutputStream("src/demo.txt");
//桥梁
OutputStreamWriter osw=new OutputStreamWriter(fos,"编码格式");
//高级流
BufferedWriter bw=new BufferedWriter(osw);

高级流

BufferedReader

1> String readLine() 每次高效读取1行数据 // 如果已达到流的末尾,则为null
2> Stream lines() 支持昨天学习Stream

PrintWriter打印流

PrintWriter 替代 BufferedWriter
void print(String str):输出任意类型的数据
void println(String x) 输出任意类型的数据,自动写入换行操作
默写 使用BufferedReader 和 PrintWriter 实现文件拷贝(适合拷贝文本)

对象序列化

用于向流中写入对象的操作流 ObjectOutputStream 称为 序列化流 writeObject(Object obj)

构造方法

ObjectOutputStream(OutputStream out)

方法

void writeObject(Object obj) 写对象

//1. 定义坐标类 
public class ZuoBiao implements Serializable{
 private int x; private int y; 
 } 
 //2. 定义将坐标对象存储在 zb.txt文件 
 File file=new File("src/zb.txt"); 
 FileOutputStream fos=new FileOutputStream(file); 
 ObjectOutputStream oos=new ObjectOutputStream(fos); 
 ZuoBiao zb1=new ZuoBiao(3, 4); 
 oos.writeObject(zb1); 
 oos.close();

对象反序列化

反序列化流,ObjectInputStream Object readObject() 将文件中的对象直接读出来

构造方法

ObjectInputStream(InputStream in)

方法

Object readObject()

//创建一个文件 
File file=new File("src/zb.txt"); 
//文件字节输入流,读数据 
FileInputStream fis=new FileInputStream(file); 
//读对象的输入流 
ObjectInputStream ois=new ObjectInputStream(fis); 
Object obj=ois.readObject();
 //将Object转换成Zuobiao 
 if(obj instanceof ZuoBiao) 
 { ZuoBiao zb=(ZuoBiao)obj; 
 System.out.println(zb);
  }
  ois.close(); 
  fis.close();

序列化异常

1 NotSerializableException 当一个对象想要被序列化,但是这个对象所对应的的类 没有实现Serializable接口,就会抛出此异常
2 同时当反序列化对象时,如果对象所属的class文件 在序列化之后,修改了,那么进行反序列化也会发生 异常 InvalidClassException

序列化和反序列化总结

1什么是序列化? 将Java对象转换成字节序列保存在磁盘或者网络的过程。
2 对象序列化的目的? 以某种存储形式将对象永久保存在硬盘中 网络传输(将一个对象从一个地方发送到另一个地方)
3序列化对“对象”有什么要求? 被序列化的类,必须实现 Serializable接口或者它的子接口
4 对象序列化使用流? java.io.ObjectOutputStream
5 哪些东西被序列化了? 类名,包名, 属性 都被序列化 被 static 修饰,transient 修饰的属性不能被序列化
6 如果一个类引入其他类,那么其他类也必须实现序列化接口 才能被序列化
class Person{
private String name;
private Dog dog; // Dog类也必须要实现序列化接口
}// 这个Person对象才能存储文件中 // 若Dog不想被序列化,使用 transient修饰就可以
7 序列化时,会有一个序列化ID,如果修改了代码 没有重新序列化,则你反序列化的时候会抛出异常 因为序列化的版本不一样

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值