一 枚举
1.1 定义
Java枚举是一种特殊的数据类型,用于表示有限个预设的值。它在Java语言中是一种类(class)类型,但又比普通的类类型多了些特殊的约束,这些约束使得枚举类型更加简洁、安全和便捷。枚举类型的名称必须以大写字母开头,可以包含字母、数字和下划线。
1.2 特点
- Java中枚举和类、接口的级别相同。
- 枚举和类一样,都有自己的属性、方法、构造方法,但枚举的构造方法只能是private修饰,也就无法从外部构造对象。
- 使用enum关键字声明一个枚举类型时,就默认继承自Java中的java.lang.Enum类,并实现了java.lang.Seriablizable和java.lang.Comparable两个接口。
- 所有的枚举值都是public static final的,且非抽象的枚举类不能再派生子类。
- 枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例
1.3 作用
- 作为类型安全的常量。例如:
public enum Color {
RED, GREEN, BLUE, YELLOW }
public static void main(String[] args) {
System.out.println(Color.RED); // 输出 RED
}
- 避免使用魔法值,用于 switch 语句中:
以前:
public static final String MONDAY = "0";
现在
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
public static void main(String[] args) {
Day today = Day.MONDAY;
switch (today) {
case MONDAY:
System.out.println("今天是星期一");
break;
case TUESDAY:
System.out.println("今天是星期二");
break;
// ...
default:
System.out.println("今天是星期日");
break;
}
}
- 用于消除重复代码,提高程序的可维护性、可读性、安全性、可扩展性:
public enum Direction {
UP, DOWN, LEFT, RIGHT }
public class Move {
public Direction direction;
public int distance;
// ...
}
public class Robot {
public void move() {
Move move = new Move();
move.direction = Direction.UP;
move.distance = 10;
// ...
}
}
1.4 枚举构造方法
枚举也可以有构造方法,其本质也是一个类,java.lang.Enum
public enum CoinP {
UNKONWN("-1"),
ONE("0");
private final String pos;
CoinP(String pos) {
this.pos = pos;
}
public String getPos() {
return pos;
}
}
1.5 常用方法
二 正则表达式
一看就懂,一用就废。
2.1 定义
Java正则表达式是一种用来匹配和解析字符串的工具,它提供了一种强大的方式来查找、处理和操作文本数据。在Java中,正则表达式通常使用java.util.regex包下的类进行支持。
Java正则表达式的基本结构由一个模式(Pattern对象)和一组规则(Matcher对象)组成,其中模式描述了要匹配的文本模式,规则定义了匹配的模式如何被解析和应用。
2.2 用法
/**
* 判断是否为数字
* true 是数字
*/
public static boolean isNumer(String str) {
if (TextUtil.isEmpty(str)) {
return false;
}
Pattern pattern = Pattern.compile("^[0-9]*$");
Matcher m = pattern.matcher(str);
return m.matches();
}
public static boolean isPhone(String num) {
String phone = "18810022666";
String regex = "1[34578][0-9]{9}";
boolean flag = phone.matches(regex);
}
这里 String 可以直接调用matches,因为在内部进行了封装
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
Pattern.java
public static boolean matches(String regex, CharSequence input) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
return m.matches();
}
2.3 方法
Matcher.find()
翻译一下:
尝试查找与模式匹配的输入序列的下一个子序列。
此方法从该匹配器区域的开头开始,或者,如果上次调用该方法成功,并且此后未重置匹配器,则从上次匹配未匹配的第一个字符开始。
如果匹配成功,则可以通过开始、结束和分组方法获得更多信息。
如果且仅当输入序列的子序列与该匹配器的模式匹配,则为true
find()方法在部分匹配时和完全匹配时返回true,匹配不上返回false;
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String input = "Hello, world!";
Pattern pattern = Pattern.compile("\\w+");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
在上面的代码中,我们首先定义了一个输入字符串input,然后使用Pattern类的compile()方法创建了一个正则表达式模式pattern。接下来,我们使用Matcher类的matcher()方法将输入字符串与正则表达式模式进行匹配,并将匹配器对象matcher赋给变量。最后,我们使用while循环调用find()方法,找到所有与正则表达式模式匹配的子串,并使用group()方法输出每个匹配的子串。
运行上面的代码,输出结果如下:
Hello
world
matcher.groups(int group)
获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
例如:
表达式 ((A)(B(C)))
里面有三个组:
((A)(B(C)))
(A)
(B(C))
(C)
形式为 matcher.group( )
即直接用小括号来分组,捕获组是指在正则表达式中使用圆括号括起来的部分,用于匹配和提取子字符串, groupCount 方法来查看表达式有多少个分组。
举个简单的例子
import java.util.regex.*;
public class RegexExample {
public static void main(String[] args) {
String input = "Hello, world!";
Pattern pattern = Pattern.compile("(\\w+) (\\w+)");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
String[] groups = matcher.groups().split(" ");
for (String group : groups) {
System.out.println(group);
}
}
}
}
在上面的代码中,我们首先定义了一个输入字符串input,然后使用Pattern类的compile()方法创建了一个正则表达式模式pattern。该模式包含两个捕获组,分别匹配一个单词和一个空格。接下来,我们使用Matcher类的matcher()方法将输入字符串与正则表达式模式进行匹配,并将匹配器对象matcher赋给变量。然后,我们使用find()方法查找第一个匹配项,并使用groups()方法获取所有捕获组的匹配结果。最后,我们使用split()方法将结果按空格分割成一个字符串数组,并使用for循环输出每个捕获组的匹配结果。
matcher.matches()
即常用的全部匹配
2.4 正则表达式支持字符
字符 | 解释 | 示例 |
---|---|---|
. | 匹配除换行符\n之外的任何单字符。 | jav. 可匹配java、javb、javc |
[] | 用于确定中括号表达式的开始和结束位置。 | java匹配j[abc]va |
- | [] 内表示字符范围 | java匹配[a-z]av[a-g] |
^ | 匹配一行的开头。 | java匹配j[^b-f]va |
\ | 用于转义下一个字符,或指定八进制、十六进制字符。 | (匹配( |
$ | 匹配一行的结尾。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与"\n"或"\r"之前的位置匹配。 | ;$匹配位于一行及外围的;号 | |
* | 指定前面子表达式可以出现零次或多次 | zo* 匹配zoo或z |
+ | 指定前面子表达式可以出现一次或多次 | zo+ 匹配zo或zoo |
? | 指定前面子表达式可以出现零次或一次 | zo? 匹配z或zo |
{} | 用于标记前面子表达式的出现频度 | o{2} 匹配food中的两个o |
() | 标记子表达式的开始和结束位置 | o{2} 匹配food中的两个o |
\b | 匹配一个字边界 va\b匹配java中的va,但不匹配javar中的va | |
\B | 非字边界匹配 va\B匹配javar中的va,但不匹配java中的va | |
\d | 匹配 0~9 的所有数字 | 1[\d] 可匹配13 、15 |
\D | 匹配非数字 | [\D]java匹配Jjava |
\w | 匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_ | java匹配[\w]ava |
\W | 匹配所有的非单词字符 | $java匹配[\W]java |
\s | 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等 | Java 2匹配Java\s2 |
\S | 匹配所有的非空白字符 java匹配 j[\S]va | |
\f | 匹配换页符 | 等效于\x0c和\cL |
\n | 匹配换行符 | 等效于\x0a和\cJ |
Object
三 equals 方法
在 Java 中,equals() 方法用于比较两个对象是否相等。默认情况下,equals() 方法比较的是对象的引用,即两个对象只有在引用相同的情况下才被认为是相等的。
如果你想比较两个对象的值是否相等,你需要重写 equals() 方法。重写 equals() 方法的一般步骤如下:
- 检查传入的对象是否为 null,如果是,返回 false。
- 检查传入的对象是否与该对象相同,如果是,返回 true。
- 检查传入的对象是否属于同一类,如果不是,返回 false。
- 将传入的对象转换为该类的类型。
- 比较该类中的所有字段是否相等,如果都相等,返回 true,否则返回 false。
举个例子:
public class Person {
private String name;
private int age;
// 构造函数和其他方法省略
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
Person other = (Person) obj;
if (!Objects.equals(name, other.name)) {
return false;
}
if (age != other.age) {
return false;
}
return true;
}
}
在这个示例中,我们重写了 equals() 方法来比较两个 Person 对象是否相等。我们首先检查传入的对象是否为 null,然后检查传入的对象是否与该对象相同。接下来,我们将传入的对象转换为 Person 类型,并比较 name 和 age 字段是否相等。如果都相等,则返回 true,否则返回 false。
equals 和 ==
在Java中,equals()和==都是用于比较两个对象是否相等的方法,但它们之间有一些区别。
equals()方法是Object类的一个方法,它用于比较两个对象的值是否相等。默认情况下,equals()方法比较的是对象的引用,即两个对象只有在引用相同的情况下才被认为是相等的。因此,如果你想比较两个对象的值是否相等,你需要重写equals()方法。
举例:
public class Person {
private String name;
private int age;
// 构造函数和其他方法省略
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (getClass() != obj.getClass()) {
return false;
}
Person other = (Person) obj;
if (!Objects.equals(name, other.name)) {
return false;
}
if (age != other.age) {
return false;
}
return true;
}
}
在这个示例中,我们重写了equals()方法来比较两个Person对象是否相等。我们首先检查传入的对象是否为null,然后检查传入的对象是否与该对象相同。接下来,我们将传入的对象转换为Person类型,并比较name和age字段是否相等。如果都相等,则返回true,否则返回false。
另一方面,==运算符用于比较两个对象的引用是否相等。如果两个对象的引用相同,则它们被认为是相等的。否则,它们被认为是不同的。因此,如果你想比较两个对象的引用是否相等,你应该使用==运算符。
例如:
Person p1 = new Person("Tom", 20);
Person p2 = new Person("Tom", 20);
Person p3 = p1;
System.out.println(p1 == p2); // false,p1和p2是不同的对象
System.out.println(p1 == p3); // true,p1和p3引用同一个对象