1.包装类
1.1 概述
Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,但当使用只针对对象设计的API或新特性(例如泛型),那么基本数据类型的数据就需要用包装类来包装。
序号 | 基本数据类型 | 包装类(java.lang包) |
---|---|---|
1 | byte | Byte |
2 | short | Short |
3 | int | Integer |
4 | long | Long |
5 | float | Float |
6 | double | Double |
7 | char | Character |
8 | boolean | Boolean |
9 | void | Void |
1.2 包装类的特点
-
① 封装性 所有的包装类都是 final 类,确保包装类的行为和特性的一致性, 避免子类可能引入不确定性。
-
② 不可变性 包装类的实例一旦被创建后,其中保存的基本数据类型数据就不能再被改变, 确保其更加安全。
-
③ 提供方法 包装类封装了许多实用的方法,提供了丰富的功能。eg:支持数据类型转换、判断字符串的大小写、以及获取最大值和最小值等。
-
④ 继承关系 除了 Character 和 Boolean 之外,其他所有的包装类都继承自 Number 类。
1.3 装箱和拆箱
1.3.1 概述
装箱(Boxing)是将基本数据类型转换为相应的包装类的过程。拆箱(Unboxing)是将包装类转换为基本数据类型的过程。手动装箱即使用一个int值创建一个 Integer 对象;手动拆箱即使用 Integer 类型对象的 intValue() 方法来获取这个对象的 int 值。
public class Test {public static void main(String[] args) {int num1 = 4;// 装箱方式1:Integer boxed1 = new Integer(num1);// 装箱方式2:Integer boxed2 = Integer.valueOf(4);// 手动拆箱int i = boxed1.intValue();}
}
1.3.2 自动装箱和自动拆箱
Java 5引入了自动装箱(Auto-boxing)和自动拆箱(Auto-unboxing)机制,简化了基本数据类型与包装类之间的转换过程。自动装箱是将基本数据类型自动转换为其对应的包装类对象的过程。自动拆箱则是将包装类对象自动转换为其对应的基本数据类型。
public class Test {public static void main(String[] args) {int num1 = 4;// 自动装箱--> 底层使用的是 Integer.valueOf(num1)Integer i1 = num1;// 自动拆箱--> 底层使用的是 intValue()方法int i2 = i1;}
}
自动装箱是通过调用包装类的**valueOf()方法来实现的。自动拆箱是通过调用包装类对象的xxxValue()**方法来实现的。
1.4 缓存机制
Java中的包装类缓存机制是为了优化性能和节省内存而设计的。它为整型(Byte、Short、Integer、Long)、字符型(Character)和布尔型(Boolean)的包装类提供了缓存,确保在这些类型的小范围值之间可以复用对象。而对于浮点数类型的包装类(Float、Double),则没有这种缓存机制,意味着每次都需要创建新的对象。
包装类 | 缓存范围 |
---|---|
Byte | -128~127 |
Short | -128~127 |
Integer | -128~127 |
Long | -128~127 |
Float | 没有 |
Double | 没有 |
Character | 0~127 |
Boolean | true和false |
1.5 包装类与字符串相互转换
1.5.1 包装类转换为字符串
Integer i = 10000;// 方式一
String str1 = i + "";// 方式二
String str2 = i.toString();// 方式三
String str3 = String.valueOf(i);
1.5.2 字符串转换为包装类
String str = "10000";// 方式一
Integer i1 = Integer.parseInt(str);// 方式二
Integer i2 = Integer.valueOf(str);// 方式三
Integer i3 = new Integer(str);
1.6 应用实例
public class WrapperExercise {public static void main(String[] args) {/*** //1. 如果 i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回* //2. 如果不在 -128~127,就直接 new Integer(i)* public static Integer valueOf(int i) {* if (i >= IntegerCache.low && i <= IntegerCache.high)* return IntegerCache.cache[i + (-IntegerCache.low)];* return new Integer(i);* }*/Integer i1 = new Integer(127);Integer i2 = new Integer(127);System.out.println(i1 == i2); // false 比较两个对象是否相等System.out.println(i1.equals(i2));// true 比较两个对象的值Integer i3 = new Integer(128);Integer i4 = new Integer(128);System.out.println(i3 == i4); // false// 见上述valueOf源码Integer i5 = 127;//底层 Integer.valueOf(127)Integer i6 = 127;//-128~127System.out.println(i5 == i6); // trueInteger i7 = 128;Integer i8 = 128;System.out.println(i7 == i8);//false 超出了范围Integer i9 = 127; //Integer.valueOf(127)Integer i10 = new Integer(127);System.out.println(i9 == i10);//falseInteger i11=127;int i12=127;//只有有基本数据类型,判断的是值是否相同System.out.println(i11==i12); //true}
}
2.String类
2.1 概述
java.lang.String
类代表字符串, 一组字符序列。Java程序中所有的字符串文字(例如"abc"
)都可以被看作是实现此类的实例。字符串是常量, 它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。
String
类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。 Java 语言提供对字符串串联符号(“+”)以及将其他对象转换为字符串的特殊支持(toString()方法)。
2.2 创建 String 对象方式
2.2.1 使用构造方法
构造方法 | 说明 |
---|---|
public String() | 初始化新创建的 String对象,以使其表示空字符序列。 |
String(String original) | 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。 |
public String(char[] value) | 通过当前参数中的字符数组来构造新的String。 |
public String(char[] value,int offset, int count) | 通过字符数组的一部分来构造新的String。 |
public String(byte[] bytes) | 通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。 |
public String(byte[] bytes,String charsetName) | 通过使用指定的字符集解码当前参数中的字节数组来构造新的String。 |
创建String对象的方式主要有:①直接赋值 ②调用构造器。在内存中的图解如下:
// String 类有很多构造器,构造器的重载。
//字符串常量对象-->直接赋值
String str = "hello";// 无参构造-->调用构造器
String str1 = new String();//创建"hello"字符串常量的副本-->调用构造器
String str2 = new String("hello");//通过字符数组构造-->调用构造器
char chars[] = {'a', 'b', 'c','d','e'};
String str3 = new String(chars);
String str4 = new String(chars,0,3);// 通过字节数组构造-->调用构造器
byte bytes[] = {97, 98, 99 };
String str5 = new String(bytes);
String str6 = new String(bytes,"GBK");
2.2.2 使用静态方法
静态方法 | 说明 |
---|---|
static String copyValueOf(char[] data) | 返回指定数组中表示该字符序列的 String |
static String copyValueOf(char[] data, int offset, int count) | 返回指定数组中表示该字符序列的 String |
static String valueOf(char[] data) | 返回指定数组中表示该字符序列的 String |
static String valueOf(char[] data, int offset, int count) | 返回指定数组中表示该字符序列的 String |
static String valueOf(xx value) | xx支持各种数据类型,返回各种数据类型的value参数的字符串表示形式 |
public class Test {public static void main(String[] args) {char[] data = {'h', 'e', 'l', 'l', 'o', 'j', 'a', 'v', 'a'};String s1 = String.copyValueOf(data);String s2 = String.copyValueOf(data, 0, 5);int num = 123456;String s3 = String.valueOf(num);System.out.println(s1);// hellojavaSystem.out.println(s2);// helloSystem.out.println(s3);//123456}
}
2.2.3 使用"+"
任意数据类型与"字符串"进行拼接,结果都是字符串。
public class Test {public static void main(String[] args) {int num = 123456;String s = num + "";System.out.println(s);Student stu = new Student(18,"科比");String s2 = stu + "";//自动调用对象的toString(),然后与""进行拼接System.out.println(s2);}
}
2.3 字符串的特点
-
① 字符串String类型本身是final声明的,意味着不能继承String。
-
② 字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新对象。
-
③ String对象内部是用字符数组进行保存的。
"abc"
等效于char[] data={ 'a' , 'b' , 'c' }
。例如: String str = "abc";相当于: char data[] = {'a', 'b', 'c'}; String str = new String(data); // String底层是靠字符数组实现的。
-
④ 字符串常量存储在方法区中的常量池中。
-
⑤ 字符串的字符使用 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节。
-
⑥ String 类实现了接口 Serializable【String 可以串行化:可以在网络传输】, 另外 String类也接口 Comparable [String 对象可以比较大小]。
-
⑦ String 有属性 private final char value[]; 用于存放字符串内容[底层是char数组]。
2.4 字符串对象的比较
-
① ==: 比较的是对象的地址
String str1 = "hello"; String str2 = "hello"; System.out.println(str1 == str2);//trueString str3 = new String("hello"); String str4 = new String("hello"); System.out.println(str1 == str4); //false System.out.println(str3 == str4); //false
-
② equals:比较是对象的内容,因为String类型重写equals,区分大小写。
String str1 = "hello"; String str2 = "hello"; System.out.println(str1.equals(str2));//trueString str3 = new String("hello"); String str4 = new String("hello"); System.out.println(str1.equals(str3));//true System.out.println(str3.equals(str4));//true
-
③ equalsIgnoreCase:比较的是对象的内容,不区分大小写
String str1 = new String("hello"); String str2 = new String("HELLO"); System.out.println(str1.equalsIgnoreCase(strs)); //true
-
④ compareTo:String类型重写了Comparable接口的抽象方法,自然排序,按照字符的Unicode编码值进行比较大小的,严格区分大小写
String str1 = "hello"; String str2 = "world"; System.out.println(str1.compareTo(str2));//小于0的值 -15
-
⑤ compareToIgnoreCase:不区分大小写,其他按照字符的Unicode编码值进行比较大小
String str1 = new String("hello"); String str2 = new String("HELLO"); System.out.println(str1.compareToIgnoreCase(str2)); //等于0
2.5 字符串的常用方法
方法 | 说明 |
---|---|
boolean equals(Object obj) | 比较字符串内容是否相等,区分大小写 |
boolean equalsIgnoreCase(Object obj) | 比较字符串内容是否相等,不区分大小写 |
int length() | 返回字符串的长度 |
int indexOf(xx) | 从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1 |
int lastIndexOf(xx) | 从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1 |
String substring(int beginIndex) | 返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。 |
String substring(int beginIndex, int endIndex) | 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。 |
String trim() | 去掉字符串前后空白符 |
char charAt(index) | 返回[index]位置的字符 |
String toLowerCase() | 将字符串中大写字母转为小写 |
String toUpperCase() | 将字符串中小写字母转为大写 |
String concat(xx) | 拼接,等价于+ |
String replace(xx,xx) | 替换字符串中的字符 |
String[] split(正则) | 按照某种规则进行拆分 |
char[] toCharArray() | 将此字符串转换为一个新的字符数组返回 |
public class Test {public static void main(String[] args) {String str1 = "hello";String str2 = "HELLO";// 比较两个字符串内容是否相等,区分大小写System.out.println(str1.equals(str2));//false// 比较两个字符串内容是否相等,不区分大小写String user_name = "JohN";if ("john".equalsIgnoreCase(user_name)) {System.out.println("相等");}else{System.out.println("不相等");}// 获取字符串的长度System.out.println("Tim".length());String str3 = "qwer@xzf@lkh";// 获取指定字符的索引,从前往后获取第一个指定字符的索引System.out.println(str3.indexOf("@"));// 获取指定字符的索引,从后往前获取最后一个指定字符的索引System.out.println(str3.lastIndexOf("@"));String str4 = "hellO";// 转换为小写System.out.println(str4.toLowerCase());// 转换为大写System.out.println(str4.toUpperCase());}
}
2.6 应用实例
Q: String a = “hello”, String b = “abc”, String c = a +b, 在程序执行过程中, 创建了几个对象?
public class StringExercise {public static void main(String[] args) {String a = "hello";String b = "abc";String c = a + b;// 1.创建一个 StringBilder sb = new StringBuilder(); 对象// 2.执行 sb.append("hello");// 3.执行 sb.append("abc");// 4.String c = sb.toString(value,0,count);System.out.println(c);}
}
上述案例分析的关键点在于分析String c = a +b 是如何执行的? 底层是通过StringBuilder对象的append方法来实现。String d = “ab” + “cd”; 常量相加, 看的是池。 String e = a + b; 变量相加, 看的是堆。
下列程序运行的结果是什么, 尝试画出内存分布图?
public class StringExercise1 {String str = new String("flink");final char[] ch = {'j', 'a', 'v', 'a'};public void change(String str, char ch[]) {str = "java";ch[0] = 'h';}public static void main(String[] args) {StringExercise1 se = new StringExercise1();se.change(se.str,se.ch);System.out.print(se.str + " and ");System.out.println(se.ch);}
}/**
输出结果: flink and hava
*/
3.StringBuffer类
3.1 概述
java.lang.StringBuffer 代表可变的字符序列, 可以对字符串内容进行增删。StringBuffer是final类, 不能被继承。StringBuffer类实现了Serializable 接口, 可以保存到文件或者网络传输。StringBuffer类继承了抽象类AbstractStringBuilder, 其中的属性属性 char[] value, 存放字符序列。StringBuffer保存的是字符串变量,每次更新内容不用更新地址, String保存的是字符串常量, 每次更新需要更新更新地址, StringBuffer的效率高于String。
3.2 String与StringBuffer相互转换
- String --> StringBuffer: ① 调用构造器 ② 调用append方法
- StringBuffer–>String: ① 调用toString方法 ② 调用构造器
public class Test {public static void main(String[] args) {// string --> stringBufferString str = "hello world";StringBuffer stringBuffer = new StringBuffer(str);System.out.println(stringBuffer);StringBuffer stringBuffer1 = new StringBuffer();StringBuffer stringBuffer2 = stringBuffer1.append(str);System.out.println(stringBuffer2);//stringBuffer --> stringStringBuffer stringBuffer3 = new StringBuffer("java python");String str1 = stringBuffer3.toString();System.out.println(str1);String str2 = new String(stringBuffer3);System.out.println(str2);}
}
3.3 StringBuffer的常用方法
方法 | 说明 |
---|---|
append() | 将指定字符串、字符、布尔值或其他数据类型的表示追加到字符串缓冲区的末尾。 |
insert() | 在指定位置插入指定字符串、字符、布尔值或其他数据类型的表示。 |
replace() | 用新的字符串替换指定范围内的字符序列[不包含结束位置下标]。 |
delete() | 删除指定范围内的字符序列[不包含结束位置下标]。 |
deleteCharAt() | 删除指定索引处的字符。 |
reverse() | 反转字符串缓冲区中的字符序列。 |
charAt() | 获取指定索引处的字符。 |
substring() | 返回一个新的字符串,其中包含字符串缓冲区中指定范围内的字符[不包含结束位置下标]。 |
indexOf() | 返回指定子字符串第一次出现的索引。 |
length() | 返回字符串缓冲区中的字符数。 |
toString() | 将字符串缓冲区中的字符序列转换为字符串。 |
public class Test {public static void main(String[] args) {StringBuffer s = new StringBuffer("hello");//增s.append(',');// "hello,"s.append("张三丰");//"hello,张三丰"s.append("赵敏").append(100).append(true).append(10.5);System.out.println(s);//"hello,张三丰赵敏 100true10.5"//删s.delete(11, 14);System.out.println(s);//"hello,张三丰赵敏 true10.5"// 改s.replace(9, 11, "周芷若");System.out.println(s);//"hello,张三丰周芷若 true10.5"//查int indexOf = s.indexOf("张三丰");System.out.println(indexOf);//6//插入s.insert(9, "赵敏");System.out.println(s);//"hello,张三丰赵敏周芷若 true10.5"//长度System.out.println(s.length());//22}
}
3.4 应用实例
下面的程序输出结果是什么?
public class StringBufferExercise01 {public static void main(String[] args) {String str = null;StringBuffer sb = new StringBuffer();sb.append(str); //底层调用的是 AbstractStringBuilder 的 appendNullSystem.out.println(sb.length()); //4 --> null的字符串的长度System.out.println(sb); //null//下面的构造器,会抛出 NullpointerExceptionStringBuffer sb1 = new StringBuffer(str); //底层源码 super(str.length() + 16);System.out.println(sb1);}
}
4.StringBuilder类
4.1 概述
StringBuilder类是一个可变的字符序列, 此类提供一个与StringBuffer兼容的API, 但不保证同步(StringBuilder不是线程安全)。该类被设计用作StringBuffer的简易替换, 用在字符串缓冲区被单个线程使用的情况。如果可能, 建议优先采用该类, 其效率比StringBuffer高。StringBuilder类实现了Serializable 接口, 可以保存到文件或者网络传输。StringBuilder类继承了抽象类AbstractStringBuilder, 其中的属性属性 char[] value, 存放字符序列。
4.2 String、StringBuffer 和 StringBuilder 的比较
类名 | 说明 |
---|---|
String | 不可变字符序列,效率低,但是复用率高 |
StringBuffer | 可变字符序列,效率较高,线程安全 |
StringBuilder | 可变字符序列,效率最高,线程不安全 |
String Vs StringBuffer Vs StringBuilder 的效率 : StringBuilder > StringBuffer > String
public class Test {public static void main(String[] args) {long startTime = 0L;long endTime = 0L;StringBuffer buffer = new StringBuffer("");startTime = System.currentTimeMillis();for (int i = 0; i < 80000; i++) {//StringBuffer 拼接 20000 次buffer.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuffer 的执行时间:" + (endTime - startTime));StringBuilder builder = new StringBuilder("");startTime = System.currentTimeMillis();for (int i = 0; i < 80000; i++) {//StringBuilder 拼接 20000 次builder.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuilder 的执行时间:" + (endTime - startTime));String text = "";startTime = System.currentTimeMillis();for (int i = 0; i < 80000; i++) {//String 拼接 20000text = text + i;}endTime = System.currentTimeMillis();System.out.println("String 的执行时间:" + (endTime - startTime));}
}
4.3 String、StringBuffer 和 StringBuilder 应用场景
- ① 如果字符串存在大量的修改操作, 一般使用 StringBuffer 或者 StringBuilder。
- ② 如果字符串存在大量的修改操作, 并在单线程的情况下,使用 StringBuilder。
- ③ 如果字符串存在大量的修改操作, 并在多线程的情况下,使用 StringBuffer。
- ④ 如果字符串很少修改, 被多个对象引用, 使用String, 比如配置信息等。
5.Math类
5.1 概述
java.lang.Math
类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。
5.2 常用方法
方法 | 说明 |
---|---|
public static double abs(double a) | 返回 double 值的绝对值。 |
public static double ceil(double a) | 返回大于等于参数的最小的整数。 |
public static double floor(double a) | 返回小于等于参数最大的整数。 |
public static long round(double a) | 返回最接近参数的 long。 |
public static double pow(double a,double b) | 返回a的b幂次方法。 |
public static double sqrt(double a) | 返回a的平方根。 |
public static double random() | 返回[0,1)的随机值。 |
public static final double PI | 返回圆周率。 |
public static double max(double x, double y) | 返回x,y中的最大值。 |
public static double min(double x, double y) | 返回x,y中的最小值。 |
public class Test {public static void main(String[] args) {//1.abs 绝对值int abs = Math.abs(-9);System.out.println(abs);//9//2.pow 求幂double pow = Math.pow(2, 4);//2 的 4 次方System.out.println(pow);//16//3.ceil 向上取整,返回>=该参数的最小整数(转成 double);double ceil = Math.ceil(3.9);System.out.println(ceil);//4.0//4.floor 向下取整,返回<=该参数的最大整数(转成 double)double floor = Math.floor(4.001);System.out.println(floor);//4.0//5.round 四舍五入 Math.floor(该参数+0.5)long round = Math.round(5.51);System.out.println(round);//6//6.sqrt 求开方double sqrt = Math.sqrt(9.0);System.out.println(sqrt);//3.0//max , min 返回最大值和最小值int min = Math.min(1, 9);int max = Math.max(45, 90);System.out.println("min=" + min);System.out.println("max=" + max);}
}
6.Array类
6.1 概述
java.util.Arrays数组工具类,提供了很多静态方法来对数组进行操作[比如排序和搜索]。
6.2 常用方法
方法 | 说明 |
---|---|
toString() | 返回指定数组的内容的字符串表示形式。 |
sort(自然排序或指定排序) | 将数组内容按照自然顺序或者指定顺序进行排序。 |
binarySearch() | 通过二分搜索法进行查找(要求排好序)。 |
copyOf() | 数组元素的复制, 截断或填充零(如果必要)所以副本具有指定的长度。 |
fill() | 数组元素的填充 |
equals() | 比较两个数组元素内容是否一致 |
asList() | 将一组值转换成list |
使用示例如下:
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;public class Test {public static void main(String[] args) {// toString()方法Integer[] integers = {1, 20, 90};System.out.println(Arrays.toString(integers));// sort方法Integer arr[] = {1, -1, 7, 0, 89};Arrays.sort(arr);System.out.println(Arrays.toString(arr));Integer arr1[] = {1, -1, 7, 0, 89};// 定制排序Arrays.sort(arr1, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});// 定制排序System.out.println("定制排序结果如下:");System.out.println(Arrays.toString(arr1));// binarySearch 通过二分搜索法进行查找,要求必须排好Integer[] arr2 = {1, 2, 90, 123, 567};int index = Arrays.binarySearch(arr2, 567);System.out.println("index=" + index);//copyOf 数组元素的复制Integer[] newArr = Arrays.copyOf(arr, arr.length);System.out.println("==拷贝执行完毕后==");System.out.println(Arrays.toString(newArr));//fill 数组元素的填充Integer[] num = new Integer[]{9,3,2};Arrays.fill(num, 99);System.out.println("==num 数组填充后==");System.out.println(Arrays.toString(num));//equals 比较两个数组元素内容是否完全一致Integer[] arr3 = {1, 2, 90, 123};boolean equals = Arrays.equals(arr, arr3);System.out.println("equals=" + equals);List asList = Arrays.asList(2,3,4,5,6,1);System.out.println("asList=" + asList);System.out.println("asList 的运行类型" + asList.getClass());}
}
6.3 应用实例
自定义Book类, 类中包含name 和 price, 按price排序(从大到小), 要求使用两种排序方式。其中Book[]数组中有4本书对象。
Book对象
public class Book {private String name;private double price;public Book() {}public Book(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Book{name='" + name + '\'' + ", price=" + price + '}';}
}
ArraysExercise类: 按照price的大小进行排序
import java.util.Arrays;
import java.util.Comparator;public class ArraysExercise {public static void main(String[] args) {Book[] books = new Book[4];books[0] = new Book("红楼梦", 100);books[1] = new Book("西游记", 90);books[2] = new Book("三国演义", 150);books[3] = new Book("水浒传", 300);//1.按照price的大小进行排序Arrays.sort(books, new Comparator<Book>() {//此处是对 Book 数组排序,因此 o1 和 o2 就是 Book 对象@Overridepublic int compare(Book o1, Book o2) {double priceVal = o2.getPrice() - o1.getPrice();if (priceVal > 0) {return 1;} else if (priceVal < 0) {return -1;} else {return 0;}}});System.out.println(Arrays.toString(books));}
}
ArraysExercise类: 按照书名长度排序
import java.util.Arrays;
import java.util.Comparator;public class ArraysExercise {public static void main(String[] args) {Book[] books = new Book[4];books[0] = new Book("假如生活欺骗了你", 100);books[1] = new Book("西游记", 90);books[2] = new Book("三国演义", 150);books[3] = new Book("复活", 300);//1.按照书名的长度大小进行排序Arrays.sort(books, new Comparator<Book>() {//此处是对 Book 数组排序,因此 o1 和 o2 就是 Book 对象@Overridepublic int compare(Book o1, Book o2) {double priceVal = o2.getName().length()-o1.getName().length();if (priceVal > 0) {return 1;} else if (priceVal < 0) {return -1;} else {return 0;}}});System.out.println(Arrays.toString(books));}
}
7.System类
7.1 概述
java.lang.System是Java中的一个预定义类, 提供了一系列用于访问系统资源的静态方法和变量。这些资源包括标准输入、输出和错误流,以及访问环境变量和加载库的方法。
7.2 常见方法
方法 | 说明 |
---|---|
exit(int status) | 终止当前正在运行的Java虚拟机。 |
arraycopy(Object src, int srcPos, Object dest, int destPos, int length) | 从指定的源数组中复制一个数组,开始在指定的位置,到目标数组的指定位置。 |
currentTimeMillis() | 返回当前时间以毫秒为单位。 |
gc() | 运行垃圾收集器。 |
7.3 应用实例
实例1:统计程序耗时
public class SystemUsage01 {public static void main(String[] args) {String massage = "ABC";long start = System.currentTimeMillis();//在操作开始前获取时间戳for (int i = 0; i < 9999; i++) {massage += i;//修改字符串}long end = System.currentTimeMillis();//在操作开始后获取时间戳System.out.println("本次程序执行时间为:" + (end - start)+" ms");}
}
实例2:观察程序退出
在一个JVM进程运行的过程中,如果出现了某些问题,则可以通过exit()方法让JVM直接结束,而exit()并不是System类本身提供的方法,它是由Runtime类提供的!
情况一: 无运行参数
public class SystemUsage02 {//2.观察程序的退出public static void main(String[] args) {if(args.length != 2){ //通过程序接收初始化参数System.out.println("【错误】本程序执行时需要传递初始化运行参数,否则无法运行!");System.out.println("【提示】可以按照以下方法输入参数:java SystemUsage02 字符串 重复次数");System.exit(1);//退出程序}String message = args[0];//获取一个参数内容int count = Integer.parseInt(args[1]);//获取循环次数//Integer.parseInt()将字符串参数转换为有符号的十进制参数for (int i = 0; i < count; i++) {System.out.println(message);}}
}
情况二:有参数运行
运行结果如下:
/*
hello
hello
hello
*/
实例3:回收垃圾
通过exit()
方法可以在Java程序内部来决定当前整个JVM进程是否继续,System类也可以直接进行gc()
方法的调用,实现垃圾回收!
public class SystemUsage {//3.gc()实现垃圾回收public static void main(String[] args) {System.out.println("【1】垃圾产生之前的内存信息:FreeMemory = " + Runtime.getRuntime().freeMemory());String message = "ABC";//定义字符串for (int i = 0; i < 20; i++) {message += message + i + "\n";//产生大量的垃圾}System.gc();//手工进行垃圾清除System.out.println("【2】垃圾产生之后的内存信息:FreeMemory = " + Runtime.getRuntime().freeMemory());}
}/*
运行结果:
【1】垃圾产生之前的内存信息:FreeMemory = 249267304
【2】垃圾产生之后的内存信息:FreeMemory = 305597904
*/
8.日期类
8.1 概述
在程序的开发中我们经常会遇到日期类型的操作,Java对日期类型的操作提供了很好的支持。在最初的版本下,java.lang
包中的System.currentTimeMillis();
可以获取当前时间与协调时间(UTC)1970年1月1日午夜之间的时间差(以毫秒为单位测量)。我们往往通过调用该方法计算某段代码的耗时。
8.2 第一代日期类
8.2.1 Date类
java.util包下的Date类表示特定的瞬间,可精确到毫秒。常用方法如下:
方法 | 说明 |
---|---|
Date() | 返回一个代表当前系统时间的Date对象,精确到毫秒 |
Date(long date) | 返回一个距离UTC时间date毫秒的新日期对象,精确到毫秒 |
int compareTo(Date anotherDate) | 比较两个日期的大小 |
long getTime() | 返回自1970年1月1日00:00:00 GMT以来此Date对象表示的毫秒数 |
String toString() | 把此Date对象转换为以下形式的String:dow mon dd hh:mm:ss zzz yyyy 其中:dow是一周中的某一天(Sun,Mon,Tue,Wed,Thu,Fri,Sat) |
示例如下:
import java.util.Date;public class DateTest {public static void main(String[] args) {// 获取系统时间Date date = new Date();System.out.println("现在的系统时间是:" + date);long time = date.getTime();System.out.println("当前时间距离UTC时间的毫秒数:" + time);}
}
8.2.2 SimpleDateFormat类
java.text.SimpleDateFormat
是格式化和解析日期的具体类。可以进行格式化(日期–>文本)、解析(文本–>日期)和规范化。常见的日期格式化模板如下:
SimpleDataFormat类主要用于将Date日期转换为字符串,或者将某个字符串转换为Date对象,其常见方法如下所示:
方法 | 说明 |
---|---|
format | 将一个Date格式转化为日期/时间字符串,此方法继承的父类DateFormat的方法 |
parse | 从给定字符串的开始解析文本,以生成一个日期,此方法为继承的父类DateFormat的方法 |
public class SimpleDateFormatTest{public static void main(String[] args) throws ParseException {Date d1 = new Date(); //获取当前系统时间SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日 hh:mm:ss E");String format = sdf.format(d1); // format:将日期转换成指定格式的字符串System.out.println("当前日期=" + format);String s = "1996 年 01 月 01 日 10:20:30 星期一";Date parse = sdf.parse(s);System.out.println("parse=" + sdf.format(parse));}
}
8.3 第二代日期类
8.3.1 Calendar类
java.util.Calendar
类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期)提供了一些方法。
方法 | 说明 |
---|---|
static getInstance() | 使用默认时区和语言环境获得一个日历,也可以通过getInstance(TimeZone time,Locale loc)或指定时区和语言环境的日历 |
get(int field) | 获取指定的日历字段 |
set(int year,int month,int date,int hourOfDay,int minute,int second) | 设置字段YEAR、MONTH、DAY_OF_MONTH、HOUR、MINUTE和SECOND的值 |
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;public class CalendarTest {public static void main(String[] args) {Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"), Locale.CHINA);System.out.println("年:"+c.get(Calendar.YEAR));System.out.println("月:"+(c.get(Calendar.MONTH)+1));//1月从0开始System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));System.out.println("小时:"+c.get(Calendar.HOUR));System.out.println("分钟:"+c.get(Calendar.MINUTE));System.out.println("秒:"+c.get(Calendar.SECOND));}
}
8.4 第三代日期类
Java8中引入的java.time
纠正了过去的缺陷,这就是第三代日期API。Java8吸收了Joda-Time的精华,以一个新的开始为Java创建优秀的API。新的java.time
中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的Date类也新增了toInstant()方法,用于把Date类转换成新的表示形式。常用的类有: LocalDate、LocalTime、LocalDateTime类, 均代表日期对象,只是包含的日历字段不同,相当于Calendar类的代替。
8.4.1 LocalDate类
java.time.LocalDate
类:代表一个只包含年、月、日的日期对象,如2007-12-03。LocalDate类常见方法如下所示。
方法 | 说明 |
---|---|
static LocalDate now() | 返回默认时区下的当前日期对象 |
int getYear() | 返回年份,从-999999999-01-01~+999999999-12-31 |
int getMonth() | 返回月份,1-12 |
int getDayOfMonth() | 返回日期,1-31 |
LocalDate parse(CharSequence text) | 按默认格式解析字符串为LocalDate的日期对象 |
LocalDate parse(CharSequence text,DateTimeFormatter formatter) | 按指定格式解析字符串为LocalDate的日期对象 |
应用示例
import java.time.LocalDate;public class LocalDate_ {public static void main(String[] args) {LocalDate ld = LocalDate.now();System.out.println(ld);System.out.println("年="+ld.getYear());System.out.println("月="+ld.getMonth());System.out.println("日="+ld.getDayOfMonth());}
}
/*
2025-01-12
年=2025
月=JANUARY
日=12
*/
8.4.2 LocalTime类
java.time.LocalTime
类:代表一个只包含小时、分钟、秒的日期对象,如13:45.30.123456789。LocalTime常见方法如下:
方法 | 说明 |
---|---|
static LocalTime now() | 返回默认时区下的当前时间对象 |
int getHour() | 返回小时,0-23 |
int getMinute() | 返回分钟,0-59 |
int getSecond() | 返回秒,0-59 |
LocalTime parse(CharSequence text) | 按默认格式解析字符串为LocalTime的日期对象 |
LocalTime parse(CharSequence text,DateTimeFormatter formatter) | 按指定格式解析字符串为LocalTime的日期对象 |
应用示例
import java.time.LocalTime;public class LocalTime_ {public static void main(String[] args) {LocalTime lt = LocalTime.now();System.out.println("时间为:" + lt);System.out.println("时=" + lt.getHour());System.out.println("分=" + lt.getMinute());System.out.println("秒=" + lt.getSecond());}
}/*
时间为:20:27:14.889
时=20
分=27
秒=14
*/
8.4.3 LocalDateTime类
java.time.LocalDateTime
类:代表一个包含年、月、日、小时、分钟、秒的日期对象,如2007-12-03T10:15:30。LocalDateTime常见方法如下:
方法 | 说明 |
---|---|
static LocalDateTime now() | 返回默认时区下的当前日期对象 |
int getYear() | 返回年份,从-999999999-01-01~+999999999-12-31 |
int getMonth() | 返回月份,1-12 |
int getDayOfMonth() | 返回日期:1-31 |
int getHour() | 返回小时:0-23 |
int getMinute() | 返回分钟:0-59 |
int getSecond() | 返回秒:0-59 |
LocalDateTime parse(CharSequence text) | 按默认格式解析字符串为LocalDateTime的日期对象 |
LocalDateTime parse(CharSequence text,DateTimeFormatter formatter) | 按指定格式解析字符串为LocalDateTime的日期对象 |
应用示例
import java.time.LocalDateTime;public class LcoalDateTime_ {public static void main(String[] args) {LocalDateTime ldt = LocalDateTime.now();System.out.println("时间为: " + ldt);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());}
}/*
时间为: 2025-01-12T20:29:54.719
年=2025
月=JANUARY
月=1
日=12
时=20
分=29
秒=54
*/
8.4.4 DateTimeFormatter 类
java.time.format.DateTimeFormatter
类提供格式化日期的方法,该类和第一代日期的SimpleDateFormatter
类似,但SimpleDateFormat
只能格式化Date类,对Calendar类无效。DateTimeFormatter
可以格式化LocalDate
、LocalTime
、LocalDateTime
及Instant
类。DateTimeFormatter
类常见方法如下:
方法 | 说明 |
---|---|
static DateTimeFormatter ofPattern(String pattern) | 静态方法,返回一个DateTimeFormatter对象 |
String format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
TemporalAccessor parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、时间 |
应用示例
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;public class DateTimeFormatterTest {public static void main(String[] args) {LocalDateTime now = LocalDateTime.now();DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd a hh小时mm分钟ss秒");//格式化日期(日期->文本)String format = dtf.format(now);System.out.println(format); // 2025-01-12 下午 08小时33分钟45秒//解析字符串为日期(文本->日期)String s="2018-08-08 下午 05小时06分钟43秒";LocalDateTime parse = LocalDateTime.parse(s, dtf);System.out.println(parse); // 2018-08-08T17:06:43}
}
8.4.5 Instant类
java.time
包通过值类型Instant提供机器视图,不提供人类意义上的时间单位。Instant类表示时间线上的一点,不需要任何上下文信息。例如,时区。从概念上讲,它只是表示自1970年1月1日0时0分0秒(UTC)开始地秒数。因为java.time
包是基于纳秒计算的,所以Instant类的精度可以达到纳秒级。Instant类的常见方法如下:
方法 | 说明 |
---|---|
static Instant now() | 静态方法,返回默认UTC时区的Instant类的对象 |
static Instant ofEpochMillo(long epochMilli) | 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象 |
static OffsetDateTime atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个OffsetDateTime |
long toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数,即时间戳 |
应用示例
import java.time.Instant;
import java.util.Date;public class InstantTest {public static void main(String[] args) {//1、创建一个Instant对象Instant now = Instant.now();System.out.println("now="+now); // now=2025-01-12T12:39:05.452Z//2、转换方法//[1]Instant->DateDate d = Date.from(now);System.out.println("d="+d); // d=Sun Jan 12 20:39:05 CST 2025//[2]Date->InstantInstant instant = d.toInstant();System.out.println("instant="+instant); // instant=2025-01-12T12:39:05.452Z}
}