枚举类enumeration(enum)

枚举是一组常量的集合。也就是说枚举属于一种特殊的类,里面只包含一组有限的特定的对象。

自定义枚举类

实现方法:

  1. 将构造器私有化,防止直接new出来
  2. 去掉set方法,防止属性被修改
  3. 直接在内部创建固定的对象
  4. 对外暴露对象(通过为对象添加 public static 修饰符)
  5. 优化:加入一个final修饰符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Season.java
public class Season {
private String name;
private String desc;

private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}

public static final Season SPRING = new Season("春天", "温暖");
public static final Season SUMMER = new Season("夏天", "炎热");
public static final Season AUTUMN = new Season("秋天", "凉爽");
public static final Season WINTER = new Season("冬天", "寒冷");

public String getName() {
return name;
}

public String getDesc() {
return desc;
}

@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}

//使用此枚举类
public static void main(String[] args) {
System.out.println(Season.SPRING);
}

使用enum关键字生成枚举类

实现方法:

  1. 使用关键字enum替代class
  2. public static final Season SPRING = new Season(“春天”, “温暖”); -> SPRING(“春天”, “温暖”); 即:常量名(实参列表);
  3. 如果有多个常量(对象),使用逗号间隔,最后一个用分号
  4. 定义的常量对象必须写在最前面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Season01.java
public enum Season01 {
SPRING("春天", "温暖"),
SUMMER("夏天", "炎热"),
AUTUMN("秋天", "凉爽"),
WINTER("冬天", "寒冷");

private String name;
private String desc;

private Season01(String name, String desc) {
this.name = name;
this.desc = desc;
}

public String getName() {
return name;
}

public String getDesc() {
return desc;
}

@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}

//使用此枚举类
public static void main(String[] args) {
System.out.println(Season01.SPRING);
}

enum常用方法

方法名 详细描述
valueOf 将字符串转化为枚举对象,要求字符串必须为已有常量名,否则报异常
toString Enum类已经重写该方法了,返回的是当前对象名。子类可以重写该方法,用来返回对象的属性信息
equals 类似于二元运算符 ==
getDeclaringClass 得到枚举常量所属的枚举类型
name 返回当前对象名(常量名),子类不能重写
ordinal 返回当前对象的位置号(默认从0开始)
compareTo 比较两个枚举常量,比较的就是位置号
clone 枚举类不能被clone。Enum类实现了一个仅抛出异常的不变clone(),防止子类实现克隆方法。
values 返回当前枚举类中的所有常量

String类

说明:

  1. String 对象用于保存字符串,也就是一组字符序列
  2. 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节大小
  3. String 类有很多构造器,常用的有:
    • String str = new String();
    • String str = new String(String original);
    • String str = new String(char[] a);
    • String str = new String(char[] a, int startIndex, int count);
    • String str = new String(byte[] b);
  4. String 类实现了 Serializable 接口(可以串行化:可以在网络上传输,可以保存到文件)
  5. String 类实现了 Comparable 接口(String 对象可以比较大小)
  6. String 是 final 类,不能被其他的类继承
  7. String 内部实现时:private final char value[]; 存储时本质就是不可变字符数组

声明和创建

1
2
3
4
5
6
//声明
String str;

//创建
1. String str = "Hello, world!";
2. String str = new String("Hello, world!");

两种字符串创建方式的区别:

方式一:先从常量池查看是否有”Hello, world!”数据空间,如果有,则直接指向;如果没有,则重新创建然后指向。所以str最终指向的是常量池的空间地址。相当于值传递。

方式二:先在堆中创建空间,里面维护了value属性,指向常量池的”Hello, world!”数据空间。如果常量池没有”Hello, world!”,则重新创建。所以使用这种方法,实际上是创建了两个对象。相当于引用。

String类常用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
字符串的比较:
matches
判断字符串与指定正则表达式是否相匹配,如:
String a = "Hello";
String re = ".*?";
System.out.println(a.matches(re));
equals
判断字符串在堆中是否相等
compareTo
比较两个字符串的大小
前面的参数大返回1
后边的参数大则返回-1
相等返回0
regionMatches
比较两个字符串的特定区域是否相等
参数:字符串1.regionMathes((是否忽略大小写boolean,)串1起始下标,字符串2,串2起始下标,比较长度);
startsWith
检测字符串是否以指定前缀开始
endsWith
检测字符串是否以指定后缀结束
equalsIgnoreCase
忽略大小写
compareToIgnoreCase
忽略大小写
获取字符串
length()
charAt()
用于返回指定索引的字符
str1 = str1.concat(str2);
将str2连接到str1上,并返回连接后的字符串
substring
返回指定字符串的子串
参数:str1.substring(起始下标,(终止下标));
在原字符串的基础上创建新字符串(不改变原字符串),返回String类型
toLowerCase
将字符串变为小写
toUpperCase
将字符串变为大写
trim
删除字符串的头尾空白符
replace
替换原字符串中的特定字符/字符串
参数:str1.replace(old, new);
replaceFirst
替换原字符串第一个匹配给定正则表达式的子字符串
参数:str1.replaceFirst(正则表达式,替换的串);
匹配失败返回原字符串
replaceAll
替换原字符串所有匹配给定正则表达式的子字符串
split
根据给定的正则表达式拆分字符串,返回字符串数组类型
参数:str1.split(正则表达式(,要拆分的份数));
从前往后拆分
找出某个字符串或者字串(以下两个方法方法重载方法较多)
indexOf
参数:str1.indexOf(char/String(,fromIndex));
返回指定字符/字符串(从fromIndex位置开始)在母串第一次出现处的索引,如果没有,返回-1
lastIndexOf
返回指定字符/字符串在母串最后一次出现处的索引,如果没有,返回-1。如果有fromIndex参数,则从此位置反向索引
字符串与数组之间的转化
串转化为数组
getBytes((String charsetName));
使用特定的字符集将字符串编码为byte序列,并将结果存储到一个新的byte数组中。如果不写参数,会使用平台默认的字符集
toCharArray
直接返回字符串转换而成的字符数组
参数:str1.toCharArray();
getChars
参数:str1.getChars(要复制的第一个字符的下标,要复制的最后一个字符的下标,目标字符数组,目标字符数组的起始下标);
没有返回值,但会抛出IndexOutOfBoundsException异常
数字转化为串
new String(char[])
将字符数组转换为字符串并返回
String.valueOf(Object o);
将传进去的int/long/float/double/Object/char/char[]/boolean类型转换为String类型并返回
格式化字符串
format
如:System.out.format("%s", str1);等同于 System.out.printf("%s", str1);

StringBuilder 和 StringBuffer 类

String 中的内容是不可变的,当需要对字符串中的内容做修改时,应使用StringBuilder和StringBuffer类。(上述方法提到的修改String内容的方法实际上是创建了新对象,使用StringBuilder和StringBuffer修改时不会产生新对象)

区别

区别:StringBuilder 类是在 Java5 之后才出现的。StringBuilder 的方法是线程不安全的(不能同步访问),但是它的效率更高。

常用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
StringBuilder类/StringBuffer类
append
将指定字符插入到原字符的末尾
insert
参数:str1.insert(offset, str);
将字符串str插入到原字符串str1的下标为offset后的位置
delete
参数:str1.delete(start, end);
删除str1从start到end的内容(前闭后开)
reverse
将字符串反转
replace
参数:str1.replace(start, end, str);
用str替换str1中从start到end之间的内容(前闭后开)
setCharAt
参数:str1.setCharAt(index, char);
将下标为index的内容更改为char
几个常见方法
toString
转为字符串
capacity
返回当前容量
ensureCapacity(int minimumCapacity)
确保容量至少等于指定的最小值
charAt
返回指定下标元素
length()
返回字符串长度
setLength
设置字符序列长度
substring
参数:str1.substring(start(, end));
返回从start到end之间的内容(end可有可无)
trimToSize
将动态数组的容量调整为数组的个数

String, StringBuilder, StringBuffer 对比

  1. String 不可变序列,效率低,但是复用率高,适合在不对字符串修改时使用
  2. StringBuffer 可变序列,效率较高,但是线程安全,多线程操作时是首选
  3. StringBuilder 可变序列,效率最高,但是线程不安全,只能在单线程程序中使用

日期和时间

Calendar 类说明:

  1. Calendar 是一个抽象类,并且构造器是 private
  2. 可以通过 getInstance() 来获取实例
  3. Calendar 提供了大量的方法和字段给程序员
  4. Calendar 没有提供对应的格式化的类,因此需要程序员自己组合来输出
  5. 如果要按照 24 小时进制来获取时间,Calendar.HOUR ==改成==> Calendar.HOUR_OF_DAY
1
2
3
4
5
6
7
8
9
//获取时间
Calendar c = Calendar.getInstance();

System.out.println("年" + c.get(Calendar.YEAR));
c.get(Calendar.MONTH)+1;
c.get(Calendar.DAY_OF_MONTH);
c.get(Calendar.HOUR);
c.get(Calendar.MINUTE);
c.get(Calendar.SECOND);

注意:Calendar 返回月份时,默认是从0开始,所以要加1

前两代日期类的不足的分析:

JDK1.0 中包含了一个 java.util.Date 类,但是它的大多数方法已经在 JDK1.1 引入 Calendar 类之后被弃用了。而 Calendar 也存在的问题是:

  1. 可变性:像日期和时间等这样的类应该是不可变的。
  2. 偏移性:Date 中的年份是从 1900 开始的,而月份都从 0 开始。
  3. 格式化:格式化只对 Date 有用,Calendar 则不行。
  4. 此外,他们也是线程不安全的;不能处理闰秒等(每隔2天,多出1秒)。

第三代日期常用方法(JDK8 加入)

  1. LocalDate (日期==年月日)
  2. LocalTime (时间==时分秒)
  3. LocalDateTime (日期时间==年月日时分秒)
1
2
3
4
5
6
7
8
9
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//格式为:2022-01-05T11:46:15.304429400
System.out.println(ldt.getYear());
System.out.println(ldt.getMonth());//英文显示的月份
System.out.println(ldt.getMonthValue());//数字显示的月份
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());

可以使用 DateTimeFormatter 类对日期进行格式化,代码如下:

1
2
3
4
5
LocalDateTime ldt = LocalDateTime.now();

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = dateTimeFormatter.format(ldt);
System.out.println(format);

其他

Instant 时间戳:

1
2
3
4
5
6
7
8
9
//1. 通过静态方法 now() 获取表示当前时间戳的对象
Instant now = Instant.now();
System.out.println(now);

//2. 通过 from 可以把 Instant 转成 Date
Date date = Date.from(now);

//3. 通过 date 的 toInstant() 可以把 date 转成 Instant 对象
Instant instant = date.toInstant();

还有一系列的 plus 和 minus 方法可以对日期进行加减操作

1
2
3
4
5
6
7
//看看 890 天后是什么时候
LocalDateTime localDateTime = ldt.plusDays(890);
System.out.println("890天后 = " + dateTimeFormatter.format(localDateTime));

//看看 3456 分钟前是什么时候
LocalDateTime localDateTime2 = ldt.minusMinutes(3456);
System.out.println("3456分钟前 = " + dateTimeFormatter.format(localDateTime2));

常用包装类

Java 为每一个内置数据类型提供了对应的包装类。所有的包装类(Integer, Long, Byte, Double, Float, Short)都是抽象类 Number 的子类。

对应关系如下:

包装类 基本数据类型
Boolean boolean
Byte byte
Short short
Integer int
Long long
Character char
Float float
Double double

继承关系如下:

img

从内置类型到包装类叫做装箱,从包装类对象到内置类型叫做拆箱。

只有变成了包装类才能使用类中的方法,而且一般编译器会自动进行装箱、拆箱的过程。

除 Character 外,字符串都可以通过 parseXXX(String str) 的方法转化为基本数据类型

Math数学类

Math 类常用方法(Math 类的方法都为 static 形式,可以直接使用):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1. 三角函数方法
double sin(double radians)
double cos(double radians)
double tan(double radians)
double toRadians(double degrees)
double toDegrees(double radians)
double asin(double a)
double acos(double a)
double atan(double a)
2. 指数函数方法
double exp(double x) e的x次方
double log(double x) ln(x)
double log10(double x) lg(x)
double pow(double a,double b) a的b次方
double sqrt(double x) x的平方根
3. 服务方法
取整方法
double ceil(double x) //向上取整
double floor(double x) //向下取整
double rint(double x) //向最近的取整
int round(float x) //四舍五入
long round(double x) //四舍五入
min, max, abs方法
random方法
4. double型常量:Math.PI(圆周率) Math.E(自然对数的底数)

System 类

常用方法:

  1. exit 退出当前程序
  2. arrayCopy 复制数组元素,比较适合底层调用。一般使用 Arrays.copyOf 完成复制数组。
1
2
3
int[] source = {1, 2, 3};
int destination = new int[3];
System.arrayCopy(source, 0, destination, 0, 3);
  1. currentTimeMillens 返回当前时间距离 1970-1-1 的毫秒数
  2. gc 运行垃圾回收机制 System.gc();