Math
Math类所在包为java.lang包,因此在使用的时候不需要进行导包。并且Math类被final修饰了,因此该类是不能被继承的。
Math类包含执行基本数字运算的方法,我们可以使用Math类完成基本的数学运算。
public static int abs(int a) // 返回参数的绝对值
public static double ceil(double a) // 返回大于或等于参数的最小整数
public static double floor(double a) // 返回小于或等于参数的最大整数
public static int round(float a) // 按照四舍五入返回最接近参数的int类型的值
public static int max(int a,int b) // 获取两个int值中的较大值
public static int min(int a,int b) // 获取两个int值中的较小值
public static double pow (double a,double b) // 计算a的b次幂的值
public static double sqrt(double a) // 平方根
public static double cbrt(double a) // 立方根
public static double random() // 返回一个[0.0,1.0)的随机值
其中,如果abs参数小于int取值下限,程序得出的结果是错误的,为了防止出问题,在JDK15之后引入了absExact方法,不能转换时候会报错;
System
System类所在包为java.lang包,因此在使用的时候不需要进行导包。并且System类被final修饰了,因此该类是不能被继承,System包含了系统操作的一些常用的方法。比如获取当前时间所对应的毫秒值,再比如终止当前JVM等等。
退出:
public static void exit(int status) // 终止当前正在运行的Java虚拟机,0表示正常退出,非零表示异常退出
计算机中的时间:
计算机中,时间存在原点,表示开始计时的点,即1970年1月1号 00:00,关于为什么是这个时间,可以自行百度;而国内操作系统,因为时差的缘故,时间原点是1970年1月1号 08:00,早了8个小时。此外还需要了解时间进制:
1秒 = 1000毫秒;1毫秒 = 1000微秒;1微秒=1000纳秒;
获取当前时间:
public static long currentTimeMillis() // 获取当前时间所对应的毫秒值(当前时间为0时区所对应的时间即就是英国格林尼治天文台旧址所在位置)
数组拷贝:
public static native void arraycopy(Object src(数据源数组), int srcPos(起始索引), Object dest(目标数组), int destPos(起始索引), int length(拷贝长度)); // 进行数值元素copy
演示一:获取当前毫秒时间
public class SystemDemo01 {
public static void main(String[] args) {
// 获取当前时间所对应的毫秒值
long millis = System.currentTimeMillis();
// 输出结果
System.out.println("当前时间所对应的毫秒值为:" + millis);
}
}
演示二:程序运行时间
public static void main(String[] args) {
//判断1~100000之间有多少个质数
long start = System.currentTimeMillis();
for (int i = 1; i <= 100000; i++) {
boolean flag = isPrime2(i);
if (flag) {
System.out.println(i);
}
}
long end = System.currentTimeMillis();
//获取程序运行的总时间
System.out.println(end - start); //方式一:1010 毫秒 方式二:37毫秒
}
//以前判断是否为质数的方式,循环次数较多,运行效率低
public static boolean isPrime1(int number) {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
//改进之后判断是否为质数的方式(效率高)
public static boolean isPrime2(int number) {
//不超过平方根次
for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
演示三、数组拷贝
public static void main(String[] args) {
// 定义源数组
int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56 } ;
// 定义目标数组
int[] desArray = new int[10] ;
// 进行数组元素的copy: 把srcArray数组中从0索引开始的3个元素,从desArray数组中的1索引开始复制过去
System.arraycopy(srcArray , 0 , desArray , 1 , 3);
// 遍历目标数组
for(int x = 0 ; x < desArray.length ; x++) {
if(x != desArray.length - 1) {
System.out.print(desArray[x] + ", ");
}else {
System.out.println(desArray[x]);
}
}
}
注意:
- 若原数组和目标数组均为基本数据类型数组,则两者类型必须保持一致;
- 注意数组长度,目标数组长度不能小于原数组要拷数据长度,否则数组越界错误;
- 如果数组是引用数据类型,则子类类型可以赋值给父类(有点像多态了)
Runtime
Runtime表示Java中运行时对象,可以获取到程序运行时设计到的一些信息。
常用方法:
public static Runtime getRuntime() //当前系统的运行环境对象
public void exit(int status) //停止虚拟机
public int availableProcessors() //获得CPU的线程数
public long maxMemory() //JVM能从系统中获取总内存大小(单位byte)
public long totalMemory() //JVM已经从系统中获取总内存大小(单位byte)
public long freeMemory() //JVM剩余内存大小(单位byte)
public Process exec(String command) //运行cmd命令
Runtime不可new,只能用getRuntime方法:
// 1.获取Runtime的对象
Runtime r1 =Runtime.getRuntime();
停止虚拟机(System.exit本质上就是调用这个方法):
//2.exit 停止虚拟机
Runtime.getRuntime().exit(0);
获取系统相关信息:
//3.获得CPU的线程数
System.out.println(Runtime.getRuntime().availableProcessors());
//4.总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);
//5.已经获取的总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);
//6.剩余内存大小
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);
运行cmd命令:
//7.运行cmd命令
//shutdown :关机
//加上参数才能执行
//-s :默认在1分钟之后关机
//-s -t 指定时间 : 指定关机时间
//-a :取消关机操作
//-r: 关机并重启
Runtime.getRuntime().exec("shutdown -s -t 3600");
Object
Object类所在包是java.lang包。Object 是类层次结构的根,即顶级父类,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类;换句话说,该类所具备的方法,其他所有类都继承了。
常用方法:
public String toString() //返回该对象的字符串表示形式(可以看做是对象的内存地址值)
public boolean equals(Object obj) //比较两个对象地址值是否相等;true表示相同,false表示不相同
protected Object clone() //对象克隆
补充:
toString()方法,是将对象所属类所在的位置拼上@再拼上地址值;
有时候,我们不想要Object的toString()方法,就可以重写,IDEA中Alt+Ins快速重写。
对于equals方法也是一样的,比较的是地址值,不想这么比,就可以重写;
以之前的Student类为例:
//对toString的重写
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
//对equals的重写
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(age, student.age); // 比较的是对象的name属性值和age属性值
}
克隆
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制。克隆分为两种,浅克隆和深克隆。
浅克隆:
不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来。基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值。也就是没有在堆里面开新的空间。Object类默认的是浅克隆。
问:下面的代码有问题吗?
public class Test3 {
public static void main(String[] args) {
Student s1 = new Student("zhangsan",'男',18);
Object clone = s1.clone();
}
}
有的,你可能会奇怪s1不是默认的Object对象,为什么调用不了?实际上源码里protected修饰的表示其子类和所在包的类可以调用,这个s1是Student对象,那么它只能在Student这个类里面调用父类的clone方法,而不是Test3这个类的main函数里;
所以,为了使它在测试类中可以使用,需要重写:
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
这样就可以在测试类调用了;
但是你运行会发现报错:java.lang.CloneNotSupportedException
这是因为,你想要某个类可克隆,则必须要让他实现Cloneable接口,否则不可克隆;
然而打开Cloneable这个接口,你会发现这是一个空的接口:
它的注释是这么写的:
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
大意是说这个接口是用来指明对于Object.clone()来说,实现这个接口的类是合规的,也就是所谓的标记性接口;
深克隆
深克隆在内存上看,他是在堆里创建一个新的空间,把被克隆对象堆空间复制一份到新空间中去,然后在栈里面记录新的空间地址;
深克隆可以考虑第三方工具gson实现:现将对象转换为字符串,再变回去就克隆成功了;
补充:关于字符串
字符串一旦定义,是不允许修改的,那么为什么在平常的编程中我们可以任意修改String变量?
实际上,字符串类在Java中被final修饰,即它不可以有子类,创建的字符串被它以char数组形式存储,而对于这个数组它用了private修饰,且没对外提供访问和修改接口,因此说它存的内容是不可变的;而你重新的赋值相当于在堆里面创建了新空间,接着把内容存进去,最后再去拿这个变量的地址值改成新空间的地址;
Objects
工具类,Objects类所在包是在java.util包下,因此在使用的时候需要进行导包。并且Objects类是被final修饰的,因此该类不能被继承,Objects类提供了一些对象常见操作的方法。比如判断对象是否相等,判断对象是否为null等等。
public static String toString(Object o) // 获取对象的字符串表现形式
public static boolean equals(Object a, Object b) // 比较两个对象是否相等
public static boolean isNull(Object obj) // 判断对象是否为null
public static boolean nonNull(Object obj) // 判断对象是否不为null
对于Objects.equals (),它会自动先判断有没有空,有空直接返回false;没有则调用 a对象的equals方法;
对于isNull:对于引用类型,只要没创建对象,就返回false ,nonNull类似地,但是和isNull反过来;