study-notes(1 JavaSE)-2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wpwbb510582246/article/details/83588214

这篇文章是将自己所学技术按模块划分总结而成的笔记,包含了 JavaSE、JavaWeb(SpringMVC、Spring、MyBatis、SpringBoot、SpringCloud 等)、Linux、Hadoop、MapReduce、Hive、Scala、Spark 等,希望通过这些笔记的总结,不仅能让自己对这些技术的掌握更加深刻,同时也希望能帮助一些其他热爱技术的人,这些笔记后续会继续更新,以后自己学习的其他最新技术,也都会以这样笔记的形式来保留,这些笔记已经共享到 Github,大家可以在那里下载到 Markdown 文件,如果大家在看的时候有什么问题或疑问,可以通过邮箱与我取得联系,或者在下面的评论区留言,同时也可以在 Github 上与我进行互动,希望能与大家一起相互学习,相互进步,共同成长。

本篇文章 Github 地址 : https://github.com/wpwbb510582246/study-notes/blob/master/1 JavaSE/1 JavaSE.md

项目 Github 地址 : https://github.com/wpwbb510582246/study-notes

email : [email protected]

博客地址 : https://blog.csdn.net/wpwbb510582246

1.5.15 HashMap 中重写 hashCode 和 equals 方法的步骤

    @Override
    public int hashCode() {
return Objects.hash(name, age);
    }

    @Override
    public boolean equals(Object obj) {
if(this == obj) return true;
if(obj == null || this.getClass() != obj.getClass()) return false;
Student student = (Student) obj;
return this.age == student.getAge() && Objects.equals(this.name, student.getName());
    }

1.6 泛型

1.6.1 什么是泛型

泛型是指可以在类或方法中预支地使用未知的类型。一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

1.6.2 使用泛型的好处有哪些

将运行时期的ClassCastException,转移到了编译时期变成了编译失败。

避免了类型强转的麻烦。

1.7 多态

1.7.1 多态的前提

继承或者实现

方法的重写

父类引用指向子类对象(格式体现)

父类类型 变量名 = new 子类对象;
变量名.方法名();
Fu f = new Zi();
f.method();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。

1.7.2 多态的好处

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。

1.7.3 向上转型与向下转型

**向上转型:**父类引用指向子类对象

使用格式:

父类类型  变量名 = new 子类类型();
如:Animal a = new Cat();

**向下转型:**父类引用指向子类引用

使用格式:

子类类型 变量名 = (子类类型) 父类变量名;:Cat c =(Cat) a;  

1.8 异常

1.8.1 异常的分类

**编译时期异常:**checked 异常,在编译时期,就会检查,如果没有处理异常,则编译失败(如日期格式化异常).

**运行时期异常:**runtime 异常,在运行时期,检查异常,运行异常不会被编译器检测(不报错)(如数学异常).

1.8.2 异常的处理方式

**抛出异常 throw :**throw 用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行.

使用格式:

throw new 异常类名(参数);

**捕获异常 try … catch … finally :**Java 中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理.

使用格式:

try {
    编写可能会出现异常的代码
} catch (异常类型 e) {
    处理异常的代码
    //  记录日志
    //  打印异常信息
    //  继续抛出异常
} finally {
    关闭资源(硬件文件资源,数据库资源,网络资源 ...}

**try : ** 该代码块中编写可能产生异常的代码.

catch : 用来进行某种异常的捕获,实现对捕获到的异常进行处理.

finally : finally 中的代码块一定会被执行,就是为了 ‘关闭资源’ 而设计,主要用于关闭硬件文件资源,数据库资源,网络资源 … ,finally 块的设计,就是为了解决 catch 块中 return 语句的问题,在 return 之前会先执行 finally 代码块.

try … catch … finally 参考代码如下:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ExceptionTest1 {
    public static void main(String[] args) {

String result = readFile("a.txt");
System.out.println("result = " + result);

    }

    // 需求 : IO (BufferedReader & BufferedWriter)
    // 说明 : 定义一个方法, 读取指定文件中的数据, 并返回是否读取成功字符串.
    public static String readFile(String fileName) {

// 1. 读取文件
// 说明 : 创建 FileReader 时, 会发生一个 `FileNotFoundException` 文件找不到异常.
// 选择捕获异常 : try - catch
FileReader reader = null;
try {
    reader = new FileReader(fileName);
} catch (FileNotFoundException e) {
    System.out.println("发生了文件找不到异常, 请检查文件路径或文件名称.");
    // 如果程序进入 catch 语句, 说明程序发生了异常. 文件读取失败了.
    return "文件读取失败";// return 之前会先执行 finally 代码块.
} finally {
    // finally 代码块就是为 `关闭资源` 而设计. (硬件文件资源, 数据库资源, 网络资源 ...)
    // 说明 : finally 块的设计就是为了解决 catch 块中 return 语句的问题.
    System.out.println("finally 代码块被执行 ...");
    // 说明 : 如果一个对象的默认值为null, 调用时, 必须要做 null 判断.
    if (reader != null) {
try {
    reader.close();
} catch (IOException exception) {
    // 忽略 ...
}
    }

    // finally 块中, 在开发时, 绝对不会出现 return 语句, 因为 finally 块就是用来关闭资源的, 而不是返回结果的.
    // 如果要返回结果, 请在 catch 语句中返回.
    // return "哈哈哈哈";
}

return "文件读取成功";
    }
}

输出结果 :
发生了文件找不到异常, 请检查文件路径或文件名称.
finally 代码块被执行 ...
result = 文件读取失败

1.8.3 try … catch … finally 执行顺序的思考

当有多个 catch 时,前面一个 catch 捕获异常后,后面的 catch 不会再执行.

参考代码如下:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ExceptionTest1 {
    public static void main(String[] args) {

String result = readFile("a.txt");
System.out.println("result = " + result);

    }

    // 需求 : IO (BufferedReader & BufferedWriter)
    // 说明 : 定义一个方法, 读取指定文件中的数据, 并返回是否读取成功字符串.
    public static String readFile(String fileName) {

// 1. 读取文件
// 说明 : 创建 FileReader 时, 会发生一个 `FileNotFoundException` 文件找不到异常.
// 选择捕获异常 : try - catch
FileReader reader = null;
try {
    reader = new FileReader(fileName);
} catch (FileNotFoundException e) {
    System.out.println("发生了文件找不到异常, 请检查文件路径或文件名称.");
    // 如果程序进入 catch 语句, 说明程序发生了异常. 文件读取失败了.
    return "文件读取失败";// return 之前会先执行 finally 代码块.
} finally {
    // finally 代码块就是为 `关闭资源` 而设计. (硬件文件资源, 数据库资源, 网络资源 ...)
    // 说明 : finally 块的设计就是为了解决 catch 块中 return 语句的问题.
    System.out.println("finally 代码块被执行 ...");
    // 说明 : 如果一个对象的默认值为null, 调用时, 必须要做 null 判断.
    if (reader != null) {
try {
    reader.close();
} catch (IOException exception) {
    // 忽略 ...
}
    }

    // finally 块中, 在开发时, 绝对不会出现 return 语句, 因为 finally 块就是用来关闭资源的, 而不是返回结果的.
    // 如果要返回结果, 请在 catch 语句中返回.
    // return "哈哈哈哈";
}

return "文件读取成功";
    }
}

输出结果 :
发生了文件找不到异常, 请检查文件路径或文件名称.
finally 代码块被执行 ...
result = 文件读取失败

1.8.4 异常处理过程

如果有异常发生,并没有进行处理,此时该异常继续向上抛,该方法由谁调用,该异常就抛给谁. 由于 Java 虚拟机调用了 main 方法,所以该异常就抛给了 ‘Java虚拟机’,当虚拟机接收到异常时,就输出异常的相关信息,然后提前终止程序,退出Java虚拟机. 当对异常进行处理时,就根据处理方案对异常进行处理.

1.9 多线程

1.9.1 并行与并发

**并行:**指两个或多个事件在同一时刻发生(同时发生).

**并发:**指两个或多个事件在同一个时间段内发生.

1.9.2 多线程执行过程

  1. 多线程执行时,在栈内存中,每一个执行线程都有一片自己所属的栈内存空间,进行方法的压栈和弹栈.
  2. 每条线程都有自己独立的栈区执行空间,堆区只有一个.
  3. 多线程中,每条线程的栈空间独立,堆空间 ‘共享’.
  4. 堆空间中存储的是 ‘对象’,而对象中存储的是该对象的 ‘数据’.
  5. 对象的属性存放在堆区中,局部变量存放在栈区中,多线程操作对象的属性会存在安全问题,多线程操作局部变量不会存在安全问题.

1.9.3 实现 Runnable 接口比继承 Thread 类所具有的优势

  1. 适合多个相同的程序代码的线程去共享同一个资源.
  2. 可以避免 Java 中的单继承的局限性.
  3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立.
  4. 线程池只能放入实现 Runnable 或 Callable 类线程,不能直接放入继承 Thread 的类.

1.10 字节流与字符流

1.10.1 字节流与字符流的区别

**字节流:**所有类型的数据在硬盘中都是以字节的形式实现存储的,字节流可以完成所有类型的 ‘读写’ 操作.

**字符流:**字符流仅能操作字符数据,不能操作其他类型数据,字符流 = 字节流 + 文字编码表. 字符流写入数据三部曲 写入、换行、刷新

程序以内存作为参照物,区分读和写.

  1. 数据从硬盘中,流入到内存,被称为读.
  2. 数据从内存中,流入到硬盘,被称为写.

字节流使用方法

/**
     * 复制文件(BufferedInputStream & BufferedOutputStream)
     * @throws IOException
     */

    public static void copyPicture2() throws IOException {

//  创建 File 对象
File origin = new File("file/柳岩.jpg");
File destination = new File("file/柳岩3.jpg");
//  创建文件输入、输出流对象
FileInputStream in = new FileInputStream(origin);
FileOutputStream out = new FileOutputStream(destination);
//  创建高效字节缓冲输入、输出流对象
BufferedInputStream bis = new BufferedInputStream(in);
BufferedOutputStream bos = new BufferedOutputStream(out);
try (in; out) {

    //  循环读取原文件数据并将其复制到目标文件
    int len = -1;
    while ((len = bis.read()) != -1) {
bos.write(len);
    }

} catch (IOException e) {
    e.printStackTrace();
}

System.out.println("文件复制完成");

    }

字符流使用方法

/**
     * FileReader 的构造方法
     * @throws FileNotFoundException
     */

    public static void testFileReader() throws IOException {

//  读取字符数据

//  创建一个字符输入流
File file2 = new File("file/a.txt");
FileReader reader3 = new FileReader(file2);

//  循环读取数据
char[] c = new char[2];
int read = -1;
while ((read = reader3.read(c)) != -1) {
    String str = new String(c, 0, read);
    System.out.println(str);
}

//  关闭资源
reader3.close();

    }
/**
     * FileWriter 的构造方法
     * @throws IOException
     */

    public static void testFileWriter() throws IOException {

//  字符缓冲流写入数据,写入数据三部曲:写入、换行、刷新

//  创建一个字符缓冲输出流对象
File file2 = new File("file/e.txt");
FileWriter fileWriter = new FileWriter(file2, true);
BufferedWriter writer2 = new BufferedWriter(fileWriter);

//  写入数据
writer2.write("我爱上海明珠塔.");
writer2.newLine();
writer2.flush();

//  关闭资源
writer2.close();

    }

1.11 函数式编程

1.11.1 方法中不定数组传参的方法

方法定义:

public static int getNum(int... nums) {
    System.out.println(Arrays.toString(nums));
}

方法调用:

private static void main(String[] args) {
    getNum(10, 20);
}

1.11.2 Lambda 表达式

**省略原则:**能推导, 就可以省略.

  1. () 参数列表小括号中, 参数类型可以以省略, 如果参数仅有一个, 小括号也可以省略.
  2. {} 如果方法体中有多条语句, 大括号必须书写. 如果方法体中仅有一条语句, 大括号就可以省略. 不管该方法有没有返回值, return 关键字和最后的分号都可以省略.

使用前提条件:

  1. 必须拥有 函数式接口. (Java语言已经提供了很多函数式接口)
  2. 调用的方法必须拥有函数式接口作为方法的参数. (Java语言已经提供了很多方法, 这些方法的参数都是函数式接口)

1.11.3 常用函数式接口

  1. Supplier : 无中生有,抽象方法为 T get() .
  2. Consumer : 有去无回,抽象方法为 void accept(T t),默认方法为 andThen .
  3. Predicate : 元芳,你怎么看,抽象方法为 boolean test(T t),默认方法为 and、or、negate(or) .
  4. Function<T, R> : 有去有会,抽象方法为 R apply(T t),默认方法为 andThen .

1.12 方法引用

1.12.1 方法引用的类型

  1. 通过对象名引用成员方法.
  2. 通过类名称引用静态方法.
  3. 通过 super 引用成员方法.
  4. 通过 this 引用成员方法.
  5. 类的构造器引用.
  6. 数组的构造器引用.

代码示例:

//  通过对象名引用成员方法.

public class Assistant {
    public void dealFile(String file) {
System.out.println("帮忙处理 <" + file + "> 文件.");
    }
}

@FunctionalInterface
public interface WorkHelper {
    void help(String file);
}

public class Test2 {
    public static void main(String[] args) {

// 调用方法 : Lambda 表达式
work(s -> System.out.println("帮忙处理 <" + s + "> 文件."));

// 调用方法 : 对象引用对象方法
Assistant assistant = new Assistant();
work(assistant::dealFile);
    }

    public static void work(WorkHelper helper) {
helper.help("机密");
    }
}

输出结果 :
帮忙处理 <机密文件> 文件.
帮忙处理 <机密文件> 文件.
//  通过类名称引用静态方法.

public class StringUtils {

    // 方法 : 判断是否为空
    public static boolean isBlank(String str) {
// 条件1 : str 参数不能为 null
// 条件2 : str 参数取出前后空格不能拿为空字符串
return str == null || "".equals(str.trim());
    }
}

@FunctionalInterface
public interface StringChecker {
    // 抽象方法
    boolean checkString(String str);
}

public class Test4 {
    public static void main(String[] args) {

// 调用方法 : Lambda 表达式
stringCheck("   ", s -> s == null || "".equals(s.trim()));

// 调用方法 : 静态方法引用
stringCheck("   ", StringUtils::isBlank);
    }

    public static void stringCheck(String str, StringChecker stringChecker) {
boolean result = stringChecker.checkString(str);
System.out.println("传入的字符串是否为空 : " + result);
    }
}

输出结果 :
传入的字符串是否为空 : true
传入的字符串是否为空 : true
//  通过 super 引用成员方法.

@FunctionalInterface
public interface Greetable {
    void greet();
}

public class Human {
    public void sayHello() {
        System.out.println("Hello!");
    }
}

public class Man extends Human {

    public void sayHi() {

// 调用方法 : Lambda 表达式
method(() -> System.out.println("Hello!"));

// 调用方法 : 执行父类中的 sayHello 方法.
method(() -> super.sayHello());

// 调用方法 : super引用, 使用父类中的 sayHello 方法.
method(super::sayHello);
    }

    public void method(Greeting greeting) {
greeting.greet();

System.out.println("I am a Man.");
    }
}
//  通过 this 引用成员方法.

@FunctionalInterface
public interface Richable {
    void buy();
}

public class Husband {

    // 行为 : 变得快乐
    public void beHappy() {
// 结婚吧
merry(() -> System.out.println("买套房子."));

merry(() -> this.buyCar());

merry(this::changeWife);
    }

    // 行为 : 结婚 (需要变得有钱, 必须要买东西)
    private void merry(Richable richable) {
richable.buy();
    }

    // 行为 : 买套方法
    private void buyHouse() {
System.out.println("买套房子.");
    }

    // 行为 : 买辆车子
    private void buyCar() {
System.out.println("买辆车子.");
    }

    // 行为 : 换个老婆
    private void changeWife() {
System.out.println("换个老婆. 开个玩笑.");
    }
}

public class Test {
    public static void main(String[] args) {

Husband husband = new Husband();
husband.beHappy();

    }
}

输出结果 :
买套房子.
买辆车子.
换个老婆. 开个玩笑.
//  类的构造器引用.

public class Person {
    
    private String name;

    public Person(String name) {
this.name = name;
    }

    public Person() {
    }

    public String getName() {
return name;
    }

    public void setName(String name) {
this.name = name;
    }
}

@FunctionalInterface
public interface PersonBuilder {

    // 抽象方法
    Person builderPerson(String name);
}

public class Test1 {
    public static void main(String[] args) {

printPerson("张三丰", name -> new Person(name));

printPerson("张三丰", Person::new);
    }

    // 定义方法 :
    public static void printPerson(String name, PersonBuilder personBuilder) {
Person person = personBuilder.builderPerson(name);
System.out.println("person = " + person);
System.out.println("person.getName() = " + person.getName());
    }
}

输出结果 :
person = cn.itcast.test5.Person@7f63425a
person.getName() = 张三丰
person = cn.itcast.test5.Person@340f438e
person.getName() = 张三丰
//  数组的构造器引用.

@FunctionalInterface
public interface ArrayBuilder {
    // 抽象方法
    int[] buildArray(int length);
}

public class Test2 {
    public static void main(String[] args) {

int[] arr1 = initIntArray(10, len -> new int[len]);
System.out.println("arr1.length = " + arr1.length);

int[] arr2 = initIntArray(10, int[]::new);
System.out.println("arr2.length = " + arr2.length);
    }

    // 初始化一个 int[] 数组
    public static int[] initIntArray(int length, ArrayBuilder builder) {
       return builder.buildArray(length);
    }
}

输出结果 :
arr1.length = 10
arr2.length = 10

1.13 Stream 流

1.13.1 Stream 常用方法

  1. count : 统计个数
Stream<String> stream = Stream.of("张无忌", "张学友", "刘德华", "张三丰");

// long count();
long count = stream.filter(name -> name.startsWith("张")).count();
System.out.println("count = " + count);
  1. forEach : 逐一处理
Stream<String> stream = Stream.of("张无忌", "张学友", "刘德华", "张三丰");

// Consumer 接口 : void accept(T t)
stream.forEach(System.out::println);
  1. filter : 过滤
Stream<String> stream = Stream.of("张无忌", "张学友", "刘德华", "张三丰");

// Predicate 接口 : boolean test(T t);
stream.filter(name -> name.startsWith("张")).forEach(System.out::println);
  1. limit : 取用前几个
Stream<String> stream = Stream.of("张无忌", "张学友", "刘德华", "张三丰");

// Stream<T> limit(long maxSize);
stream.filter(name -> name.startsWith("张"))
.limit(2).forEach(System.out::println);
  1. skip : 跳过前几个
Stream<String> stream = Stream.of("张无忌", "张学友", "刘德华", "张三丰");

// Stream<T> skip(long n);
stream.filter(name -> name.startsWith("张"))
.skip(1).forEach(System.out::println);
  1. map : 映射
Stream<String> stream = Stream.of("10", "20", "30", "40", "50");

// Function 接口 : R apply(T t);
stream.map(Integer::parseInt).forEach(System.out::println);
  1. concat : 组合
Stream<String> stream1 = Stream.of("刘德华", "张学友", "黎明", "郭富城");
Stream<String> stream2 = Stream.of("西施", "杨玉环", "貂蝉", "王昭君");

Stream<String> stream = Stream.concat(stream1, stream2);

1.14 反射

1.14.1 反射常用方法

  1. 获取 class 对象的 constructor 信息 :
//  根据参数类型获取构造方法对象,包括private修饰的构造方法。
Constructor getDeclaredConstructor(Class... parameterTypes) 

//  根据指定参数创建对象。
T newInstance(Object... initargs) 
   
//  暴力反射,设置为可以直接访问私有类型的构造方法。
void setAccessible(true)
//  示例

// 1. 获取 Student 类表示的 Class 对象
Class<?> cls = Class.forName("cn.itcast.test2.Student");
// 2. 调用 getDeclaredConstructor 方法
Constructor<?> constructor = cls.getDeclaredConstructor(String.class, int.class);
// 3. 暴力反射 (设置可访问权限)
constructor.setAccessible(true);
// 4. 调用 Constructor 对象的 newInstance 方法, 创建对象
Object obj = constructor.newInstance("柳岩", 18);
  1. 获取 class 对象的 method 信息
//  根据方法名和参数类型获得一个方法对象,包括private修饰的
Method getDeclaredMethod("方法名", 方法的参数类型... 类型)

//  根据参数args调用对象obj的该成员方法,如果obj=null,则表示该方法是静态方法
Object invoke(Object obj, Object... args) 

//  暴力反射,设置为可以直接调用私有修饰的成员方法
void setAccessible(boolean flag) 
//  示例

// 1. 获取 Student 类表示的 Class 对象
Class<?> cls = Class.forName("cn.itcast.test2.Student");
// 2. 调用 declaredMethod 方法
Method sleep = cls.getDeclaredMethod("fallInLove");
// 3. 暴力反射 (设置可访问权限)
sleep.setAccessible(true);
// 4. 调用 invoke 执行
Object obj = cls.getDeclaredConstructor().newInstance();
sleep.invoke(obj);
  1. 获取 class 对象的 field 信息
//  根据属性名获得属性对象,包括private修饰的
Field getDeclaredField(String name) 

//  设置属性值
void set(Object obj, Object value) 

//  获取属性值
Object get(Object obj)  

//  暴力反射,设置为可以直接访问私有类型的属性。
void setAccessible(true);

//   获取属性的类型,返回Class对象。
Class getType();
//  示例

// 1. 获取 Student 类表示的 Class 对象
 Class<?> cls = Class.forName("cn.itcast.test2.Student");
 // 2. 调用 getField 方法
 Field description = cls.getField("description");
 // 3. 设置属性
 Object obj = cls.getDeclaredConstructor().newInstance();
 description.set(obj, "这就是那个神奇的学生.");
 // 4. 获取属性
 Object desc = description.get(obj); 

1.15 动态代理

1.15.1 动态代理流程

  1. ClassLoader : 类加载器
  2. Class[] interfaces : 接口数组
  3. InvacationHandler : 调用处理器对象

**原理:**如果使用代理对象调用任何方法,最终都会执行 调用处理器对象的 invoke 方法.

创建过程:

//  创建一个被代理对象
SuperStar star = new SuperStar();

//  创建一个代理对象
ClassLoader loader = star.getClass().getClassLoader();
Class<?> [] interfaces = star.getClass().getInterfaces();
MyInvocationHandler handler = new MyInvocationHandler(star);
SuperStar proxy = (SuperStar)Proxy.newProxyInstance(loader, interfaces, handler);

//  使用代理调用接口中的行为规范
proxy.sing(10);
proxy.liveShow(100);
proxy.sleep();

//  自定义 '调用处理器对象类'
public class MyInvocationHandler implements InvocationHandler {

    private SuperStar star;

    public MyInvocationHandler(SuperStar star) {
this.star = star;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

String methodName = method.getName();

//  如果方法是 'sing',当 money 小于 10000 时,给出提示,不进行操作,否则,执行 'sing' 方法
if (methodName.equals("sing")) {

    int money = (int) args[0];  //  收入
    if (money < 10000) {
System.out.println("滚,你这个屌丝,赶快回家撸代码去 ...");
return null;
    } else {
//  代理抽取回扣
int rebate = (int) (money * 0.3);
money = money - rebate;
System.out.println("代理抽取回扣 : " + rebate);
return method.invoke(star, money);
    }

} else if (methodName.equals("liveShow")) {

    int money = (int) args[0];  //  收入
    if (money < 100000) {
System.out.println("滚,how old are you,回家继续撸代码去 ...");
return null;
    } else {
//  代理抽取回扣
int rebate = (int) (money * 0.3);
money = money - rebate;
System.out.println("代理抽取回扣 : " + rebate);
return method.invoke(star, money);
    }

}
return method.invoke(star, args);

    }
}

1.16 正则表达式

1.16.1 常用正则表达式

符号 :

  1. [] 取值的范围. 0-9 数值0到9都成立.
    说明 : [0-9] 可以使用 \\d 表示

    . {} 表示前一个条件中 可以出现的次数.

    说明 : {4,11} 至少4次, 最多11次.
    ​ {0,1} 至少0次,最多一次. 可以使用 表示.
    ​ {1,} 至少1次,最多无限次 可以使用 + 表示.
    ​ {0,} 至少0次,最多无限次. 可以使用 * 表示.

    . () 表示分组. 在replaceAll方法的第二个参数上可以使用 $ 符号来引用之前的分组,分组编号自动从1开始.

示例:

//  手机号码规则 :
//  1. 长度必须是11位
//  2. 第一位只能是数字1
//  3. 第二位可以是3, 4, 5, 7, 8

String phone = "13366285946";
boolean result = phone.matches("1[34578]\\d{9}");
//  切割字符串

String str = "boxing#####basketball####football##ILOVEYOU##爱我中华";
String[] names = str.split("#+");

String str = "boxing123basketball4567football888ILOVEYOU9876爱我中华";
String[] names = str.split("\\d+");

String str = "boxingaaaaabasketballYYYYYfootball888ILOVEYOU9999爱我中华";
String[] names = str.split("(.)\\1{2,}");
//  隐藏部分手机号码
//  13366285946  ->  133****5946

String phone = "13366285946";

/*
    源数据 : 13366285946
    第一部分 : 133      规则一 : 1[34578]\\d
    第二部分 : 6628     规则二 : \\d{4}
    第三部分 : 5946     规则三 : \\d{4}
 */

String result = phone.replaceAll("(1[34578]\\d)(\\d{4})(\\d{4})", "$1****$3");
System.out.println("result = " + result);

猜你喜欢

转载自blog.csdn.net/wpwbb510582246/article/details/83588214
今日推荐