【Java进阶篇】—— 常用类和基础API
创始人
2025-05-29 05:15:47
0

请添加图片描述

一、String类

1.1 String的特性

  • java.lang.String 类代表字符串,由final关键字修饰,在赋值后不能改变(常量),不能继承String
  • String 对象的字符内容是存储在一个字符数组 value[]中的

请添加图片描述

  • 我们来看一下StringJDK8中的源码:
public final class String implements java.io.Serializable, Comparable, CharSequence{private final char value[];private int hash;
}

private 代表外面无法直接获取字符数组,而且String也没有提供set/get方法
final 意味着字符数组的引用不可变

  • 所以String类代表着不可变的字符序列,一旦对字符串进行修改,就会产生新对象
  • Java 语言提供对字符串串联符号 (“+”) 以及将其他对象转换为字符串的方法(toString())
  • JDK9,底层只有一个byte类型的value数组
public final class String implements java.io.Serializable, Comparable, CharSequence { @Stableprivate final byte[] value;
}//官方说明:... that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.//细节:... The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

1.2 String的内存结构

  • String类型的字符串在初始化之后不可变,所以字符串由常量池来存储常量对象
  • JDK6中,字符串常量池在方法区;JDK7开始,就移到堆空间,直到目前JDK17

请添加图片描述

接下来我们将演示几种情况:【绘图以JDK6为例】

🌔 1、直接通过赋值创建的多个相同的字符串的引用,其实指向的是同一个常量池地址:

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0*/
public class StringLocation {public static void main(String[] args) {String s1 = "abc";String s2 = "abc";//在Java中两个String对象使用 == 比较,比较的是地址是否相同System.out.println(s1 == s2);//结果输出true}
}

请添加图片描述

  • 对于s1、s2来说,只是String类对象的两个引用
  • 如果修改了其中一个字符串,那么就会指向新的引用

请添加图片描述
🌔 2、通过new创建的字符串,会在堆中创建一个value数组,然后再指向常量池中的字符串

  • 我们可以思考一下 String s1 = “abc” 和 String s2 = new String(“abc”);的区别?

请添加图片描述

字符串常量存储在字符串常量池中,目的是共享;
然而通过new创建的字符串的对象存储在堆中,然后由堆中的字符串的value数组指向常量池中常量对象的value数组

  • 我们分别以两种不同的方式创建四个内容相同的字符串分析:
String s1 = "javaEE";
String s2 = "javaEE";
String s3 = new String("javaEE");
String s4 = new String("javaEE");System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false

请添加图片描述

我们通过new创建的字符串实际一共创建了两个对象:

一个在堆中、一个在常量池中

🌔 3、String 提供了intern() 方法,可以返回字符串再常量池中的引用

直接上案例分析:

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0*/
public class Test {public static void main(String[] args) {String s1 = "hello";String s2 = "world";String s3 = "hello" + "world";String s4 = s1 + "world";String s5 = s1 + s2;String s6 = (s1 + s2).intern();System.out.println(s3 == s4);//falseSystem.out.println(s3 == s5);//falseSystem.out.println(s4 == s5);//falseSystem.out.println(s3 == s6);//true}
}
  • 对于s1、s2、s3、s6都是字符串常量,s4、s5都是字符串变量
  • s1、s2、s3 在字符串常量池里面创建三个常量
  • 我们如何判断返回的是常量中的对象还是在堆中创建新对象呢?
    • 常量+常量:结果是常量池。且常量池中不会存在相同内容的常量
    • 常量与变量 或 变量与变量:结果在堆中
    • )拼接后调用intern方法:返回值在常量池中

🌔 4、我们可以用 concat 拼接字符串

  • concat方法拼接,哪怕是两个常量对象拼接,结果也是在堆。
public class TestString {public static void main(String[] args) {String str = "hello";String str2 = "world";String str3 ="helloworld";String str4 = "hello".concat("world");String str5 = "hello"+"world";System.out.println(str3 == str4);//falseSystem.out.println(str3 == str5);//true}
}

🌔 5、将String类型的变量传到一个函数,在这个函数中修改变量的值,但是实参的值并没有改变

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0*/
public class StringTest {String str = new String("good");char[] ch = { 't', 'e', 's', 't' };public void change(String str, char ch[]) {str = "test ok";ch[0] = 'b';System.out.println(str);}public static void main(String[] args) {StringTest ex = new StringTest();ex.change(ex.str, ex.ch);System.out.print(ex.str + " and ");System.out.println(ex.ch);}
}

在这里插入图片描述

  • 因为String在底层是一个字符数组常量,定义后就不能改变了
    • 我们传递到方法里面的字符串,是指向常量池里面字符串的一个引用
    • 在方法里修改了字符串,实际返回的是一个新的 str,所以后来我们再次调用我们的成员变量还是原来的值

在这里插入图片描述

1.3 String的API-1

🌔 1、String类的构造器

  • public String(): 初始化新创建的 String 对象,以使其表示空字符序列
  • String (String original): 初始化一个新创建的String对象,以我们传入的字符串为副本
  • public String(char [] value):通过传入的字符数组构造新的String对象
  • public String(char [] value, int offset, int count):通过字符数组的一部分构造新的String对象【offset是字符数组第一个索引,count是子序列长度】
  • public String(byte [] bytes):通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String
  • public String(byte [] bytes, String charsetName)::通过使用指定的字符集解码当前参数中的字节数组来构造新的String【charsetName是我们指定的字符集】

代码举例:

package com.zwh.shangguigu.commonclassandapi;import java.io.UnsupportedEncodingException;/*** @author Bonbons* @version 1.0* 利用String提供的各种构造器创建String的实例*/
public class CreateStringTest {public static void main(String[] args) throws UnsupportedEncodingException {//1、根据无参构造方法创建空字符串String s1 = new String();//2、有参构造方法String s2 = new String("abc");//创建字符数组和字节数组char [] ch = {'a', 'n', 'z'};byte [] bt = {98, 97, 99}; //数字对应ASCII码的字母//3、直接根据字符数组创建字符串String s3 = new String(ch);//4、选取字符数组的一部分创建字符串String s4 = new String(ch, 1, 2);//5、根据字节数组创建字符串String s5 = new String(bt);//6、根据字节数组选用我们指定的字符集String s6 = new String(bt, "GBK");//7、最朴素的方式String s7 = "zbc";//打印我们创建的字符串System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println(s5);System.out.println(s6);System.out.println(s7);//也可以使用copyValueOf拷贝数组String s8 = String.copyValueOf(ch);String s9 = String.copyValueOf(ch, 1, 2);//还可以使用valueOf将其他类型的数据转换成String类型int num = 520;String s10 = String.valueOf(num);System.out.println(s8);System.out.println(s9);System.out.println(s10);}
}

🌔 2、String与其他结构间的转换

字符串 --> 基本数据类型、包装类:

  • Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。

基本数据类型、包装类 --> 字符串:

  • 调用String类的public String valueOf(int n)可将int型转换为字符串
  • 相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换。

字符数组 --> 字符串:

  • String 类的构造器:String(char[]) 和 String(char[],int offset,int length) 分别用字符数组中的全部字符和部分字符创建字符串对象。
    字符串 --> 字符数组:

  • public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。

  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。

字符串 --> 字节数组:(编码)

  • public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName) :使用指定的字符集将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。

字节数组 --> 字符串:(解码)

  • String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
  • String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置offset开始取length个字节构造一个字符串对象。
  • String(byte[], String charsetName ) 或 new String(byte[], int, int,String charsetName ):解码,按照指定的编码方式进行解码。
@Test
public void test01() throws Exception {String str = "中国";System.out.println(str.getBytes("ISO8859-1").length);// 2// ISO8859-1把所有的字符都当做一个byte处理,处理不了多个字节System.out.println(str.getBytes("GBK").length);// 4 每一个中文都是对应2个字节System.out.println(str.getBytes("UTF-8").length);// 6 常规的中文都是3个字节/** 不乱码:(1)保证编码与解码的字符集名称一样(2)不缺字节*/System.out.println(new String(str.getBytes("ISO8859-1"), "ISO8859-1"));// 乱码System.out.println(new String(str.getBytes("GBK"), "GBK"));// 中国System.out.println(new String(str.getBytes("UTF-8"), "UTF-8"));// 中国
}

1.4 String的常用API-2

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写

🌔 1、常用方法

  • boolean isEMpty(): 字符串是否为空
  • int length(): 返回字符串的长度
  • String concat(String str): 字符串拼接
  • boolean equals(Object obj):比较字符串内容是否相同,区分大小写
  • int compareTo(String other):根据Unicode编码值比较字符串大小,区分大小写
  • int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
  • String toLowerCase(): 将字符串中的大写字母转为小写
  • String toUpperCase(): 将字符串中的小写字母转为大写
  • String trim(): 去掉字符串前后空白符
  • public String intern():结果在常量池中共享

🌔 2、查找

  • boolean contains(String xx): 是否包含字符串xx
  • int indexOf(xx): 从前向后找xx,返回第一次出现的下标,不存在则返回-1
  • int indexOf(String str, int fromIndex): 从指定的索引开始向后查找,返回第一次出现str的索引,没有则返回-1
  • int lastIndexOf(xx):从后向前找字符串xx,如果有则返回最后一次出现xx的索引,如果没有则返回-1
  • int lastIndexOf(String str, int fromIndex):从指定的索引开始反向搜索,返回str最后一次出现的索引,没有则返回-1
String s = "woaoniwa";
System.out.println(s.contains("ao"));
System.out.println(s.indexOf("w"));
System.out.println(s.lastIndexOf("w"));
System.out.println(s.indexOf("w", 1));
System.out.println(s.lastIndexOf("w", 5));

🌔 3、字符串截取

  • String substring(int beginIndex):从我们指定的索引开始到字符串末尾,截取出一个新的字符串
  • String substring(int beginIndex, int endIndex):从[beginIndex,endIndex)【前闭后开】截取出一个字符串
@Test
public void test01(){String str = "helloworldjavaatguigu";String sub1 = str.substring(5);String sub2 = str.substring(5,10);System.out.println(sub1);System.out.println(sub2);
}@Test
public void test02(){String fileName = "快速学习Java的秘诀.dat";//截取文件名System.out.println("文件名:" + fileName.substring(0,fileName.lastIndexOf(".")));//截取后缀名System.out.println("后缀名:" + fileName.substring(fileName.lastIndexOf(".")));
}

🌔 4、与字符或字符数组相关的方法

  • char charAt(int index): 返回index(索引)位置的字符
  • char [] toCharArray(): 将此字符串转换为一个新的字符数组返回
  • static String valueOf(char [] data, int offset, int count)::在data数组中从offset位置开始截取出长度为count的字符串
  • static String valueOf(char [] data, int offset):从offset起到字符数组末尾生成一个字符串返回
  • static String copyValueOf(char [] data):以字符数组为副本拷贝出一个字符串返回
  • static String copyValueOf(char [] data, int offset, int count):从offset开始,拷贝count这么长的字符数组生成字符串

🌔 5、与开头和结尾相关的String类的方法

  • boolean startsWith(xx): 测试此字符串是否以指定的字符前缀开始
  • boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定的前缀开始
  • boolean endsWith(xx): 测试此字符串是否以指定的后缀结束
String file = "HelloWorld.java";
System.out.println(file.startsWith("He"));
System.out.println(file.startsWith("He", 3));
System.out.println(file.endsWith(".java"));

🌔 6、替换相关的方法

  • String replace(char oldChar, char new Char):返回一个新的字符串,将其中的所有oldChar字符全部替换为newChar,不支持正则
  • String replace(CharSequence tatget, CharSequnce replacement):使用指定的组面值替换序列替换此字符串所有匹配字面值目标序列的子字符串
  • String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串
  • String replaceFirst(String regex, String replacement): 使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串

1.5 常见的算法题目

🌔 1、模拟 trim方法,去除字符串两端的空格

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0* 模拟trim方法*/
public class TrimTest {public static void main(String[] args) {String s = " abc a";String res = trim(s);System.out.println("去除首尾空格的结果为: " + res);}public static String trim(String s){int start = 0, end = s.length() - 1;//从头开始遇到空格就跳过while(start < end && s.charAt(start) == ' '){start++;}//从后向前遍历,找到第一个非空格的位置while(start < end && s.charAt(end) == ' '){end--;}return start == end ? "" : s.substring(start, end + 1); //因为不包含右边界}
}

🌔 2、翻转字符串指定范围的字符

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0* 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”*/
public class ReverseTest {public static void main(String[] args) {String s = "abcdefg";String res = reverse(s, 2, 5);System.out.println("将索引2-5翻转后的字符串为: " + res);}public static String reverse(String s, int start, int end){StringBuilder sb = new StringBuilder();//直接截取成三段,中间的一段进行翻转sb.append(s.substring(0, start));for(int i = end; i >= start; i--){sb.append(s.charAt(i));}sb.append(s.substring(end + 1));//返回结果字符串return sb.toString();}
}

🌔 3、获取一个字符串在另一个字符串中出现的次数。比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数

package com.zwh.shangguigu.commonclassandapi;/*** @author Bonbons* @version 1.0* 获取一个字符串在另一个字符串中出现的次数。* 比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数*/
public class StringNumber {public static void main(String[] args) {String p = "ab";String t = "abkkcadkabkebfkabkskab";System.out.println(p + "在" + t + "中出现的次数为: " + num(p, t));}public static int num(String p, String t){int count = 0;int index = 0;while(t.indexOf(p, index) != -1){count++;index += p.length();}return count;}
}

🌔 4、获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm”
提示:将短的那个串进行长度依次递减的子串与较长的串比较。

	// 第4题// 如果只存在一个最大长度的相同子串public String getMaxSameSubString(String str1, String str2) {if (str1 != null && str2 != null) {String maxStr = (str1.length() > str2.length()) ? str1 : str2;String minStr = (str1.length() > str2.length()) ? str2 : str1;int len = minStr.length();for (int i = 0; i < len; i++) {// 0 1 2 3 4 此层循环决定要去几个字符for (int x = 0, y = len - i; y <= len; x++, y++) {if (maxStr.contains(minStr.substring(x, y))) {return minStr.substring(x, y);}}}}return null;}// 如果存在多个长度相同的最大相同子串// 此时先返回String[],后面可以用集合中的ArrayList替换,较方便public String[] getMaxSameSubString1(String str1, String str2) {if (str1 != null && str2 != null) {StringBuffer sBuffer = new StringBuffer();String maxString = (str1.length() > str2.length()) ? str1 : str2;String minString = (str1.length() > str2.length()) ? str2 : str1;int len = minString.length();for (int i = 0; i < len; i++) {for (int x = 0, y = len - i; y <= len; x++, y++) {String subString = minString.substring(x, y);if (maxString.contains(subString)) {sBuffer.append(subString + ",");}}System.out.println(sBuffer);if (sBuffer.length() != 0) {break;}}String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");return split;}return null;}// 如果存在多个长度相同的最大相同子串:使用ArrayList
//	public List getMaxSameSubString1(String str1, String str2) {
//		if (str1 != null && str2 != null) {
//			List list = new ArrayList();
//			String maxString = (str1.length() > str2.length()) ? str1 : str2;
//			String minString = (str1.length() > str2.length()) ? str2 : str1;
//
//			int len = minString.length();
//			for (int i = 0; i < len; i++) {
//				for (int x = 0, y = len - i; y <= len; x++, y++) {
//					String subString = minString.substring(x, y);
//					if (maxString.contains(subString)) {
//						list.add(subString);
//					}
//				}
//				if (list.size() != 0) {
//					break;
//				}
//			}
//			return list;
//		}
//
//		return null;
//	}@Testpublic void testGetMaxSameSubString() {String str1 = "abcwerthelloyuiodef";String str2 = "cvhellobnmiodef";String[] strs = getMaxSameSubString1(str1, str2);System.out.println(Arrays.toString(strs));}

🌔 5、对字符串中字符进行自然顺序排序

	public void testSort() {String str = "abcwerthelloyuiodef";char[] arr = str.toCharArray();Arrays.sort(arr);String newStr = new String(arr);System.out.println(newStr);}

二、StringBuffer、StringBuilder类

  • String对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作效率较低、空间消耗也比较高

    • 所以,JDK又在 java.lang 包提供了可变字符序列StringBuilder和StringBuffer类型
  • 我们如何区分String、StringBuffer、StringBuilder呢?

    • String:不可变的字符序列; 底层使用char[]数组存储(JDK8.0中)
    • StringBuffer:可变的字符序列;线程安全(方法有synchronized修饰),效率低;底层使用char[]数组存储 (JDK8.0中)
    • StringBuilder:可变的字符序列; jdk1.5引入,线程不安全的,效率高;底层使用char[]数组存储(JDK8.0中)

🌔 1、介绍一下这两个类的常用API

  • StringBuffer append(xx): 用于字符串的拼接
  • StringBuffer delete(int start, int end): 删除[start, end) 之间的字符
  • StringBuffer deleteCharAt(int index): 删除索引为index处的字符
  • StringBuffer replace(int start, int end, String str): 替换[start,end) 范围的字符序列为str
  • void setCharAt(int index, char c): 替换索引为 index 位置的字符
  • char charAt(int index): 查找索引为index位置的字符
  • StringBuffer insert(int index, xx): 在索引为index的位置插入xx
  • int length(): 返回字符串的长度
  • StringBuffer reverse(): 反转字符串

🌔 2、一些其他API

  • int indexOf(String str):获取str在字符串中第一次出现的索引,没有则返回-1
  • int indexOf(String str, int fromIndex): 从指定索引开始,从左向右查找str返回第一次出现的索引位置,没有返回-1
  • int lastIndexOf(String str): 从后向前查找最后一次出现str的索引位置,没有则返回-1
  • int lastIndexOf(String str, int fromIndex):从指定索引位置向前查找str,返回第一次出现的位置,没有则返回-1
  • String substring(int start):从start索引到最后截取字符串
  • String substring(int start, int end): 截取[start, end) 左闭右开】的字符串
  • String toString(): 返回此序列中数据的字符串表示形式
  • void setLength(int newLength): 设置当前字符序列长度为 newLength

我们可以分析一下下面的这段代码会输出什么?
在这里插入图片描述

  • 使用append拼接的时候,只是将 null 当做一个普通的字符串拼接到sb上 >> 所以,sb = “null”、长度为4
  • 然而将null作为参数传递给StringBuffer的构造器时,会抛出空指针异常

三、JDK8之前:日期时间API

java.lang.System类的方法

  • System 类提供的 public static long currentTimeMillis():
    • 用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
    • 此方法适用于时间差计算

java.util.Date 表示特定的瞬间,可以精确到毫秒

  • Date类提供两个常用构造器:
    • Date(): 使用无参构造器创建的对象可以获取本地当前时间
    • Date(long 毫秒数): 把该毫秒值换算成日期的时间对象.
  • 常用方法:
    • getTime(): 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
    • toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 【星期几 月 日 时分秒 时间标准 年】
package com.zwh.shangguigu.commonclassandapi;import java.util.Date;/*** @author Bonbons* @version 1.0*/
public class DateTest {public static void main(String[] args) {//获取当前的系统时间Date d = new Date();System.out.println(d);//以毫秒数显示当前距1970-1-1的时间long time = System.currentTimeMillis();System.out.println(time);//Date类的getTime方法和System的currentTimeMillis效果相同System.out.println(d.getTime());//定义一个毫秒数long time2 = Long.MAX_VALUE;//将毫秒换成日期时间的对象Date d2 = new Date(time2);System.out.println(d2);}
}

java.text.SimpleDateFormat是一个与语言环境无关的方式来格式化和解析日期的具体类

  • 可以完成日期到文本的格式化:

    • public String format(Date date): 格式化时间对象date
  • 可以完成文本到日期的解析:

    • public Date parse(String source): 从给定的字符串开始解析文本以生成一个日期
  • SimpleDateFormat有两种创建的构造器:

    • SimpleDateFormat(): 默认的模式和语言环境创建对象
    • public SimpleDateFormat(String pattern): 用指定的格式创建一个对象

请添加图片描述

package com.zwh.shangguigu.commonclassandapi;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @author Bonbons* @version 1.0*/
public class SimpleDateFormatTest {public static void main(String[] args) {Date d = new Date();//先输出看一下最开始日期的格式System.out.println(d);//创建我们常见的时间格式的时间格式化对象[E代表星期几、Z代表时区]SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒" +" SSS毫秒 E Z");//格式化日期获得文本字符串String str = df.format(d);System.out.println("格式化后的日期: " + str);//创建一个和时间相关的文本串String str2 = "2022年02月22日 22时22分22秒 22毫秒 星期二 +0800";//利用上面的格式化对象,解析文本串到时间try{Date d2 = df.parse(str2);System.out.println(d2);}catch (ParseException e){e.printStackTrace();}}
}

在这里插入图片描述

java.util.Calendar(日历),是一个抽象类,主要用于完成日期字段之间相互操作的功能,Date类废弃了大部分的API被Calendar替代

  • 如何获取Calendar的实例?

    • 我们可以通过 Calendar.getInstance() 方法获取实例
      请添加图片描述
    • 也可以调用它的子类 GregorianCalendar(公历)的构造器
      请添加图片描述
  • 一个Calendar的实例是系统时间的抽象表示,可以修改或获取 YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、MINUTE、SECOND等 日历字段对应的时间值。

    • public int get(int field):返回给定日历字段的值
    • public void set(int field,int value) :将给定的日历字段设置为指定的值
    • public void add(int field,int amount):根据日历的规则,为给定的日历字段添加或者减去指定的时间量
    • public final Date getTime():将Calendar转成Date对象
    • public final void setTime(Date date):使用指定的Date对象重置Calendar的时间
  • 介绍其中一些我们常用的字段:【月份是从0-11星期是从1-7(星期日到星期六)】
    请添加图片描述

  • 示例代码:

package com.zwh.shangguigu.commonclassandapi;import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;/*** @author Bonbons* @version 1.0*/
public class CalendarTest {public static void main(String[] args) {test1();test2();test3();}//直接通过getInstance获取默认的Calendar的实例public static void test1(){//获取Calendar的实例Calendar c = Calendar.getInstance();System.out.println(c);//接下来我们获取一些特定的信息int year = c.get(Calendar.YEAR);int month = c.get(Calendar.MONTH) + 1;int day = c.get(Calendar.DATE);int hour = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);System.out.println(year + "-" + month + "-" + day + "-" + hour + "-" + minute);}//指定时区public static void test2(){TimeZone t= TimeZone.getTimeZone("America/Los_Angeles");Calendar c = Calendar.getInstance(t);int year = c.get(Calendar.YEAR);int month = c.get(Calendar.MONTH)+1;int day = c.get(Calendar.DATE);int hour = c.get(Calendar.HOUR_OF_DAY);int minute = c.get(Calendar.MINUTE);System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute);}//public static void test3(){Calendar calendar = Calendar.getInstance();//从Calendar对象中获得Date对象Date date = calendar.getTime();//使用Date设置Calendar的时间date = new Date(234234235235L);calendar.setTime(date);calendar.set(Calendar.DAY_OF_MONTH, 8);System.out.println("当前时间日设置为8后,时间是:" + calendar.getTime());calendar.add(Calendar.HOUR, 2);System.out.println("当前时间加2小时后,时间是:" + calendar.getTime());calendar.add(Calendar.MONTH, -2);System.out.println("当前日期减2个月后,时间是:" + calendar.getTime());}
}
  • 练习:输入年份和月份,输出该月日历。闰年计算公式:年份可以被4整除但不能被100整除,或者可以被400整除。
package com.unit2.test;
import java.util.Scanner;
/** 输入年月,将输出出日历表(从1900.1.1开始计算总天数)*/
public class Calendar {public static void main(String[] args) {Scanner in=new Scanner(System.in);System.out.println("请输入年份:");int year=in.nextInt();System.out.println("请输入月份:");int month=in.nextInt();int sum=0;//按年计算1900.1.1到输入年份的1.1一共有多少天(分闰年和平年)for(int i=1900;iif(i%4==0&&i%100!=0||i%400==0) {sum+=366;}else {sum+=365;}}//按月计算今年的1.1号到输入月份的1号一共有多少天//二月分闰年(29)和平年(28),大月31天,小月30天for(int j=1;jif(j==2) {if(year%4==0&&year%100!=0||year%400==0){sum+=29;}else {sum+=28;}}else {if(j==4||j==6||j==9||j==11){sum+=30;}else {sum+=31;}}}sum+=1;int wekday=sum%7;System.out.println("日\t一\t二\t三\t四\t五\t六");for(int i=1;i<=wekday;i++){System.out.print("\t");}for(int i=1;i<=30;i++) {if(sum%7==6) {System.out.print(i+"\n");}else {System.out.print(i+"\t");}sum++;}}}

四、JDK8:新的时间日期API

  • Java 8 以一个新的开始为 Java 创建优秀的 API。新的日期时间API包含:
    • java.time – 包含值对象的基础包
    • java.time.chrono – 提供对不同的日历系统的访问
    • java.time.format – 格式化和解析时间和日期
    • java.time.temporal – 包括底层框架和扩展特性
    • java.time.zone – 包含时区支持的类

🌔 1、本地日期时间:LocalDate、LocalTime、LocalDateTime

在这里插入图片描述

  • 通过代码演示方法的使用:
package com.zwh.shangguigu.commonclassandapi;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;/*** @author Bonbons* @version 1.0*/
public class LocalDateTimeTest  {public static void main(String[] args) {//创建三种本地日期的对象LocalDate now1 = LocalDate.now();LocalTime now2 = LocalTime.now();LocalDateTime now3 = LocalDateTime.now();//输出System.out.println(now1);//年月日System.out.println(now2);//时分秒System.out.println(now3);//年月日 时分秒//用指定的日期/时间创建对象LocalDate lai = LocalDate.of(2022, 5, 13);//输出时间、是一年中的第几天System.out.println(lai);System.out.println(lai.getDayOfYear());//日期计算LocalDate go = lai.plusDays(7);LocalDate before = lai.minusDays(3);System.out.println(go + " " + before);}
}

在这里插入图片描述

🌔 2、瞬时:Instant

  • Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
    • 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
  • java.time.Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。

在这里插入图片描述
请添加图片描述

整个地球分为二十四时区,每个时区都有自己的本地时间。北京时区是东八区,领先UTC八个小时,在电子邮件信头的Date域记为+0800。如果在电子邮件的信头中有这么一行:
Date: Fri, 08 Nov 2002 09:42:22 +0800
说明信件的发送地的地方时间是二○○二年十一月八号,星期五,早上九点四十二分(二十二秒),这个地方的本地时领先UTC八个小时(+0800, 就是东八区时间)。电子邮件信头的Date域使用二十四小时的时钟,而不使用AM和PM来标记上下午。

🌔 3、日期时间格式化:DateTimeFormatter

  • 有三种格式化方法:
    • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME、ISO_LOCAL_DATE、ISO_LOCAL_TIME
    • 本地化相关的格式。如:ofLocalizedDate(FormatStyle.LONG)
    • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
方法描述
ofPattern(String pattern)静态方法,返回一个指定字符串格式的DateTimeFormatter
format(TemporalAccessor t)格式化一个日期、时间,返回字符串
parse(CharSequence text)将指定格式的字符序列解析为一个日期、时间
  • 通过代码演示如何使用这几种方法:
package com.zwh.shangguigu.commonclassandapi;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;/*** @author Bonbons* @version 1.0*/
public class DatetimeFormatterTest {public static void main(String[] args) {test1();System.out.println();test2();System.out.println();test3();}public static void test1(){//采用预定义的标准格式创建日期时间格式化对象DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;//获取当前日期并格式化为字符串LocalDateTime localDateTime = LocalDateTime.now();String str1 = formatter.format(localDateTime);System.out.println(localDateTime + " " + str1);//将日期字符串解析成日期TemporalAccessor parse = formatter.parse("2023-05-20T20:37:08.460");LocalDateTime dateTime = LocalDateTime.from(parse);System.out.println(dateTime);}public static void test2(){//获取当前时间LocalDateTime localDateTime = LocalDateTime.now();//采用本地化相关的格式DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//格式化String str2 = formatter1.format(localDateTime);System.out.println(str2);//第二种本地化相关的格式DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);// 格式化String str3 = formatter2.format(LocalDate.now());System.out.println(str3);}public static void test3(){DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//格式化String str4 = dateTimeFormatter.format(LocalDateTime.now());System.out.println(str4);//解析TemporalAccessor accessor = dateTimeFormatter.parse("2022-02-22 22:22:22");LocalDateTime localDateTime = LocalDateTime.from(accessor);System.out.println(localDateTime);}
}

在这里插入图片描述

🌔 4、其他的几个API

(1)指定时区日期时间: Zondld 和 ZonedDateTime

  • ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris

  • ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12-03T10:15:30+01:00 Europe/Paris

    • 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等
    • 常见的时区ID:Asia/Shanghai , UTC , America/New_York
  • 可以通过Zondld 获取所有可用的时区ID:

package com.zwh.shangguigu.commonclassandapi;import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;/*** @author Bonbons* @version 1.0*/
public class ZoneTest {public static void main(String[] args) {//利用set集合存储一下所有可用的时区Set availableZoneIds = ZoneId.getAvailableZoneIds();//超级for循环打印一下这些IDfor(String availableZoneId : availableZoneIds){System.out.println(availableZoneId);}//获取当前时间 默认的是[Asia/Shanghai]ZonedDateTime t1 = ZonedDateTime.now();System.out.println(t1);ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));System.out.println(t2);}
}

(2)持续日期/时间:Period 和 Duration

  • Duration 持续时间:用于计算两个“时间”的间隔
  • Period 日期间隔:用于计算两个"日期"的间隔
package com.zwh.shangguigu.commonclassandapi;import javax.security.auth.callback.LanguageCallback;
import java.time.*;/*** @author Bonbons* @version 1.0*/
public class PeriodDurationTest {public static void main(String[] args) {test1();System.out.println();test2();System.out.println();test3();}public static void test1(){LocalDate t1 = LocalDate.now();LocalDate t2 = LocalDate.of(2090, 12, 31);Period between = Period.between(t1, t2);//相差P67Y9M16DSystem.out.println(between);System.out.println("相差的年数: " + between.getYears());System.out.println("相差的月数: " + between.getMonths());System.out.println("相差的天数: " + between.getDays());System.out.println("相差的总数(转化为月): " + between.toTotalMonths());}public static void test2(){LocalDateTime t1 = LocalDateTime.now();LocalDateTime t2 = LocalDateTime.of(2010, 8, 8, 0, 0, 0, 0);Duration between = Duration.between(t1, t2);System.out.println(between);System.out.println("相差的总天数:"+between.toDays());System.out.println("相差的总小时数:"+between.toHours());System.out.println("相差的总分钟数:"+between.toMinutes());System.out.println("相差的总秒数:"+between.getSeconds());System.out.println("相差的总毫秒数:"+between.toMillis());System.out.println("相差的总纳秒数:"+between.toNanos());System.out.println("不够一秒的纳秒数:"+between.getNano());}public static void test3(){//时分秒LocalTime localTime = LocalTime.now();LocalTime localTime1 = LocalTime.of(15, 24, 50);Duration duration = Duration.between(localTime1, localTime);System.out.println(duration);//秒和纳秒差距System.out.println(duration.getSeconds());System.out.println(duration.getNano());//年月日LocalDate localDate = LocalDate.now();LocalDate localDate1 = LocalDate.of(2023, 5, 21);Period period = Period.between(localDate1, localDate);System.out.println(period);System.out.println(period.getYears());System.out.println(period.getMonths());System.out.println(period.getDays());Period period1 = period.withYears(2);System.out.println(period1);}
}

在这里插入图片描述
在这里插入图片描述
(3)Clock:使用时区提供对当前即时、日期和时间的访问的时钟

(4)TemporalAdjuster : 时间校正器。有时我们可能需要获取。例如:将日期调整到“下一个工作日”等操作。
TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。

@Test
public void test1(){// TemporalAdjuster:时间校正器// 获取当前日期的下一个周日是哪天?TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);System.out.println(localDateTime);// 获取下一个工作日是哪天?LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {@Overridepublic Temporal adjustInto(Temporal temporal) {LocalDate date = (LocalDate) temporal;if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {return date.plusDays(3);} else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {return date.plusDays(2);} else {return date.plusDays(1);}}});System.out.println("下一个工作日是:" + localDate);}

(5)与传统日期处理的转换

在这里插入图片描述


五、Java比较器

  • 在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题

  • Java实现对象排序的方式有两种:

    • 自然排序: java.lang.Comparable
    • 定制排序:java.util.Comparator
  • 对于引用数据类型是不能直接使用比较运算符来比较大小的,那么如何解决这个问题呢?

    • boolean、char、byte、short、int、long、float 和 double为基本数据类型,其余的都是引用数据类型

1.1 自然排序:java.lang.Comparable

  • Comparable 接口强行对实现它的每个类的对象进行整体排序。【类的自然排序】
  • 实现Comparable 接口的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小
    • this > 形参对象,返回正整数
    • this < 形参对象,返回负整数
    • this = =形参对象, 返回零
package java.lang;public interface Comparable{int compareTo(Object obj);
}
  • 实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器
  • 对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致
  • Comparable 的典型实现:(默认都是从小到大排列的)
    • String:按照字符串中字符的Unicode值进行比较
    • Character:按照字符的Unicode值来进行比较
    • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
    • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    • Date、Time等:后面的日期时间比前面的日期时间大

以学生类为例,根据学号来比较学生对象的大小

package com.atguigu.api;public class Student implements Comparable {private int id;private String name;private int score;private int age;public Student(int id, String name, int score, int age) {this.id = id;this.name = name;this.score = score;this.age = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", score=" + score +", age=" + age +'}';}@Overridepublic int compareTo(Object o) {//这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性//默认按照学号比较大小Student stu = (Student) o;return this.id - stu.id;}
}

编写测试类:

package com.atguigu.api;public class TestStudent {public static void main(String[] args) {Student[] arr = new Student[5];arr[0] = new Student(3,"张三",90,23);arr[1] = new Student(1,"熊大",100,22);arr[2] = new Student(5,"王五",75,25);arr[3] = new Student(4,"李四",85,24);arr[4] = new Student(2,"熊二",85,18);//单独比较两个对象System.out.println(arr[0].compareTo(arr[1]));System.out.println(arr[1].compareTo(arr[2]));System.out.println(arr[2].compareTo(arr[2]));System.out.println("所有学生:");for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}System.out.println("按照学号排序:");for (int i = 1; i < arr.length; i++) {for (int j = 0; j < arr.length-i; j++) {if(arr[j].compareTo(arr[j+1])>0){Student temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}}
}

1.2 定制排序:java.util.Comparator

  • 既然有了实现Comparable接口重新compareTo的方式,为什么还需要定制排序呢?

    • 当元素类型没有实现Comparable接口又不方便修改代码
    • 或者实现了这个接口,但是想用其他方法实现比较
  • JDK 提供了 java.util.Comparator 接口,强行对多个对象进行整体排序的比较

    • 重写compare(Object o1, Object o2)方法来比较o1和o2的大小
      • 返回正整数表示 o1 > o2
      • 返回负整数表示 o1 < o2
      • 返回零表示 o1 == o2
    • 我们可以将Comparator 传递给 sort 方法(Arrays.sortCollection.sort),从而允许在排序顺序上实现精确控制
package jaa.util;
public Interface Comparator{int compare(Object o1, Object o2);
}

通过一个学生类的案例来分析这个接口以及排序如何"食用" ?

package com.atguigu.api;import java.util.Comparator;
//定义定制比较器类
public class StudentScoreComparator implements Comparator { @Overridepublic int compare(Object o1, Object o2) {Student s1 = (Student) o1;Student s2 = (Student) o2;int result = s1.getScore() - s2.getScore();return result != 0 ? result : s1.getId() - s2.getId();}
}
package com.atguigu.api;public class TestStudent {public static void main(String[] args) {Student[] arr = new Student[5];arr[0] = new Student(3, "张三", 90, 23);arr[1] = new Student(1, "熊大", 100, 22);arr[2] = new Student(5, "王五", 75, 25);arr[3] = new Student(4, "李四", 85, 24);arr[4] = new Student(2, "熊二", 85, 18);System.out.println("所有学生:");for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}System.out.println("按照成绩排序");StudentScoreComparator sc = new StudentScoreComparator();for (int i = 1; i < arr.length; i++) {for (int j = 0; j < arr.length - i; j++) {if (sc.compare(arr[j], arr[j + 1]) > 0) {Student temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}}
}
@Test
public void test01() {Student[] students = new Student[5];students[0] = new Student(3, "张三", 90, 23);students[1] = new Student(1, "熊大", 100, 22);students[2] = new Student(5, "王五", 75, 25);students[3] = new Student(4, "李四", 85, 24);students[4] = new Student(2, "熊二", 85, 18);System.out.println(Arrays.toString(students));//定制排序StudentScoreComparator sc = new StudentScoreComparator();Arrays.sort(students, sc);System.out.println("排序之后:");System.out.println(Arrays.toString(students));
}
Goods[] all = new Goods[4];
all[0] = new Goods("War and Peace", 100);
all[1] = new Goods("Childhood", 80);
all[2] = new Goods("Scarlet and Black", 140);
all[3] = new Goods("Notre Dame de Paris", 120);Arrays.sort(all, new Comparator() {@Overridepublic int compare(Object o1, Object o2) {Goods g1 = (Goods) o1;Goods g2 = (Goods) o2;return g1.getName().compareTo(g2.getName());}
});System.out.println(Arrays.toString(all));

六、系统相关类

1.1 java.lang.System 类

  • System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。

  • 由于该类的构造器是private的,所以无法创建该类的对象。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。

  • 成员变量 Scanner scan = new Scanner(System.in);

    • System类内部包含in、out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
  • 成员方法

    • native long currentTimeMillis():
      该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
    • void exit(int status):
      该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
    • void gc():
      该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
    • String getProperty(String key):
      该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:

请添加图片描述

import org.junit.Test;public class TestSystem {@Testpublic void test01(){long time = System.currentTimeMillis();System.out.println("现在的系统时间距离1970年1月1日凌晨:" + time + "毫秒");System.exit(0);System.out.println("over");//不会执行}@Testpublic void test02(){String javaVersion = System.getProperty("java.version");System.out.println("java的version:" + javaVersion);String javaHome = System.getProperty("java.home");System.out.println("java的home:" + javaHome);String osName = System.getProperty("os.name");System.out.println("os的name:" + osName);String osVersion = System.getProperty("os.version");System.out.println("os的version:" + osVersion);String userName = System.getProperty("user.name");System.out.println("user的name:" + userName);String userHome = System.getProperty("user.home");System.out.println("user的home:" + userHome);String userDir = System.getProperty("user.dir");System.out.println("user的dir:" + userDir);}@Testpublic void test03() throws InterruptedException {for (int i=1; i <=10; i++){MyDemo my = new MyDemo(i);//每一次循环my就会指向新的对象,那么上次的对象就没有变量引用它了,就成垃圾对象}//为了看到垃圾回收器工作,我要加下面的代码,让main方法不那么快结束,因为main结束就会导致JVM退出,GC也会跟着结束。System.gc();//如果不调用这句代码,GC可能不工作,因为当前内存很充足,GC就觉得不着急回收垃圾对象。//调用这句代码,会让GC尽快来工作。Thread.sleep(5000);}
}class MyDemo{private int value;public MyDemo(int value) {this.value = value;}@Overridepublic String toString() {return "MyDemo{" + "value=" + value + '}';}//重写finalize方法,让大家看一下它的调用效果@Overrideprotected void finalize() throws Throwable {
//        正常重写,这里是编写清理系统内存的代码
//        这里写输出语句是为了看到finalize()方法被调用的效果System.out.println(this+ "轻轻的我走了,不带走一段代码....");}
}

static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。常用于数组的插入和删除

import org.junit.Test;import java.util.Arrays;public class TestSystemArrayCopy {@Testpublic void test01(){int[] arr1 = {1,2,3,4,5};int[] arr2 = new int[10];System.arraycopy(arr1,0,arr2,3,arr1.length);System.out.println(Arrays.toString(arr1));System.out.println(Arrays.toString(arr2));}@Testpublic void test02(){int[] arr = {1,2,3,4,5};System.arraycopy(arr,0,arr,1,arr.length-1);System.out.println(Arrays.toString(arr));}@Testpublic void test03(){int[] arr = {1,2,3,4,5};System.arraycopy(arr,1,arr,0,arr.length-1);System.out.println(Arrays.toString(arr));}
}

1.2 java.lang.Runtime类

  • 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。

  • public static Runtime getRuntime(): 返回与当前 Java 应用程序相关的运行时对象。应用程序不能创建自己的 Runtime 类实例。

  • public long totalMemory():返回 Java 虚拟机中初始化时的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境。默认为物理电脑内存的1/64。

  • public long maxMemory():返回 Java 虚拟机中最大程度能使用的内存总量。默认为物理电脑内存的1/4。

  • public long freeMemory():回 Java 虚拟机中的空闲内存量。调用 gc 方法可能导致 freeMemory 返回值的增加。

package com.atguigu.system;public class TestRuntime {public static void main(String[] args) {Runtime runtime = Runtime.getRuntime();long initialMemory = runtime.totalMemory(); //获取虚拟机初始化时堆内存总量long maxMemory = runtime.maxMemory(); //获取虚拟机最大堆内存总量String str = "";//模拟占用内存for (int i = 0; i < 10000; i++) {str += i;}long freeMemory = runtime.freeMemory(); //获取空闲堆内存总量System.out.println("总内存:" + initialMemory / 1024 / 1024 * 64 + "MB");System.out.println("总内存:" + maxMemory / 1024 / 1024 * 4 + "MB");System.out.println("空闲内存:" + freeMemory / 1024 / 1024 + "MB") ;System.out.println("已用内存:" + (initialMemory-freeMemory) / 1024 / 1024 + "MB");}
}

七、和数学相关的类

1.1 java.lang.Math

java.lang.Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单

  • 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 double max(double x, double y):返回x,y中的最大值
  • public static double min(double x, double y):返回x,y中的最小值
    其它:acos,asin,atan,cos,sin,tan 三角函数

1.2 java.math

(1) BigInteger

  • Integer类作为int的包装类,能存储的最大整型值为231-1,Long类也是有限的,最大为263-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。

  • java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。

  • 构造器

    • BigInteger(String val):根据字符串构建BigInteger对象
      方法
  • public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。

  • BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger

  • BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger

  • BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger

  • BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。

  • BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。

  • BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。

  • BigInteger pow(int exponent) :返回其值为 (this^exponent) 的 BigInteger。

@Test
public void test01(){//long bigNum = 123456789123456789123456789L;BigInteger b1 = new BigInteger("12345678912345678912345678");BigInteger b2 = new BigInteger("78923456789123456789123456789");//System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和System.out.println("和:" + b1.add(b2));System.out.println("减:" + b1.subtract(b2));System.out.println("乘:" + b1.multiply(b2));System.out.println("除:" + b2.divide(b1));System.out.println("余:" + b2.remainder(b1));
}

(2) BigDecimal

  • 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。

  • BigDecimal类支持不可变的、任意精度的有符号十进制定点数。

  • 构造器

    • public BigDecimal(double val)
    • public BigDecimal(String val) --> 推荐
  • 常用方法

    • public BigDecimal add(BigDecimal augend)
    • public BigDecimal subtract(BigDecimal subtrahend)
    • public BigDecimal multiply(BigDecimal multiplicand)
    • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode):divisor是除数,scale指明保留几位小数,roundingMode指明舍入模式(ROUND_UP :向上加1、ROUND_DOWN :直接舍去、ROUND_HALF_UP:四舍五入)
@Test
public void test03(){BigInteger bi = new BigInteger("12433241123");BigDecimal bd = new BigDecimal("12435.351");BigDecimal bd2 = new BigDecimal("11");System.out.println(bi);// System.out.println(bd.divide(bd2));System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}

(3) java.util.Random

  • 用于产生随机数
    • boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 boolean 值。
    • void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
    • ouble nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 double 值。
    • float nextFloat():返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 float 值。
    • double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0。
    • int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
    • int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
    • long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
@Test
public void test04(){Random r = new Random();System.out.println("随机整数:" + r.nextInt());System.out.println("随机小数:" + r.nextDouble());System.out.println("随机布尔值:" + r.nextBoolean());
}

相关内容

热门资讯

爱的教育作文 爱的教育作文爱的教育看到这个书名,我不禁开始思考一个问题:在这个缤纷多彩的世界里,爱究竟是什么含义?...
梁衡《把栏杆拍遍》读书笔记 梁衡《把栏杆拍遍》读书笔记梁衡《把栏杆拍遍》读书笔记这是一篇写得很美的散文,有以下特点:一、联想丰富...
【每日一题Day150】LC1... 分割两个字符串得到回文串【LC1616】 给你两个字符串 a 和 b ,它们长度相同...
一年级春游日记 一年级春游日记一年级春游日记1  今天是春游,我作天就去买许多零食和矿泉水,打算在春游的时候干掉,我...
课外读书笔记摘抄 课外读书笔记摘抄(精选12篇)  导语:舍弃就是这样,它也许出于无奈,可在无奈之后是另一份希望,它也...
蚂蚁观察日记 【热门】蚂蚁观察日记4篇蚂蚁观察日记 篇1  我家有一个后院,我经常到后院去观察那些鹭绿上得小精灵—...
ImageView(图像视图) 本节介绍的UI基础控件是:ImageView(图像视图),就是用来显示图像的一个View或者说控件!...
关于接口测试——自动化框架的设... 一、自动化测试框架 在大部分测试人员眼中只要沾上“框架”,就感觉非常神秘,...
【2023.3.8】数据结构复... 【2023.3.8】数据结构复习笔记 文章目录【2023.3.8】数据结构复习笔记序言一、绪论二、线...
数学周记 【精华】数学周记范文(通用20篇)  不经意间,一个星期已经结束了,想必有很多难忘的瞬间吧,是时候仔...
男生贾里全传读书笔记 男生贾里全传读书笔记(通用24篇)  当品读完一部作品后,相信大家一定领会了不少东西,不能光会读哦,...
1.计算机网络和因特网 1.因特网的描述1.1 具体构成描述根据底层实现(硬件软件)端系统(主机...
使用YOLO部署哨岗相机 流程 一.模型选取 将YOLO和Faster RCNN进行搭配,通过多次实验ÿ...
大蒜观察日记 大蒜观察日记3篇  【导语】大蒜虽然是一种很不起眼的植物,但是它的生命力很强,无论在任何的环境下都可...
四年级观察植物的日记 四年级观察植物的日记范文  观察植物的日记需要怎么写呢?同学们是否有观察过植物的生长过程呢?不妨写下...
同一片天空共眠,同一个梦想奋斗... 同一片天空共眠,同一个梦想奋斗《大抠车始歌》(1) Eng...
Vue 3.0 Data选项 #概览 非兼容:data 组件选项声明不再接收纯 JavaScript object...
Java中原子操作的实现原理 Java中原子操作的实现原理1. 什么是原子操作2. 处理器如何是实现操作的原子性2.1 使用总线锁...
春节的街头小学日记 春节的街头小学日记  今天是大年初一,天气晴朗,妈妈带着我一早来到了兴宁路。  街上可热闹了,车水马...
通用实习日记 通用实习日记集合10篇通用实习日记 篇1  4 月18 日  今天是为期三周实习的第一天,心情有点紧...