Java--常用API(1)

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]);
            }

        }

    }

注意:

  1. 若原数组和目标数组均为基本数据类型数组,则两者类型必须保持一致; 
  2. 注意数组长度,目标数组长度不能小于原数组要拷数据长度,否则数组越界错误;
  3. 如果数组是引用数据类型,则子类类型可以赋值给父类(有点像多态了)

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反过来;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值