Math类的常用方法
abs的bug:
以int类型为例,取值范围:-2147483648~2147483647
如果没有正数与负数对应,那么传递负数结果有误
-2147483648 没有正数与之对应,所以abs结果产生bug
system.out.println(Math.abs(-2147483648));//-2147483648,出现bug
system.out.println(Math.abs(-2147483647));//2147483647
开根号:
Math.sqrt(4) // 输出2.0,开平方根
Math.cbrt(8) // 输出2.0,开立方根
random的应用:
// 输出1~100的随机数
System.out.println(Math.floor(Math.random()*100 + 1));
System:
System也是一个工具类,提供了一些与系统相关的方法。
// 需要把整个程序结束的时候
System.exit(0);
// 获取程序运行的总时间
long l = System.currentTimeMillis(); // 单位毫秒
System.out.println(l);
int[] arr1 = {1,2,3,4,5,6,7,8,9,10};
int[] arr2 = new int [10];
// 把arr1的数组拷贝到arr2中
// 参数一:数据源,要拷贝的数据要从哪个数组而来
// 参数二:从数据源数组中的第几个索引开始拷贝
// 目的地,我把数据拷贝到哪个数组
//目的地数组的索引
// 拷贝的个数
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
// 细节:
// 如果数据源数组和目的地数组都是基本数据类型,那么两者的类型必须保持一致,否则会出错
// 在拷贝的时候需要考虑数组的长度。如果超出范围则会报错
// 如果数组源数组和目的地数组都是引用数据类型(地址值),那么子类类型可以复制给父类类型
Runtime:
// 获取Runtime的对象
// 由于底层代码让构造方法私有化,所以外界不准创建Runtime的对象
Runtime r1 = Runtime.getRuntime();
// exit停止虚拟机
Runtime.getRuntime().exit(0);
// 获取CPU的线程数
System.out.println(Runtime.getRuntime().availableProcessors()); // 12(不一定)
// 总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().maxMemory());
// 已经获取的总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().totalMemory());
// 剩余内存的大小
System.out.println(Runtime.getRuntime().freeMemory());
// 运行cmd命令
// shutdown 关机
// 加上参数才能执行
//-s:默认在1min后关机
//-s -t 指定时间:指定关机时间
//-a:取消关机操作
//-r:关机并重启
Runtime.getRuntime().exec("notepad");
Runtime.getRuntime().exec("shutdown -a");
object:
object是Java中的顶级父类。所有的类都直接或间接的继承于object类。
object类中的方法可以被所有子类访问,所以我们要学习object类和其中的方法。
public boolean equals(Object obj)
-
作用:用于比较两个对象是否“相等”。默认实现是比较两个对象的引用是否相同,即判断它们是否指向同一个内存地址。
-
重写:通常会重写
equals
方法,以提供对象内容的比较。例如,比较两个Person
对象时,可能需要比较它们的姓名和年龄,而不仅仅是内存地址。 (在类里面重写)
结论:
如果没有重写equals方法,那么默认使用object中的方法进行比较,比较的是地址值是否相等
一般来讲地址值对于我们意义不大,所以我们会重写,重写之后比较的就是对象内部的属性值了。
// 比较对象内部的属性值
@Override
public boolean equals(Object obj) {
if (this == obj) return true;// 判断是不是同一个对象
if (obj == null || getClass() != obj.getClass()) return false; // 非空判断和类是否相同
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
例子:
public String toString()
-
作用:返回对象的字符串表示,默认实现是返回对象的类名+
@
+哈希码的十六进制值。 -
重写:通常会重写
toString
方法,以提供对象的详细信息,例如字段值的字符串表示。
思考:默认情况下,因为object类中的tostring方法返回的是地址值。所以,默认情况下,打印一个对象打印的就是地址值,但是地址值对于我们是没什么意义的。
我想要看到对象内部的属性值?我们该怎么办?
处理方案:重写父类0bject类中的tostring方法
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
clone方法:
1. clone()
方法的基本概念
-
定义:
clone()
方法用于创建并返回当前对象的一个副本。这个副本通常被称为“克隆对象”。 -
声明:
clone()
方法在Object
类中是protected
访问级别,这意味着只有在子类中可以直接访问它,或者通过重写并改变其访问级别为public
才能在外部调用。 -
抛出异常:该方法可能会抛出
CloneNotSupportedException
异常,这是因为并非所有对象都可以被克隆。为了让一个对象能够被克隆,它的类必须实现Cloneable
接口,否则调用clone()
方法时将抛出此异常。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
2. Cloneable
接口
-
功能:
Cloneable
是一个标识接口(即没有任何方法),用于指示该类的对象可以安全地使用clone()
方法进行克隆。如果一个类没有实现Cloneable
接口,调用clone()
方法时会抛出CloneNotSupportedException
。 -
作用:实现
Cloneable
接口的类表明它同意并且支持使用clone()
方法进行对象的克隆操作。
public class Person implements Cloneable {
private String name;
private int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
3. 浅拷贝与深拷贝
-
浅拷贝:o
bject
类的默认clone()
方法执行的是浅拷贝,即复制当前对象及其所有字段的副本,但如果这些字段是对象的引用,浅拷贝只复制引用,而不复制引用对象本身。这意味着原对象和克隆对象共享引用类型字段的数据。
例子:如果一个对象有一个数组或其他对象作为字段,浅拷贝只会复制数组的引用,而不会复制数组的内容。
class Person implements Cloneable {
String name;
int[] data;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝
}
}
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
p1.name = "Alice";
p1.data = new int[]{1, 2, 3};
Person p2 = (Person) p1.clone();
// == 对于引用型数据则比较内存地址,Object 类的默认 equals() 实现也是比较内存地址
System.out.println(p1.name.equals(p2.name)); // true
System.out.println(p1.data == p2.data); // true, data 数组共享,指向的是同一个数组
}
}
深拷贝:深拷贝不仅复制对象本身,还会递归复制所有引用类型字段指向的对象。这意味着克隆后的对象与原对象完全独立,它们不共享任何引用类型字段。
实现方式:要实现深拷贝,必须在重写 clone()
方法时手动复制所有引用类型字段的内容。通常需要逐层调用 clone()
方法,或者创建这些引用对象的新实例。
class Person implements Cloneable {
String name;
int[] data;
// 深浅拷贝结合
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone(); // 浅拷贝
cloned.data = this.data.clone(); // 深拷贝
return cloned;
}
}
public class TestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person();
p1.name = "Alice";
p1.data = new int[]{1, 2, 3};
Person p2 = (Person) p1.clone();
System.out.println(p1.name.equals(p2.name)); // true
System.out.println(p1.data == p2.data); // false, data 数组被深拷贝,在内存中开辟了新的地址
}
}
objects工具类:
1. objects.equals(Object a, Object b)
-
功能:安全地比较两个对象是否相等。如果两个对象都是
null
,则返回true
;如果只有一个对象是null
,则返回false
;否则,调用a.equals(b)
进行比较。 -
好处:避免了手动检查
null
值的麻烦,减少了NullPointerException
的风险。
String s1 = null;
String s2 = "hello";
System.out.println(Objects.equals(s1, s2)); // 输出: false
System.out.println(Objects.equals(s1, null)); // 输出: true
2. Objects.isNull(Object obj)
-
功能:判断对象是否为
null
。该方法的作用相当于obj == null
。 -
好处:使代码更加语义化,更加可读。
3. Objects.nonNull(Object obj)
-
功能:判断对象是否非
null
。该方法相当于obj != null
。 -
好处:语义化表达,通常用于流操作中进行
null
过滤。
BigInteger:
. BigInteger
的基本特性
-
不可变性:
BigInteger
对象是不可变的。一旦创建,它的值就不能被更改。每次进行操作时,都会返回一个新的BigInteger
对象。 -
任意精度:
BigInteger
可以表示的整数大小仅受限于可用的内存,因此可以处理非常大的整数。
2. 创建 BigInteger
对象
可以通过以下几种方式创建 BigInteger
对象:
-
通过字符串创建:这是最常用的方式,可以从任意长度的字符串创建一个
BigInteger
。
BigInteger bigInt = new BigInteger("123456789012345678901234567890");
通过基本类型创建:可以使用 valueOf
方法从基本类型(如 long
)创建一个 BigInteger
。
BigInteger bigInt = BigInteger.valueOf(123456789L);
场景:当你有一个非常大的整数,它超出了 long
的范围(超过 9223372036854775807),或者该数值是以字符串形式存储时,可以使用字符串来创建 BigInteger
。
BigInteger.valueOf(long value)
在内部会缓存 -16
到 16
之间的 BigInteger
对象,这样在这些范围内的数字每次调用时不会创建新的 BigInteger
对象,而是直接返回缓存中的实例。
BigInteger a = BigInteger.valueOf(10);
BigInteger b = BigInteger.valueOf(10);
System.out.println(a == b); // 输出: true
System.out.println(a.equals(b)); // 输出: true
BigInteger c = BigInteger.valueOf(100);
BigInteger d = BigInteger.valueOf(100);
System.out.println(c == d); // 输出: false
System.out.println(c.equals(d)); // 输出: true
3. BigInteger
的运算
BigInteger
提供了类似于基本数据类型的数学运算方法,包括加法、减法、乘法、除法、取模等。由于 BigInteger
是不可变的,每次操作都会返回一个新的对象。
-
加法:
BigInteger a = new BigInteger("123456789"); BigInteger b = new BigInteger("987654321"); BigInteger sum = a.add(b);
-
减法:
BigInteger difference = a.subtract(b);
-
乘法:
BigInteger product = a.multiply(b);
-
除法:
BigInteger quotient = a.divide(b);
-
取模:
BigInteger mod = a.mod(b);
-
幂运算:
BigInteger power = a.pow(10); // 计算 a 的 10 次幂
-
最大公约数(GCD):
BigInteger gcd = a.gcd(b); // 计算 a 和 b 的最大公约数
-
取反运算:
BigInteger negation = a.negate(); // 返回 a 的相反数
-
绝对值:
BigInteger absValue = a.abs(); // 返回 a 的绝对值
-
求模的同时求商:
BigInteger[] result = a.divideAndRemainder(b); BigInteger quotient = result[0]; // 商 BigInteger remainder = result[1]; // 余数
-
模幂运算:常用于加密算法中,可以高效计算
(base^exponent) % modulus
。BigInteger modPow = a.modPow(b, m); // 计算 (a^b) % m
4.
BigInteger
的比较方法
相等比较:使用 equals()
方法判断两个 BigInteger
对象的数值是否相等。boolean isEqual = a.equals(b);
总结:
BigDecimal:
计算机的小数:
BigDecimal
是 Java 中用于高精度浮点数计算的类,位于 java.math
包中。
1. BigDecimal
的基本特性
-
不可变性:
BigDecimal
对象是不可变的。一旦创建,它的值就不能被更改。每次进行操作时,都会返回一个新的BigDecimal
对象。 -
任意精度:
BigDecimal
可以表示非常大或非常小的数值,并且可以精确到小数点后的任意位数。
2. 创建 BigDecimal
对象
可以通过以下几种方式创建 BigDecimal
对象:
-
通过字符串创建:这是推荐的方式,因为它能避免由于浮点数转换带来的精度问题。
BigDecimal bigDecimal = new BigDecimal("123.456");
-
通过基本类型创建:可以通过
int
、long
、double
等类型直接创建BigDecimal
,但注意使用double
可能会引入精度问题。BigDecimal fromInt = new BigDecimal(123); BigDecimal fromLong = new BigDecimal(123L); BigDecimal fromDouble = new BigDecimal(123.456); // 不推荐,会失去精度
注意:建议避免使用
BigDecimal(double)
构造函数,因为double
可能会丢失精度。使用BigDecimal.valueOf(double)
是更好的选择。BigDecimal safeFromDouble = BigDecimal.valueOf(123.456);
细节:
1.如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
2.如果要表示的数字比较大,超出了double的取值范围,建议使用字符串的构造方法
3.如果我们传递的是0~10之问的整数,包含0,包含10,那么方法会返回己经创建好的对象,不会重新new,如果是double类型的还是会重新new。
3. BigDecimal
的基本运算
BigDecimal
提供了类似于 BigInteger
的基本数学运算方法,包括加法、减法、乘法、除法、取模等。所有这些方法都会返回一个新的 BigDecimal
对象。
-
加法:
BigDecimal a = new BigDecimal("123.45"); BigDecimal b = new BigDecimal("678.90"); BigDecimal sum = a.add(b);
-
减法:
BigDecimal difference = a.subtract(b);
-
乘法:
BigDecimal product = a.multiply(b);
-
除法:
BigDecimal quotient = a.divide(b, RoundingMode.HALF_UP); // 指定舍入模式
注意:除法操作必须指定舍入模式,否则可能抛出
ArithmeticException
,因为BigDecimal
不一定能精确除尽。
4. BigDecimal
的舍入模式
RoundingMode.UP
:向远离零的方向舍入。RoundingMode.DOWN
:向接近零的方向舍入。RoundingMode.CEILING
:向正无限大方向舍入。RoundingMode.FLOOR
:向负无限大方向舍入。RoundingMode.HALF_UP
:四舍五入,如果离中间值等距,向上舍入。RoundingMode.HALF_DOWN
:五舍六入,如果离中间值等距,向下舍入。RoundingMode.HALF_EVEN
:银行家舍入法,如果离中间值等距,舍入到偶数。