AI智能
改变未来

Java 常用类总结(SE基础)

本篇博客对java常用类相关知识进行了归纳总结,比较详细,适用于学习和复习。

1. 字符串相关的类

1.1 String

String

是一个

final

类,代表不可变的字符序列。不可被继承。

String

对象的字符内容是存储在一个字节数组

byte[]

中。JDK1.8中存储的是

char[]

注意区别。

  • String

    实现了

    Serializable

    接口,支持序列化

  • 实现了
    Comparable

    接口,表示可以比较大小

  • 通过字面量的方式(区别于
    new

    )给一个

    String

    赋值,此时的字符串值在字符串常量池中(和方法区在同一个地方)

  • 当
    String

    进行连接操作、重新赋值、

    replace()

    等操作时,会重新指定内存区域赋值,不使用原有的

    value

    进行赋值

String str = \"hello\";  //字面量赋值String s1 = new String();//本质上为,this.value = new byte[0]String s2 = new String(String str); //放一个String类型的参数String s3 = new String(byte[] a);String s3 = new String(byte[] a,int off,int length);//构造方法,放char[]也是可以的

考虑如下代码:

String s1 = \"javaEE\";String s2 = \"javaEE\";String s3 = new String(\"javaEE\");String s4 = new String(\"javaEE\");

这里,

s1==s2

为

true

,

s1==s3

,

s1==s4

,

s3==s4

均为

false

原因如下:

实际上,通过构造方法来构造

String

会指向

value

,而

value

再去指向字符串常量。

即

String s3 = new String(\"javaEE\");

在内存中创建了两个对象:一个是堆中的

value

结构,一个是常量池中的字符串数据。

  • intern()

    返回字符串对象的规范表示。 这里会返回一个字符串常量。内存空间在常量池中。

另外,有一个关于形参实参方面的需要注意:

public class StringTest {String str = new String(\"hello\");char[]ch = {\'t\',\'e\',\'s\',\'t\'};public void change(String str,char ch[]){str = \"hello,world\";ch[0]=\'b\';}public static void main(String[] args) {StringTest st = new StringTest();st.change(st.str, st.ch);System.out.println(st.str);System.out.println(st.ch);}}

这里的结果为:\”hello\” /n \”best\”

类似于C语言中,根据指针进行交换两个指针中的内容,值传递过程中,实际参数的值传入形参,形成副本,方法结束后形参消失,实际参数值并没有改变。

另外还有一点需要注意:

String str = null; //这个指针指向null,并没有实例化System.out.println(str);//输出”null“System.out.println(str.length());//异常

1.2 String的常用方法

将

String

的常用方法总结如下(未总结的请自己查阅):

同时还需要注意的一些方法如下,重要程度依次降低,但仍需掌握:

注意:上表下部的4个

int

方法如果未找到,返回的均为-1

再举例一些方法(一些可能不太常用的):

String regex

一般都用正则表达式表示

String转换为基本数据类型或包装类

调用包装类的静态方法:对应的类型,如要转

int

,调用

Integer.parseInt(str)

基本数据类型、包装类转为String

调用

String

重载的

valueOf(xxx)

另外

int num = 100;String str = num+\"\";  //存在变量才会返回堆中,如果常量相加则会返回常量池

这样也可以转换为

String

,但是需要注意,该类型是在堆中生成了

value

数组,和

new String

的方式类似。

String与char[], byte[]的相互转换

String

–>

char[]

:调用

String.toCharArray

即返回了一个

char[]

char[]或byte[] --> String

:直接调用构造器

String

–>

byte[]

:调用

String.getBytes

即返回了一个

byte[]

,使用默认的字符集(例如\”gbk、utf-8\”等)进行转换。

getBytes(Charset charset)

使用给定的

charset

将该

String

编码为字节序列,将结果存储到新的字节数组中。不同的编码方式返回的可能不同。

1.3 StringBuffer与StringBuilder

String

与

StringBuffer, StringBuilder

之间的异同?

String

:不可变的字符序列,注意理解不可变性

StringBuffer

:56c可变的字符序列,线程安全,效率较低(都是同步方法)

StringBuilder

:jdk5.0新增,可变的字符序列,线程不安全,效率高

final byte[] value  //String中的byte[] value  //StringBuffer和StringBuilder中的

StringBuffer

String str = new String();// new char[0]String str1 = new String(\"abc\");//new char[] {\'a\',\'b\',\'c\'};StringBuffer sb = new StringBuffer();//new char[16] 初始容量为16sb.append(\'a\');// value[0]=\'a\';依次进行StringBuffer sb1 = new StringBuffer(\"abc\");//new char[\"abc\".length()+16]System.out.println(sb.length()); //return的是count,每append操作count+=len,这里为1,并不是value.length

接下来看

StringBuffer

的扩容机制

简述:一般情况下,若容量不够的时候,扩充为原来容量的2倍+2,同时将原有数组的元素复制到新数组中

JDK15中,源码已经改变,为:

private int newCapacity(int minCapacity) {int oldLength = value.length;int newLength = minCapacity << coder;int growth = newLength - oldLength;int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder));if (length == Integer.MAX_VALUE)56c{throw new OutOfMemoryError(\"Required length exceeds implementation limit\");}return length >> coder;}

ArraysSupport.newLength

这里就是比较

growth

和

oldLength + (2 << coder)

谁大,大者加上

oldLength

(这样就成了2倍+2)。这里coder原始值为0,我只看了

append

相关源码,

coder

值并没有变,其他源码没有看,注意可能发生改变。

JDK1.8中是直接进行移位操作+2的,现版本已更新。

StringBuffer常用方法

StringBuilder

的API与之相同,只是线程不安全,没有保证同步。

2. 日期时间

2.1 JDK8之前的日期时间

java.lang.System

中的

static long currentTimeMillis()

返回当前时间与1970年1月1日00:00:00之间的时间差(以毫秒为单位)。适用于计算时间差。(时间戳)

计算世界时间的主要标准有:

UTC

,

GMT

,

CST

java.util.Date

java.sql

中也有一个

Date

类,是java.util.Date的子类

表示特定的时间,精确到毫秒

两个构造器的使用:

构造器一: 创建一个当前时间的

Date

对象

Date date = new Date();System.out.println(date);//sout自带.toString,输出:Mon Apr 26 01:16:00 CST 2021System.out.println(date.getTime());//返回当前date对象对应的时间戳//Date中的无参构造源码public Date() {this(System.currentTimeMillis());}

构造器二: 创建了一个指定时间的

Date

对象

Date date1 = new Date(1619371381884L); //随便找了个时间戳System.out.println(date1);

构造器的其余方法均已过时,不建议使用。

java.sql.Date

对应的是数据库中的日期时间类,一般在数据库交互时使用

java.sql.Date date2 = new java.sql.Date(1619371381884L); //2021-04-26System.out.println(date2);

该类没有无参构造。输出形式不同。

两种

Date

互转:

Date date3 = (Date)date2;  //子类转父类System.out.println(date3);java.sql.Date date4 = new java.sql.Date(new Date().getTime()); //父类转子类,不能强制类型转换

ad0

java.text.SimpleDateFormat

允许进行格式化:日期–>文本,解析:文本–>日期

格式化:

解析:

Date parse(String text,  ParsePosition pos)

从字符串中解析文本以产生一个

Date

。

pattern

举例如下图:

demo1默认模式

:

SimpleDateFormat sdf = new SimpleDateFormat();Date date = new Date();String format = sdf.format(date);System.out.println(date); //Mon Apr 26 02:38:11 CST 2021System.out.println(format); //2021/4/26 上午2:38//解析过程String str = \"2021/4/16 上午12:38\";  //格式有要求Date date1 = sdf.parse(str);System.out.println(date1); //Fri Apr 16 00:38:00 CST 2021

使用指定模式:

SimpleDateFormat sdf1 = new SimpleDateFormat(\"yyyy,MM,dd HH:mm:ss aaa\");String str2 = sdf1.format(date);System.out.println(str2); //2021,04,26 02:47:22 上午//解析的话也需要按这种模式进行,正常模式通常为”yyyy-MM-dd hh:mm:ss“String str3 =\"2021,04,26 02:47:22 上午\";Date date2 = sdf1.parse(str3);System.out.println(date2); //Mon Apr 26 02:47:22 CST 2021

Calendar

Calendar

是一个抽象类,主要用于完成日期字段之间的相互操作。

Calendar

提供了一种类方法

getInstance

,用于获取此类型的一般有用的对象。

Calendar

的

getInstance

方法返回一个

Calendar

对象,其日历字段已使用当前日期和时间进行初始化:

Calendar rightNow = Calendar.getInstance();

调用了它的子类

GregorianCalendar

的构造器

Calendar calendar = Calendar.getInstance();System.out.println(calendar.getClass());//class java.util.GregorianCalendar

Calendar

对象可以产生实现特定语言和日历风格的日期时间格式化所需的所有日历字段值(例如日语 – 公历,日语 – 繁体)。

Calendar

定义某些日历字段返回的值的范围及其含义。 例如,日历系统第一个月的值为

MONTH == JANUARY

为所有日历。 其他值由具体的子类定义,如

ERA

。 有关详细信息,请参阅各个实体文档和子类文档。

常用方法:

void set(int field,  int v1044alue)

将给定的日历字段设置为给定的值。

void add(int field,  int amount)

根据日历的规则,将指定的时间量添加或减去给定的日历字段。

final Date getTime()

返回一个

Date

表示此物体

Calendar

的时间值

void setTime(Date date)

使用给定的

Date

设置此日历的时间

demo

如下:

Calendar calendar = Calendar.getInstance();//getint i = calendar.get(Calendar.DAY_OF_MONTH);System.out.println(i);//获取这个月的第几天,本实例为26,当前时间4/26System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//类似上一个//setcalendar.set(Calendar.DAY_OF_MONTH,12);int j = calendar.get(Calendar.DAY_OF_MONTH);  //12,改变了System.out.println(j);//addcalendar.add(Calendar.DAY_OF_MONTH,3);j = calendar.get(Calendar.DAY_OF_MONTH); //15,还是改变,增加3天System.out.println(j);//getTimeDate date = calendar.getTime(); //Thu Apr 15 03:10:28 CST 2021,返回时间戳System.out.println(date);//setTime:Date --> Calendarcalendar.setTime(date);//直接操作当前对象int days = calendar.get(Calendar.DAY_OF_MONTH);  //15System.out.println(days);

获取月份时,一月是0;获取星期几时,周日是1

2.2 JDK8中的日期时间

因为之前的类具有4个问题:

  • 可变性:例如
    Calendar

    的

    set

    ,它们都是可变的

  • 偏移性:
    Date

    中的年份都是从1900开始,月份从0开始,如果调用有参构造,会发生偏移。

  • 格式化:格式化只对
    Date

    有用,对于

    Calendar

    则不行

  • 线程不安全

java8中的java.time API已经纠正了过去的缺陷。

时间日期的相关packge:

LocalDate

,

LocalTime

,

LocalDateTime

是其中比较重要的几个类,他们的实例均为不可变实例,使用

ISO-8601

日历系统。

ISO-8601

日历系统是国际标准话组织制定的现代公民的日期和时间的表示法(公历)

相关方法:

上面四个层次其实就是构造、get、set、加减操作。和

Calendar

类似。

localDate

是一个

final

类,有构造方法,类似

String

,

Math

,举例当前时间生成:

LocalDate localDate = LocalDate.now();  //2021-04-27LocalTime localTime = LocalTime.now();  //19:24:37.171676500LocalDateTime localDateTime = LocalDateTime.now();  //2021-04-27T19:24:37.171676500

举例设置指定时间:

LocalDateTime localDateTime1 = LocalDateTime.of(2020,10,6,13,12,13);//2020-10-06T13:12:13

举例相关

get

操作:

System.out.println(localDateTime.getMonth()); //APRILSystem.out.println(localDateTime.getMonthValue()); //4

这里的月份是从1开始的。

.with

操作(设置相关属性):

LocalDate localDate1 = localDate.withDayOfMonth(22); //2021-04-22System.out.println(localDate);  //2021-04-27System.out.println(localDate1);

locatDate

实例本身并没有发生变化(不可变性)。

加减操作:

LocalDate localDate2 = localDate.plusDays(4); //localDate为4-27System.out.println(localDate225f4);//2021-05-01//减的话即将Plus换位minus

2.3 Instant(瞬时)

时间线上的一个瞬时点,可能用来记录应用程序中的事件时间戳。

同样是起始于1970年1月1日00:00:00的一个时间戳(纳秒级)。

相关方法:

时间标准主要有:UTC, GMT, CST,UTC时间与伦敦本地时间相同,与北京相差8个小时(早了8个小时)

Instant instant = Instant.now();System.out.println(instant); //2021-04-27T11:45:00.321544Z,实际时间19:45,相差8个小时

偏移应用:

OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));System.out.println(offsetDateTime);  //2021-04-27T19:48:17.448368100+08:00

返回时间戳(毫秒数):

System.out.println(instant.toEpochMilli());//1619524168468

设置特定时间,和

Date

类似:

Instant instant1 = Instant.ofEpochMilli(1619524168468L);  //2021-04-27T11:49:28.468Z,这里的时间就是毫秒级的了System.out.println(instant1);

2.4 DateTimeFormatter

三种预定义的标准格式:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;//格式化:日期-->字符串LocalDateTime localDateTime = LocalDateTime.now();String str = dateTimeFormatter.format(localDateTime);  //将当前时间格式化System.out.println(str); //2021-04-27T19:59:19.0153049//解析:字符串-->日期TemporalAccessor temporalAccessor = dateTimeFormatter.parse(\"2021-04-27T19:59:19.0153049\");System.out.println(temporalAccessor);//{},ISO resolved to 2021-04-27T19:59:19.015304900

本地化相关的格式:

DateTimeFormatter format = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);//SHORT 2021/4/27 下午8:09,  MEDIUM  2021年4月27日 下午8:10:02,// 在java15中LONG会异常,1.8不会,DateTime中没有FULL,Date中有String str1 = format.format(localDateTime);System.out.println(str1);

自定义格式(类似于

SimpleDateFormat

):

DateTimeFormatter format = DateTimeFormatter.ofPattern(\"yyyy-MM-dd hh:mm:ss\");String str1 = format.format(localDateTime); //2021-04-27 08:21:52System.out.println(str1);TemporalAccessor temporalAccessor1 = format.parse(str1);System.out.println(temporalAccessor1);//{MicroOfSecond=0, HourOfAmPm=8, MilliOfSecond=0, NanoOfSecond=0, MinuteOfHour=21, SecondOfMinute=52},ISO resolved to 2021-04-27

解析同上面即可,注意解析时需要一个

TemporalAccessor

转承。

其他的一些API(不再详细赘述):

以上三种

Date

之间的转换:

3. 比较器

这里牵扯到对象的比较

实现

Comparable

接口(自然排序),重写

compareTo()

方法,重写的规则是:当前对象this大于形参对象obj,返回正整数;this小于,返回负整数;this等于,返回0;

使用

Comparator

接口(定制排序)

适用于该类型没有实现

Comparable

接口,且不方便修改代码;或者实现了

Comparable

接口但是排序规则不适合当前操作

对比:

  • Comparable

    接口的方式可以保证类的对象在任何位置都可以实现比较

  • Comparator

    接口属于临时性的比较

关于应用在之前的博客中已有实现,可参考

(Set, Map, Collections工具类)JAVA集合框架二

4. System, Math, BigInteger 和 BigDecimal

4.1 System

java.lang.System

成员变量:in, out ,err三个,分别代表标准输入流(键盘输入),标准输出流(显示器),标准错误输出流(显示器)

static long currentTimeMillis()

返回当前时间(以毫秒为单位)。表达格式同时间戳。

static void exit(int status)

终止当前运行的Java虚拟机。

status

为0时代表正常退出,非零则为异常退出。

static void gc()

运行垃圾回收器。请求系统进行垃圾回收。

static String getProperty(String key)

获取指定键指示的系统属性。对于常用的

key

:

4.2 Math

以上为

Math

常用方法总结。可见开发文档。

4.3 BigInteger与BigDecimal

BigInteger

构造方法:

BigInteger

提供所有java的基本整数操作符的对应物,并提供

java.lang.Math

的所有相关方法,另外,还提供一下运算:模算术,GCD计算,质数测试,素数生成,位操作等。

BigDecimal

Float

和

Double

的精度不能满足用户需求时,可以使用

BigDecimal

构造方法:

BigDecimal(double val)

将

double

转换为

BigDecimal

,这是

double

的二进制浮点值的精确十进制表示。

BigDecimal(String val)

将BigDecimal的字符串表示

BigDecimal

转换为

BigDecimal

。

还有很多,只举例了两种常用的。

加减乘除操作类似于

BigInteger

,说明一下

devide

:

scale

即保留多少位小数,上下文设置用的不多不再赘述。

几种舍入模式:

其中,有些翻译不够准确,解释一下:

ROUND_UP

,即向上舍。0.1203456789,当精度为3的时候,按照

ROUND_UP

模式,结果是0.121

ROUND_DOWN

即向下舍。

而

ROUND_HALF_EVEN

,像邻近的偶数方向舍。

这几个可以参考对应英文进行理解。

4.4 个人总结的其他类

其实经常用到的还有

Ramdom

,生活中经常用到随机数。

例如取一个随机整数。

Random r1 = new Random();int i = r1.nextInt(100); //取0到100的随机整数,无 100

其他方法都是与之类似的,具体可参考开发文档。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Java 常用类总结(SE基础)