1. 所有类的父类,不管继承不继承都是这个类的子类
2. 构造方法public Object(){} 注意,因为是超类,所以第一句没有super()
用来向键盘输入一些数据,Scanner in = new Scanner(System.in);
备注:System.in 系统输入指的是通过键盘录入数据
int i = in.nextInt();//输入一个整数
String s = in.next();//输入一个字符串
控制端输入一些信息的类
//获取当前的时间戳起点是1970
Long time =System.currentTimeMillis();
//结束当前的jvm虚拟机
System.exit(0);
//立即运行垃圾回收机制
System.gc();
System类不能手动创建对象,因为构造方法被private修饰,阻止外界创建对象。System类中的都是static方法,类名访问即可。在JDK中,有许多这样的类
顾名思义,Math
类就是用来进行数学计算的,它提供了大量的静态方法来便于我们实现数学计算:
主要方法
Random
用来创建伪随机数。所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的。
要生成一个随机数,可以使用nextInt()
、nextLong()
、nextFloat()
、nextDouble()
:
- Random r = new Random();
- r.nextInt(); // 2071575453,每次都不一样
- r.nextInt(10); // 5,生成一个[0,10)之间的int
- r.nextLong(); // 8811649292570369305,每次都不一样
- r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
- r.nextDouble(); // 0.3716...生成一个[0,1)之间的double
有童鞋问,每次运行程序,生成的随机数都是不同的,没看出伪随机数的特性来。
这是因为我们创建Random
实例时,如果不给定种子,就使用系统当前时间戳作为种子,因此每次运行时,种子不同,得到的伪随机数序列就不同。
如果我们在创建Random
实例时指定一个种子,就会得到完全确定的随机数序列:
public class Main {
public static void main(String[] args) {
Random r = new Random(12345);
for (int i = 0; i < 10; i++) {
System.out.println(r.nextInt(100));
}
// 51, 80, 41, 28, 55...
}
}
前面我们使用的Math.random()
实际上内部调用了Random
类,所以它也是伪随机数,只是我们无法指定种子。
有伪随机数,就有真随机数。实际上真正的真随机数只能通过量子力学原理来获取,而我们想要的是一个不可预测的安全的随机数,SecureRandom
就是用来创建安全的随机数的:
- SecureRandom sr = new SecureRandom();
- System.out.println(sr.nextInt(100));
SecureRandom
无法指定种子,它使用RNG(random number generator)算法。JDK的SecureRandom
实际上有多种不同的底层实现,有的使用安全随机种子加上伪随机数算法来产生安全的随机数,有的使用真正的随机数生成器。实际使用的时候,可以优先获取高强度的安全随机数生成器,如果没有提供,再使用普通等级的安全随机数生成器:
- public class Main {
- public static void main(String[] args) {
- SecureRandom sr = null;
- try {
- sr = SecureRandom.getInstanceStrong(); // 获取高强度安全随机数生成器
- } catch (NoSuchAlgorithmException e) {
- sr = new SecureRandom(); // 获取普通的安全随机数生成器
- }
- byte[] buffer = new byte[16];
- sr.nextBytes(buffer); // 用安全随机数填充buffer
- System.out.println(Arrays.toString(buffer));
- }
- }
SecureRandom
的安全性是通过操作系统提供的安全的随机种子来生成随机数。这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”。
在密码学中,安全的随机数非常重要。如果使用不安全的伪随机数,所有加密体系都将被攻破。因此,时刻牢记必须使用SecureRandom
来产生安全的随机数。
需要使用安全随机数的时候,必须使用SecureRandom,绝不能使用Random!
一台机器上通过当前时间与电脑网卡生成的一段字符
UUID.randomUUID().toString()一般转成string使用
Comparator
java.util包中的接口
Comparable
java.lang包中得接口
在Java中,由CPU原生提供的整型最大范围是64位long
型整数,如果我们使用的整数范围超过了long
型怎么办?
java.math.BigInteger
就是用来表示任意大小的整数。BigInteger
内部用一个int[]
数组来模拟一个非常大的整数:
对BigInteger
做运算的时候,只能使用实例方法,例如,加法运算:
- BigInteger i1 = new BigInteger("1234567890");
- BigInteger i2 = new BigInteger("12345678901234567890");
- BigInteger sum = i1.add(i2); // 12345678902469135780
和long
型整数运算比,BigInteger
不会有范围限制,但缺点是速度比较慢。
也可以把BigInteger
转换成long
型:
- BigInteger i = new BigInteger("123456789000");
- System.out.println(i.longValue()); // 123456789000
- System.out.println(i.multiply(i).longValueExact()); // java.lang.ArithmeticException: BigInteger out of long range
使用longValueExact()
方法时,如果超出了long
型的范围,会抛出ArithmeticException
。
BigInteger
和Integer
、Long
一样,也是不可变类,并且也继承自Number
类。因为Number
定义了转换为基本类型的几个方法:
byte
:byteValue()
short
:shortValue()
int
:intValue()
long
:longValue()
float
:floatValue()
double
:doubleValue()
因此,通过上述方法,可以把BigInteger
转换成基本类型。如果BigInteger
表示的范围超过了基本类型的范围,转换时将丢失高位信息,即结果不一定是准确的。如果需要准确地转换成基本类型,可以使用intValueExact()
、longValueExact()
等方法,在转换时如果超出范围,将直接抛出ArithmeticException
异常。
如果BigInteger
的值甚至超过了float
的最大范围(3.4x1038),那么返回的float是什么呢?
- public static void main(String[] args) {
- BigInteger n = new BigInteger("999999").pow(99);
- float f = n.floatValue();
- System.out.println(f);//Infinity
- }
BigDecimal
和BigInteger
类似,BigDecimal
可以表示一个任意大小且精度完全准确的浮点数。
- BigDecimal bd = new BigDecimal("123.4567");
- System.out.println(bd.multiply(bd)); // 15241.55677489
BigDecimal
用scale()
表示小数位数,例如:
- BigDecimal d1 = new BigDecimal("123.45");
- BigDecimal d2 = new BigDecimal("123.4500");
- BigDecimal d3 = new BigDecimal("1234500");
- System.out.println(d1.scale()); // 2,两位小数
- System.out.println(d2.scale()); // 4
- System.out.println(d3.scale()); // 0
通过BigDecimal
的stripTrailingZeros()
方法,可以将一个BigDecimal
格式化为一个相等的,但去掉了末尾0的BigDecimal
:
- BigDecimal d1 = new BigDecimal("123.4500");
- BigDecimal d2 = d1.stripTrailingZeros();
- System.out.println(d1.scale()); // 4
- System.out.println(d2.scale()); // 2,因为去掉了00
-
- BigDecimal d3 = new BigDecimal("1234500");
- BigDecimal d4 = d3.stripTrailingZeros();
- System.out.println(d3.scale()); // 0
- System.out.println(d4.scale()); // -2
如果一个BigDecimal
的scale()
返回负数,例如,-2
,表示这个数是个整数,并且末尾有2个0。
可以对一个BigDecimal
设置它的scale
,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:
- public class Main {
- public static void main(String[] args) {
- BigDecimal d1 = new BigDecimal("123.456789");
- BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568
- BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截断,123.4567
- System.out.println(d2);
- System.out.println(d3);
- }
- }
对BigDecimal
做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断:
- BigDecimal d1 = new BigDecimal("123.456");
- BigDecimal d2 = new BigDecimal("23.456789");
- BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入
- BigDecimal d4 = d1.divide(d2); // 报错:ArithmeticException,因为除不尽
还可以对BigDecimal
做除法的同时求余数:
- public class Main {
- public static void main(String[] args) {
- BigDecimal n = new BigDecimal("12.345");
- BigDecimal m = new BigDecimal("0.12");
- BigDecimal[] dr = n.divideAndRemainder(m);
- System.out.println(dr[0]); // 102
- System.out.println(dr[1]); // 0.105
- }
- }
调用divideAndRemainder()
方法时,返回的数组包含两个BigDecimal
,分别是商和余数,其中商总是整数,余数不会大于除数。我们可以利用这个方法判断两个BigDecimal
是否是整数倍数:
- BigDecimal n = new BigDecimal("12.75");
- BigDecimal m = new BigDecimal("0.15");
- BigDecimal[] dr = n.divideAndRemainder(m);
- if (dr[1].signum() == 0) {
- // n是m的整数倍
- }
比较BigDecimal
在比较两个BigDecimal
的值是否相等时,要特别注意,使用equals()
方法不但要求两个BigDecimal
的值相等,还要求它们的scale()
相等:
- BigDecimal d1 = new BigDecimal("123.456");
- BigDecimal d2 = new BigDecimal("123.45600");
- System.out.println(d1.equals(d2)); // false,因为scale不同
- System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2
- System.out.println(d1.compareTo(d2)); // 0
必须使用compareTo()
方法来比较,它根据两个值的大小分别返回负数、正数和0
,分别表示小于、大于和等于。
总是使用compareTo()比较两个BigDecimal的值,不要使用equals()!
如果查看BigDecimal
的源码,可以发现,实际上一个BigDecimal
是通过一个BigInteger
和一个scale
来表示的,即BigInteger
表示一个完整的整数,而scale
表示小数位数:
- public class BigDecimal extends Number implements Comparable
{ - private final BigInteger intVal;
- private final int scale;
- }
BigDecimal
也是从Number
继承的,也是不可变对象。