【Java】常用API及底层原理剖析

目录

前言

一.Math类

二.System类

三.Object类

1.toString

2.equals

3.clone

3.1浅克隆

3.3深克隆

四.Objects类

五.BigInteger类

六.BigDecimal类

七.包装类

八.Arrays类

九.Lambda表达式

十.JDK8时间类

1.Date类

2.日期格式化类

3.Calendar日历类

4.时间间隔工具类


前言

API(Application Programming Interface):应用程序编程接口
简单理解:API就是别人已经写好的东西,我们不需要自己编写,直接使用即可.

JDK中提供的各种功能的类
java.lang包使用中不需要导包

在本章中,我们将讨论:

  • Math
  • System
  • Object
  • Objects
  • BigInteger
  • BigDecimal
  • 包装类
  • Arrays
  • Lambda表达式
  • JDK8时间类

一.Math类

首先我们要知道,一个类中应该有成员变量,构造方法,成员方法等,当一个类中的成员方法被static修饰后,就不需要创建这个类的对象,可以直接用类名.来调用,Math类就是这样的一种类,他的成员方法全部是用static修饰,可以直接使用Math.调用

成员变量

成员方法

补充
sqrt返回平方根,返回值是double类型
cbrt返回立方根,返回值是double类型

ceil往数轴正方向取整

floor往数轴反方向取整

二.System类

在介绍System类之前,我们简单了解一个小故事,是关于计算机中的时间原点的

成员方法

System.exit();

System.currentTimeMillis();获取1970年1月1日到现在有多少毫秒
作用:可以相减判断程序执行了多久

arraycopy()拷贝数组

拓展:
Arrays类中也有两个方法拷贝数组,传入参数不同,按需使用

三.Object类

Object是所有类的父类,所有类都继承他的方法

成员方法不是静态的,必须先创建对象,再用对象调用方法

1.toString

就是把一个对象变成字符串表现形式
sout源码就是一个toString方法

但在Object中,toString返回的是对象的地址值
当我们需要对象的成员变量属性值而不需要地址值的时候必须重写Object的toString方法
在重写的方法中,把对象的属性值进行拼接就好

在一个标准的JavaBean中,我们一般需要去重写toString方法来使他返回属性值而不是地址值

所以我们不重写toString的时候,用toString打印和直接sout打印的值一样

2.equals

比较地址值
需要比较属性值的时候需要重写方法

public boolean equals(Object obj) {
    return (this == obj);
}

这个方法只是检查两个对象是否是同一个对象(即引用是否相同).

注意:
在字符串String中的equals方法里,先判断传递的参数是不是一个String类型,如果不是,返回false
如果是再去比较属性值,因为String类里重写了equals方法

StringBuilder类里没有重写equals方法,使用的是Object方法,所以equals比较的是地址值

3.clone

把方法调用对象的属性值(成员变量)完全拷贝给另一个对象
注意克隆的是成员变量,成员方法没有被克隆.

要使用clone方法,对象的类必须实现Cloneable这个接口,Cloneable接口是一个标记性接口,没有定义任何方法,他的存在只是为了表明该类支持克隆操作.

public interface Cloneable{}//标记性接口

表示一旦实现了,那么当前类的对象就可以被克隆,没有实现当前类的对象就不能被克隆

public class User implements Cloneable{}//User类实现标记接口,表示可以被克隆

由于Object类中的clone方法是被protected修饰的,因此需要在子类中将其重写

方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去
书写步骤:
1.重写Object中的clone方法
2.让JavaBean类实现Cloneable接口
3.创建原对象并调用clone就可以了

User u2 = (User)u1.clone();//创建u2对象,把u1的属性值全部克隆给u2
3.1浅克隆

把u1引用数据类型地址值克隆给u2
u1的改变会影响u2
默认情况下,Object类的clone方法执行的是浅克隆,浅克隆会创建一个新的对象,并将原对象的所有成员变量复制到新对象中,对于基本数据类型,会创建新的副本,但对于引用数据类型,新对象中的引用将指向与原对象相同的对象

3.3深克隆

基本数据类型会直接复制
引用数据类型会在堆内存创建新的对象,赋值新的地址值
但是直接赋值(=)的字符串会在串池中,地址值不变,会复用.

四.Objects类

主要是用来做非空判断的

boolean result = Objects.equals(s1,s2);

equals底层会判断s1是否为null,如果为null,直接返回false
如果s1不为null,那么就会用s1调用Object中的equals方法
如果没有重写,比较地址值,如果重写了,比较属性值

五.BigInteger类

大整数
BigInteger类的对象一旦创建,不能被修改

构造方法,创建对象时使用

BigInteger bi1 = new BigInteger("9999999999");//当创建整数大于long类型的时候用
BigInteger bi2 = BigInteger.valueOf(99999);//当创建整数小于等于long类型的时候用

传递的字符串内容只能是整数
通过静态方法获取的大整数内部优化:
在内部提前把-16~16的整数先创建好BigInteger对象,如果多次获取就不会重新创建新的


成员方法


只要进行计算都会产生一个新的BigInteger对象


底层存储方式

在java中,整数有四种类型:byte1个字节,short 2个字节,int 4个字节,long 8个字节
1个字节byte = 8个比特bit

把大整数变成补码的形式,以32位为一组,把每组的十进制数字存到数组int[]mag
为什么是32位呢,因为数组的类型是int.int是4个字节,32个bit位,所以最多能存放int类型的十进制

成员变量:
int signum(存储大整数的正负号) -1 负 0/1 正
int [] mag 

六.BigDecimal类

大浮点数
BigDecimal类的对象一旦创建,不能被修改

当我们使用小数去进行计算的时候,会出现不精确的现象,为什么会这样呢?
让我们来看一下小数在计算机中是如何计算的

我们发现,小数部分在转换成二进制的时候位数是很庞大的,而java中存放小数的类型只有float和double,而他们给小数部分存放位数的bit位往往没有那么大,所以多出来的位数就会被省略,从而导致数据不精确

所以BigDecima的作用不但可以表示很大的小数,而且用做小数的精确计算

同样的,当我们要创建BigDecima对象的时候
如果要表示小数长度不超过double的时候,可以用BigDecimal类的静态方法去获取对象

BigDecimal bd = BigDecimal.valueOf(0.32);//当创建小数小于double的时候

当要表示小数长度超过double的时候,要用构造方法创建BigDecimal对象

BigDecimal bd = new BigDecimal("0.3222222");//当创建小数大于double的时候

构造方法可以传递字符串也可以传递小数和整数,但返回结果也会不精确,所以建议只传递字符串

同样的,java在BigDecima的静态方法内部也提前把0~10的整数先创建好BigDecima对象,如果多次获取就不会重新创建新的,注意是整数


成员方法


底层存储

遍历字符串,得到每一个字符,转换成asc码,存储到数组(byte类型的数组)中

七.包装类

基本数据类型对应的引用数据类型.
就是把基本数据类型变成对象

JDK5以前创建包装类对象

包装类没有构造方法,只能通过静态方法创建对象

Integer i = Integer.valueOf(10);

底层原理



这种方法虽然可以正常打印127,但在Java 10 及更高版本中被删除,因为是new出来的,会浪费空间


JDK5以后创建包装类对象

把Integer和int看成一个东西就行,会在底层自动完成装箱拆箱的操作
自动装箱:把基本数据类型自动变成其对应的包装类
自动拆箱:把包装类自动变成其对应的基本数据类型

Integer i = 10;//自动装箱

在底层,还会调用valueof静态方法得到一个Integer对象,只不过这个动作不需要我们自己去操作了

Integer i = Integer.valueOf(10);
int i1 = i;//自动拆箱

成员方法

八.Arrays类

成员方法

sort(数组,规则)

规则Comparator是一个匿名内部类

sort的底层原理是算法中的快速排序
sort(数组,规则)这个方法的底层原理是利用插入排序+二分查找的方式进行排序的,接下来我们梳理一下sort(数组,规则)这个方法的底层原理

o1:表示无序列表中的元素
o2:表示有序列表中的元素

第一个0索引元素是有序序列
遍历无序序列,取出第一个元素和有序序列比较,用o1(无序元素)-o2(有序元素)
前<----------------后
结果如果是负数,表示o1<o2,取出的无序元素小,要放到前面
结果如果是正数,表示o1>o2,取出的无序元素大,要放到后面
结果如果是0,表示o1=o2,取出的无序元素和有序元素相等,也要放到后面
当有序元素越来越多的时候,o1就会利用二分查找来和中间的元素比较

结论:
o1-o2,升序
o2-o1,降序

九.Lambda表达式

简化匿名内部类

如果只有一个参数,那么()也可以省略

十.JDK8时间类

JDK7的时间类对象会发生改变,多线程环境下会导致数据安全问题
所以我们只了解JDK8的时间类即可

JDK8时间日期对象都是不可变的,改变时间会产生新的时间类对象

1.Date类

ZoneId类
成员方法

Instant类
成员方法

ZoneDateTime类
成员方法

2.日期格式化类

DateTimeFormatter类

解析:字符串->日期类

格式化:日期类->字符串

3.Calendar日历类

日历类(最常用)

LocalDate 年月日
LocalTime 时分秒
LocalDateTime 年月日时分秒


成员方法

转换

4.时间间隔工具类

成员方法
静态方法between(date1,date2)

Period用get获取间隔
Duration用to获取间隔

重点掌握ChronoUnit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值