完成目标:
学习java下半段课程
知识点:
1.经典接口
基本数据类型的数据(除boolean类型外)需要比较大小使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。
Java给所有引用数据类型的大小比较,指定了一个标准接口:java.lang.Comparable接口
需要比较大小的类实现java.lang.Comparable接口
重写compareTo方法,定义比较规则
package java.lang;
public interface Comparable{
int compareTo(Object obj);
}
知识点 |
核心内容 |
重点 |
Comparable接口 |
通过实现compareTo(Object o)方法定义对象自然排序规则; this对象与参数对象比较 |
1. 返回值规则:this-参数>0返回正整数(当前对象大); 2. 必须强制类型转换参数对象 |
Comparator接口 |
通过compare(Object o1, Object o2)方法定义灵活比较规则; 独立于比较类的外部比较器 |
1. 双参数比较:o1-o2>0返回正整数(o1大); 2. 两个参数都需要强制类型转换 |
比较场景 |
1. 引用数据类型排序; 2. 集合框架中的排序操作 |
易混淆: - Comparable是类内部实现; - Comparator是外部比较器类 |
冒泡排序应用 |
通过比较器返回值控制排序方向; students[i].compareTo(students[i+1])>0时交换位置 |
关键代码: return this.getScore()-((Student)o).getScore() |
返回值语义 |
>0:前者大于后者; <0:前者小于后者; =0:两者相等 |
易错点: 比较对象属性时忘记类型转换 |
典型应用场景 |
1. 学生成绩排序; 2. 商品价格排序; 3. 日期对象比较 |
重点: 两种接口的实现方式差异 |
2.String
知识点 |
核心内容 |
重点 |
String类概述 |
Java中所有双引号字符串字面值均为String类的实例(对象),可直接创建无需new |
字符串字面值本质是对象,但语法简化 |
String不可变性 |
字符串创建后值不可更改(底层为final修饰的数组),拼接操作会生成新对象 |
s += "world"实际产生新对象,原字符串不变 |
字符串共享机制 |
相同字面值的字符串对象可共享(如s1="ABC"和s2="ABC"指向同一内存) |
==比较地址值,equals()比较内容 |
底层实现演变 |
JDK8:final char[]; JDK9+:final byte[](节省内存空间) |
数组地址被final固定导致字符串不可变 |
String vs StringBuilder |
String适用于常量字符串;StringBuilder适用于频繁修改的字符串 |
面试高频:内存效率与操作性能对比 |
隐含面试题 |
1. String s = "a" + "b"编译期优化机制; 2. 字符串常量池与堆内存关系 |
编译优化与运行时内存分配差异 |
3.String的创建
public class Demo02String {
public static void main(String[] args) {
//1.String() -> 利用String的无参构造创建String对象
String s1 = new String(); //
System.out.println(s1);
//2.String(String original) -> 根据字符串创建String对象
String s2 = new String("abc");
System.out.println(s2);
//3.String(char[] value) -> 根据char数组创建String对象
char[] chars = {'a','b','c'};
String s3 = new String(chars);
System.out.println(s3);
/*
4.String(byte[] bytes) -> 通过使用平台的默认字符集解码指定的 byte 数组,
构造一个新的 String
*/
byte[] bytes1 = {97,98,99};
String s4 = new String(bytes1);
System.out.println(s4);
byte[] bytes2 = {-97,-98,-99};
String s5 = new String(bytes2);
System.out.println(s5);
byte[] bytes3 = {-28,-67,-96};
String s6 = new String(bytes3);
System.out.println(s6);
//5.简化形式
String s7 = "abc";
System.out.println(s7);
}
}
1.String(char[] value, int offset, int count)->将char数组的一部分转成String对象
value:要转String的char数组
offset:从数组的哪个索引开始转
count:转多少个
2.String(byte[] bytes, int offset, int length)->将byte数组的一部分转成String对象
bytes:要转String的byte数组
offset:从数组的哪个索引开始转
length:转多少个
public class Demo03String {
public static void main(String[] args) {
/* 1.String(char[] value, int offset, int count)->将char数组的一部分转成String对象
value:要转String的char数组
offset:从数组的哪个索引开始转
count:转多少个*/
char[] chars = {'a','b','c','d','e','f'};
String s1 = new String(chars,1,3);
System.out.println(s1);
/* 2.String(byte[] bytes, int offset, int length)->将byte数组的一部分转成String对象
bytes:要转String的byte数组
offset:从数组的哪个索引开始转
length:转多少个*/
byte[] bytes = {97,98,99,100,101};
String s2 = new String(bytes,0,2);
System.out.println(s2);
}
}
知识点 |
核心内容 |
重点 |
String构造方法 |
通过无参构造、字符串直接赋值、char数组、byte数组等方式创建String对象 |
无参构造创建空字符串 vs 直接赋值空字符串"" |
char数组构造 |
new String(char[] chars) 将整个char数组转为字符串 |
数组索引从0开始,需注意越界问题 |
byte数组构造 |
new String(byte[] bytes) 使用平台默认字符集(实际受IDE影响为UTF-8)解码 |
负数字节可能对应中文(UTF-8中3字节=1中文); 正数字节直接转ASCII字符 |
部分数组转换 |
new String(char[] chars, int offset, int count) 从指定索引开始转换指定长度的字符 |
offset起始位置包含在结果中,count需严格匹配有效范围 |
简化形式 |
直接赋值(如String s = "ABC")是最常用方式 |
IDE自动补全可能导错包(需确认java.lang.String) |
编码差异 |
操作系统默认GBK(中文占2字节) vs IDE强制UTF-8(中文占3字节) |
字节数组转字符串时需统一编码,否则乱码 |
IDE影响 |
IDEA启动参数强制UTF-8,覆盖平台默认字符集 |
实际开发环境与理论差异需特别注意 |
4.String知识点
知识点 |
核心内容 |
重点 |
字符串创建与内存分配 |
String s1="ABC"直接指向常量池,String s3=new String("ABC")在堆中创建新对象,但内容共享常量池的"ABC" |
s1==s2为true(常量池共享),s1==s3为false(new强制新地址) |
字符串对象数量分析 |
new String("ABC")可能创建1个(常量池已存在"ABC")或2个对象(常量池无"ABC"时先创建字面量) |
笔试需区分“共有对象数”和“实际创建对象数” |
字符串拼接机制 |
字面量拼接(如"hello"+"world")编译期优化为"helloworld"(不产生新对象);含变量的拼接(如s1+s2)触发StringBuilder生成新对象 |
s3==s4为true(字面量优化),s3==s5/s6为false(变量拼接必new) |
反编译验证原理 |
通过反编译工具可观察到:变量拼接代码被转换为StringBuilder的new操作,直接证明内存分配差异 |
实际笔试中需结合JVM常量池规则和编译优化行为分析 |
5.判断字符串内容
已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录成功与否,给出相应的提示
步骤:
1.先定义两个字符串,表示注册过的用户名和密码
2.创建Scanner对象,键盘录入用户名和密码
3.比较,如果输入的用户名和密码跟已经注册过的用户名和密码内容一样,就登录成功,否则就登录失败
public class Demo02String {
public static void main(String[] args) {
//1.先定义两个字符串,表示注册过的用户名和密码
String username = "root";
String password = "123";
//2.创建Scanner对象,键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请您输入用户名:");
String name = sc.next();
System.out.println("请您输入密码:");
String pwd = sc.next();
//3.比较,如果输入的用户名和密码跟已经注册过的用户名和密码内容一样,就登录成功,否则就登录失败
if (name.equals(username) && pwd.equals(password)) {
System.out.println("登录成功");
break;
} else {
if (i == 2) {
System.out.println("账号冻结");
} else {
System.out.println("登录失败!");
}
}
}
}
}
===============================================================================
public class Demo03String {
public static void main(String[] args) {
//String s = "abc";
String s = null;
//method(s);
String s1 = null;
String s2 = "abc";
method01(s1,s2);
}
/*
工具类:Objects
方法:判断两个对象是否相等 -> 自带防空指针作用
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
*/
private static void method01(String s1, String s2) {
if (Objects.equals(s1,s2)){
System.out.println("是abc");
}else{
System.out.println("不是abc");
}
}
/*
如果传递过来的对象是null,再去点其他方法,就会空指针
解决:不要让一个字符串变量去点,用确定的字符串去点,可以防空
*/
private static void method(String s) {
/*if (s.equals("abc")){
System.out.println("是abc");
}else{
System.out.println("不是abc");
}*/
if ("abc".equals(s)){
System.out.println("是abc");
}else{
System.out.println("不是abc");
}
}
}
知识点 |
核心内容 |
重点 |
String.equals()方法 |
比较字符串内容(区分大小写) |
返回值是布尔类型,比较的是内容而非地址 |
String.equalsIgnoreCase()方法 |
比较字符串内容(忽略大小写) |
仅适用于字母字符,数字/繁简体不适用 |
字符串比较的防空技巧 |
将常量字符串放在equals()方法调用方 |
开发实战技巧:"ABC".equals(s)可避免空指针 |
Objects.equals()工具方法 |
比较两个对象是否相等(自动防空) |
位于java.util.Objects类,可处理双变量比较 |
用户登录案例实现 |
三次登录机会控制流程 |
循环结构与字符串比较的综合应用 |
账号锁定机制 |
第三次失败后提示账号冻结 |
通过循环计数器(i==2)判断最终尝试 |
6.String获取方法
public class Demo04String {
public static void main(String[] args) {
String s1 = "abcdefg";
//int length() -> 获取字符串长度
System.out.println(s1.length());
//String concat(String s)-> 字符串拼接,返回新串儿
System.out.println(s1.concat("haha"));
//char charAt(int index) -> 根据索引获取对应的字符
System.out.println(s1.charAt(0));
//int indexOf(String s) -> 获取指定字符串在大字符串中第一次出现的索引位置
System.out.println(s1.indexOf("a"));
//String subString(int beginIndex) -> 截取字符串,从指定索引开始截取到最后,返回新串儿
System.out.println(s1.substring(3));
//String subString(int beginIndex,int endIndex) -> 截取字符串,从beginIndex开始到endIndex结束
//含头不含尾,返回新串儿
System.out.println(s1.substring(1,6));
}
}
知识点 |
核心内容 |
重点 |
长度获取 |
使用 length() 方法获取字符串长度(如 s1.length()) |
length 是方法(带括号),数组的 length 是属性 |
字符串拼接 |
concat() 方法拼接字符串,返回新字符串(原字符串不可变) |
返回新串,原串不变 |
字符索引获取 |
charAt(index) 根据索引获取对应字符(索引从 0 开始) |
越界会报错 |
子串查找 |
indexOf(str) 返回子串首次出现的索引位置 |
仅返回第一次匹配的索引 |
字符串截取 |
substring(beginIndex) 或 substring(beginIndex, endIndex) 截取子串 |
含头不含尾 |
字符串遍历 |
通过循环和 charAt() 遍历字符串字符 |
索引从 0 到 length()-1 |
7.String的转换功能
1.char[] toCharArray() -> 将字符串转成char数组
2.byte[] getBytes() -> 将字符串转成byte数组
3.String replace(CharSequence c1,CharSequence c2)-> 替换字符
CharSequence->String的接口
4.byte[] getBytes(String charsetName) -> 按照指定的编码将字符串转成byte数组
public class Demo06String {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "abcdefg";
//1.char[] toCharArray() -> 将字符串转成char数组
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
System.out.println("===============");
//2.byte[] getBytes() -> 将字符串转成byte数组
byte[] bytes = s.getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
System.out.println("===============");
//3.String replace(CharSequence c1,CharSequence c2)-> 替换字符 CharSequence->String的接口
System.out.println(s.replace("a","z"));
System.out.println("===============");
//4.byte[] getBytes(String charsetName) -> 按照指定的编码将字符串转成byte数组
byte[] bytes1 = "你好".getBytes("GBK");
for (int i = 0; i < bytes1.length; i++) {
System.out.println(bytes1[i]);
}
}
}
键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
步骤:
1.创建Scanner对象,键盘录入
2.定义三个变量,用来统计
3.调用next方法录入一个字符串,遍历字符串,将每一个字符拿出来
4.统计大写字母
A-Z -> 65-90
比如:B -> 66 -> 在65-90之间,证明就是大写字母
5.统计小写字母
a-z -> 97-122
比如:b -> 98 -> 在97-122之间,证明就是小写字母
6.统计数字:
0-9 -> 48-57
比如:字符1 -> 49 -> 在48-57之间,证明就是数字
7.将统计结果打印出来
public class Demo07String {
public static void main(String[] args) {
//1.创建Scanner对象,键盘录入
Scanner sc = new Scanner(System.in);
//2.定义三个变量,用来统计
int big = 0;
int small = 0;
int number = 0;
//3.调用next方法录入一个字符串,遍历字符串,将每一个字符拿出来
String data = sc.next();
char[] chars = data.toCharArray();
for (int i = 0; i < chars.length; i++) {
char num = chars[i];
/*4.统计大写字母
A-Z -> 65-90
比如:B -> 66 -> 在65-90之间,证明就是大写字母*/
if (num>='A' && num<='Z'){
big++;
}
/*5.统计小写字母
a-z -> 97-122
比如:b -> 98 -> 在97-122之间,证明就是小写字母*/
if (num>='a' && num<='z'){
small++;
}
/*6.统计数字:
0-9 -> 48-57
比如:字符1 -> 49 -> 在48-57之间,证明就是数字*/
if (num>='0' && num<='9'){
number++;
}
}
//7.将统计结果打印出来
System.out.println("大写有"+big+"个");
System.out.println("小写有"+small+"个");
System.out.println("数字有"+number+"个");
}
}
知识点 |
核心内容 |
重点 |
string转换功能 |
toCharArray:将字符串转成字符数组 |
区分toCharArray与getBytes方法 |
getBytes:将字符串转成byte数组,可指定编码 |
理解编码对字节数组长度的影响 |
|
replace:替换字符串中的字符序列 |
区分replace的两个参数类型,理解其为CharSequence |
|
字符判断与统计 |
判断字符是否为大写、小写或数字 |
理解ASCII码范围,并准确应用判断条件 |
统计字符串中大写字母、小写字母及数字的出现次数 |
遍历字符串,准确统计各类字符数量 |
|
Scanner类应用 |
使用Scanner类从键盘录入字符串 |
理解Scanner类的next方法,获取输入字符串 |
字符遍历方法 |
使用toCharArray或for循环遍历字符串 |
掌握多种遍历字符串的方法,灵活应用 |
统计结果输出 |
将统计结果以特定格式输出 |
准确拼接并输出统计结果,注意格式规范 |
8..String分割方法
public class Demo08String {
public static void main(String[] args) {
String s = "abc,txt";
String[] split = s.split(",");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
}
System.out.println("===============");
String s2 = "haha.hehe";
String[] split1 = s2.split("\\.");
for (int i = 0; i < split1.length; i++) {
System.out.println(split1[i]);
}
}
}
一些其他方法
1.boolean contains(String s) -> 判断老串儿中是否包含指定的串儿
2.boolean endsWith(String s) -> 判断老串儿是否以指定的串儿结尾
3.boolean startsWith(String s) -> 判断老串儿是否以指定的串儿开头
4.String toLowerCase()-> 将字母转成小写
5.String toUpperCase() -> 将字母转成大写
6.String trim() -> 去掉字符串两端空格
public class Demo09String {
public static void main(String[] args) {
String s = "abcdefg";
//1.boolean contains(String s) -> 判断老串儿中是否包含指定的串儿
System.out.println(s.contains("a"));
//2.boolean endsWith(String s) -> 判断老串儿是否以指定的串儿结尾
System.out.println(s.endsWith("g"));
//3.boolean startsWith(String s) -> 判断老串儿是否以指定的串儿开头
System.out.println(s.startsWith("a"));
//4.String toLowerCase()-> 将字母转成小写
System.out.println("ADbcda".toLowerCase());
//5.String toUpperCase() -> 将字母转成大写
System.out.println("dafadRWERW".toUpperCase());
//6.String trim() -> 去掉字符串两端空格
System.out.println(" hadfhad hdsfha sfhdsh ".trim());
System.out.println("==================");
System.out.println(" hadfhad hdsfha sfhdsh ".replace(" ",""));
}
}
知识点 |
核心内容 |
重点 |
字符串分割(split) |
按照指定规则分割字符串,参数为正则表达式 |
点(.)在正则中代表任意字符,需转义(\\\.)才能按字面点分割 |
字符串包含检测(contains) |
判断字符串是否包含指定子串 |
注意区分大小写 |
字符串首尾匹配(startsWith/endsWith) |
检测字符串是否以指定子串开头/结尾 |
可检测完整字符串但无实际意义 |
大小写转换(toLowerCase/toUpperCase) |
将字符串全部转为小写/大写 |
返回新字符串不改变原字符串 |
去空格(trim) |
去除字符串两端空格 |
无法去除字符串中间的空格 |
替换空格(replace) |
通过替换实现全部空格去除 |
比"先split再join"更高效 |
正则表达式特殊字符 |
点(.)代表任意字符 |
需用\\\转义特殊字符 |
9.StringBuilder
1.构造:
StringBuilder()
StringBuilder(String str)
public class Demo01StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb);
StringBuilder sb1 = new StringBuilder("abc");
System.out.println(sb1);
}
}
知识点 |
核心内容 |
重点 |
StringBuilder概述 |
可变字符序列,提供与StringBuffer兼容的API |
与StringBuffer方法相同但线程不安全 |
StringBuilder与String对比 |
拼接时不产生新对象,直接在缓冲区操作 |
String拼接会产生新对象导致内存浪费 |
缓冲区机制 |
底层使用未被final修饰的byte数组(默认长度16) |
数组可修改 vs String的final数组 |
自动扩容规则 |
默认扩容:老数组2倍+2(16→34) |
特殊情况:当添加数据>默认扩容量时按实际需求扩容 |
性能优势 |
内存利用率高(减少对象创建) |
拼接效率显著高于String的"+"操作 |
源码分析 |
通过AbstractStringBuilder实现扩容(Arrays.copyOf) |
关键参数:coder/oldCapacity/newCapacity |
特性 | StringBuilder | StringBuffer |
---|---|---|
线程安全 | 非线程安全 | 线程安全 |
同步机制 | 无同步(方法无 synchronized 修饰) |
所有方法使用 synchronized 同步 |
性能 | 更高(无锁开销) | 较低(同步带来性能损耗) |
适用场景 | 单线程环境 | 多线程环境 |
使用 StringBuilder
的情况
单线程环境:当字符串操作仅在单个线程内进行时(如方法内的局部变量),优先使用
StringBuilder
,避免同步带来的性能损耗。高频字符串操作:如循环中拼接字符串、动态生成 SQL 或 JSON 等场景。
编译器优化:现代 Java 编译器会将
+
操作符的字符串拼接自动优化为StringBuilder
(但仅限于非循环的简单操作,循环内仍需手动使用)。
// 单线程下的字符串拼接
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(", ");
}
String result = sb.toString();
使用 StringBuffer
的情况
多线程环境:当多个线程需要同时操作同一个字符串缓冲区时(如全局共享的日志缓冲区),需使用
StringBuffer
保证线程安全。遗留代码兼容:维护早期基于
StringBuffer
的代码时保留原有实现。
// 多线程共享的字符串缓冲区
StringBuffer buffer = new StringBuffer();
Runnable task = () -> {
synchronized(buffer) { // 即使使用 StringBuffer,复杂操作仍需外部同步
buffer.append("data from ").append(Thread.currentThread().getName()).append("\n");
}
};
// 启动多个线程操作 buffer
new Thread(task).start();
new Thread(task).start();
10.StringBuilder常用方法
常用方法:
StringBuilder append(任意类型数据) -> 字符串拼接,返回的是StringBuilder自己
StringBuilder reverse()-> 字符串翻转,返回的是StringBuilder自己
String toString() -> 将StringBuilder转成String-> 用StringBuilder拼接字符串是为了效率,为了不占内存,那么拼完之后我们后续可能会对拼接好的字符串进行处理,就需要调用String中的方法,所以需要将StringBuilder转成String
public class Demo02StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
StringBuilder sb1 = sb.append("张无忌");
System.out.println(sb1);
System.out.println(sb);
System.out.println(sb==sb1);
System.out.println("==============");
//链式调用
sb.append("赵敏").append("周芷若").append("小昭");
System.out.println(sb);
sb.reverse();
System.out.println(sb);
String s = sb.toString();
System.out.println(s);
}
}
============================================================
练习:键盘录入一个字符串,判断此字符串是否为"回文内容"
比如: abcba 上海自来水来自海上
public class Demo03StringBuilder {
public static void main(String[] args) {
//1.创建Scanner对象
Scanner sc = new Scanner(System.in);
String data = sc.next();
//2.创建StringBuilder对象
StringBuilder sb = new StringBuilder(data);
//3.翻转
sb.reverse();
//4.将StringBuilder转成String
String s = sb.toString();
if (data.equals(s)){
System.out.println("是回文内容");
}else{
System.out.println("不是回文内容");
}
}
}
知识点 |
核心内容 |
重点 |
Stream Builder的使用 |
创建对象(无参/有参构造) |
有参构造创建对象时缓冲区有内容 |
append方法(传任意类型数据) |
append返回值是string builder对象,不会产生新对象 |
|
链式调用 |
调方法后返回对象,可继续调其他方法 |
|
reverse方法 |
字符串翻转,返回的还是原string builder对象 |
|
toString方法 |
将string builder转成string,以便处理字符串 |
|
回文内容判断 |
录入字符串,翻转后与原字符串比较 |
用equals方法比较内容 |
String与String Builder的区别 |
String拼接字符串效率低,每次产生新对象 |
|
String Builder拼接效率高,线程不安全 |
与String Buffer的区别在于线程安全和效率 |
|
String Buffer拼接效率较低,但线程安全 |
11.数学相关类_Math类
public class Demo01Math {
public static void main(String[] args) {
//static int abs(int a) -> 求参数的绝对值
System.out.println(Math.abs(-10));
//static double ceil(double a) -> 向上取整
System.out.println(Math.ceil(3.6));
//static double floor(double a) ->向下取整
System.out.println(Math.floor(3.6));
//static long round(double a) -> 四舍五入
System.out.println(Math.round(3.6));
System.out.println(Math.round(-2.8));
//static int max(int a, int b) ->求两个数之间的较大值
System.out.println(Math.max(10,20));
//static int min(int a, int b) ->求两个数之间的较小值
System.out.println(Math.min(10,20));
}
}
知识点 |
核心内容 |
重点 |
Math类概述 |
数学工具类,用于执行基本数学运算 |
构造方法私有化特点 |
Math类特点 |
1. 构造方法私有化; 2. 方法均为静态方法 |
工具类设计模式理解 |
绝对值计算 |
Math.abs()方法使用,求绝对值 |
负数处理逻辑 |
取整方法 |
Math.ceil()向上取整; Math.floor()向下取整; Math.round()四舍五入 |
负数取整规则 |
极值运算 |
Math.max()求最大值; Math.min()求最小值 |
多值比较需嵌套调用 |
数学函数 |
包含指数/对数/平方根/三角函数等方法 |
实际应用场景理解 |
API文档特征 |
1. 无公开构造方法; 2. 直接显示字段摘要 |
与普通类的文档对比 |
12.数学相关类_BigInteger类
public class Demo02BigInteger {
public static void main(String[] args) {
BigInteger b1 = new BigInteger("121212121212121212121212121212121212121");
BigInteger b2 = new BigInteger("121212121212121212121212121212121212121");
//BigInteger add(BigInteger val) 返回其值为 (this + val) 的 BigInteger
System.out.println(b1.add(b2));
//BigInteger subtract(BigInteger val) 返回其值为 (this - val) 的 BigInteger
System.out.println(b1.subtract(b2));
//BigInteger multiply(BigInteger val) 返回其值为 (this * val) 的 BigInteger
System.out.println(b1.multiply(b2));
//BigInteger divide(BigInteger val) 返回其值为 (this / val) 的 BigInteger
System.out.println(b1.divide(b2));
}
}
int intValue() 将BigInteger转成int
long longValue() 将BigInteger 转成 long
BigInteger上限:42亿的21亿次方,内存根本扛不住,所以可以认为BigInteger无上限
知识点 |
核心内容 |
重点 |
BigInteger类概述 |
用于处理超大整数(超过long类型范围)的数据结构 |
与基本数据类型(如int/long)的存储上限差异 |
构造方法 |
必须通过字符串数字创建对象(如new BigInteger("123")) |
非数字字符串(如"ABC")会报错 |
四则运算方法 |
add()加法、subtract()减法、multiply()乘法、divide()除法 |
方法命名与数学符号的对应关系(如subtract对应-) |
类型转换 |
intValue()/longValue()将BigInteger转为基本数据类型 |
溢出风险(超大数转int可能丢失精度) |
理论上限 |
数值上限为42亿的20次方,但实际受内存限制 |
与long(2^63-1)的数值范围对比 |
13.数学相关类_BigDecimal类
常用方法:
static BigDecimal valueOf(double val) -> 此方法初始化小数时可以传入double型数据
BigDecimal add(BigDecimal val) 返回其值为 (this + val) 的 BigDecimal
BigDecimal subtract(BigDecimal val) 返回其值为 (this - val) 的 BigDecimal
BigDecimal multiply(BigDecimal val) 返回其值为 (this * val) 的 BigDecimal
BigDecimal divide(BigDecimal val) 返回其值为 (this / val) 的 BigDecimal
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
divisor:除号后面的那个数
scale:指定保留几位小数
roundingMode:取舍方式
static int ROUND_UP -> 向上加1
static int ROUND_DOWN -> 直接舍去
static int ROUND_HALF_UP -> 四舍五入
如果除不尽,会报错,出现运算异常
=======================================================================================
## BigDecimal使用
public class Demo03BigDecimal {
public static void main(String[] args) {
//big01();
//big02();
big03();
}
private static void big03() {
BigDecimal b1 = new BigDecimal("3.55");
BigDecimal b2 = new BigDecimal("2.12");
BigDecimal divide = b1.divide(b2, 2, BigDecimal.ROUND_UP);
System.out.println("divide = " + divide);
double v = divide.doubleValue();
System.out.println("v = " + v);
}
private static void big02() {
BigDecimal b1 = new BigDecimal("3.55");
//BigDecimal b2 = new BigDecimal("2.12");
BigDecimal b2 = BigDecimal.valueOf(2.12);
//BigDecimal add(BigDecimal val) 返回其值为 (this + val) 的 BigDecimal
BigDecimal add = b1.add(b2);
System.out.println("add = " + add);
//BigDecimal subtract(BigDecimal val) 返回其值为 (this - val) 的 BigDecimal
BigDecimal subtract = b1.subtract(b2);
System.out.println("subtract = " + subtract);
//BigDecimal multiply(BigDecimal val) 返回其值为 (this * val) 的 BigDecimal
BigDecimal multiply = b1.multiply(b2);
System.out.println("multiply = " + multiply);
//BigDecimal divide(BigDecimal val) 返回其值为 (this / val) 的 BigDecimal
BigDecimal divide = b1.divide(b2);
System.out.println("divide = " + divide);
}
private static void big01() {
float a = 3.55F;
float b = 2.12F;
float result = a-b;
System.out.println("result = " + result);//1.4300001
}
}
double doubleValue() 将此BigDecimal转成double
========================================================================================
## 3.BigDecimal除法过时方法解决
1.注意:如果调用的成员上面有一个横线,证明此成员过时了,底层会有一个注解@Deprecated修饰,但是过时的成员还能使用,只不过被新的成员代替了,不推荐使用了
2.方法:
divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
divisor:代表除号后面的数据
scale:保留几位小数
roundingMode:取舍方式-> RoundingMode是一个枚举,里面的成员可以类名直接调用
UP:向上加1
DOWN:直接舍去
HALF_UP:四舍五入
private static void big04() {
BigDecimal b1 = new BigDecimal("3.55");
BigDecimal b2 = new BigDecimal("2.12");
BigDecimal divide = b1.divide(b2, 2, RoundingMode.HALF_UP);
System.out.println("divide = " + divide);
}
知识点 |
核心内容 |
重点 |
BigDecimal的作用 |
解决float/double直接运算的精度损失问题,尤其适用于金融计算 |
构造方法传参必须用String,禁用double(不可预知性) |
BigDecimal初始化 |
推荐构造方法new BigDecimal("3.55")或静态方法BigDecimal.valueOf(3.55) |
valueOf支持double参数但内部仍转为String处理 |
加减乘除方法 |
add()、subtract()、multiply()、divide() |
除法divide()需处理除不尽异常(如指定保留小数位和舍入模式) |
舍入模式 |
ROUND_UP(向上加一)、ROUND_DOWN(直接舍去)、ROUND_HALF_UP(四舍五入) |
默认除法必须精确,否则抛ArithmeticException |
类型转换 |
doubleValue()将BigDecimal转回double |
转换后可能重新引入精度问题,需谨慎使用 |
知识点 |
核心内容 |
重点 |
过时方法标识 |
方法名或输入方式带横杠表示已过时(@Deprecated注解标记) |
横杠的语义与底层注解关联性 |
过时方法的使用 |
仍可调用但不推荐,需替换为新方法 |
新旧方法兼容性差异 |
替代方案 |
BigDecimal.divide()新版本使用RoundingMode枚举(如DOWN/UP/HALF_UP) |
参数类型从int变为枚举,功能等价但更规范 |
枚举类型应用 |
RoundingMode包含舍入策略(如直接舍去、向上加一、四舍五入) |
枚举成员通过类名直接调用(如RoundingMode.DOWN) |
新旧方法对比 |
旧方法:divide(divisor, scale, int roundingMode); 新方法:divide(divisor, scale, **RoundingMode mode**) |
参数含义一致,但枚举类型提升代码可读性 |
14.日期相关类_Date类
构造:
Date() -> 获取当前系统时间
Date(long time) -> 获取指定时间,传递毫秒值 -> 从时间原点开始算
private static void date01() {
//Date() -> 获取当前系统时间
Date date1 = new Date();
System.out.println("date1 = " + date1);
//Date(long time) -> 获取指定时间,传递毫秒值 -> 从时间原点开始算
Date date2 = new Date(1000L);
System.out.println("date2 = " + date2);
}
====================================================================================
常用方法:
1.void setTime(long time) -> 设置时间,传递毫秒值-> 从时间原点开始算
2.long getTime()->获取时间,返回毫秒值
private static void date02() {
Date date = new Date();
//1.void setTime(long time) -> 设置时间,传递毫秒值-> 从时间原点开始算
date.setTime(1000L);
//2.long getTime()->获取时间,返回毫秒值
System.out.println(date.getTime());
}
知识点 |
核心内容 |
重点 |
Date类的定义 |
Date类表示特定的一个瞬间,可以精确到毫秒 |
Date类的精确度和表示的内容 |
时间原点 |
Unix系统起始时间,1970年1月1日0时0分0秒(格林威治时间,零时区) |
Unix时间原点的具体时间和含义 |
时区的概念 |
地球上不同位置的时间差异,北京位于东八区 |
时区的定义和北京所在的时区 |
时区与时间的关系 |
每个时区相差15度,时间相差1小时;北京时间比时间原点所在时区时间差8小时 |
时区之间的时间差异和计算方法 |
Date类的构造方法 |
无参构造方法获取当前系统时间; 有参构造方法传递毫秒值创建时间对象 |
Date类两种构造方法的使用和区别 |
Date类的方法 |
常用方法:getTime()获取时间的毫秒值; setTime(long time)设置时间的毫秒值 |
Date类常用方法的名称和功能 |