【Java基础】API高级

Object类

类层次结构的根。所有类都默认继承Object类。

public String toString()

返回对象的字符串表达形式。

  • 直接打印对我们意义不大,一般是重写toString()以便返回对象的内容。
  • 重写方法:①右键-generate-toString(),②写toS自动生成。

public boolean equals(Object o)

指示某个其他对象是否“等于”此对象。

  • 默认是判断两个对象的地址是否相等。但在开发中,这个功能用“==”也能实现。
  • 在开发中也是为了让子类重写,比较两个对象的内容一样。
  • 重写方法:写eq自动生成,反复回车即可。
  • 原理:比较者是this,被比较者是o。①首先判断两个对象是否地址一样,一样直接返回true,②判断o是null直接返回false,或者比较者和被比较者的类型不同,返回false,③o不是null,且o一定是相同类型的对象,就开始比较内容。将o强制转换为比较者类型,然后比较。

public String clone()

创建并返回对象的副本。

  • 由protected修饰,也就是只能在当前包(java.lang)、Object子类中才能访问。
  • 要使用clone()方法,必须要在子类中重写该方法。再通过它中转调用父类的克隆方法。
  • 重写方法:在子类中输入“clon”自动创建。这里是super去调用父类Object。克隆出来返回Object对象。
  • 注意:不是所有类都能克隆。克隆的话还要让子类实现一个接口(implements Clonable)。这个接口里面啥都没,称为标记接口(规则)。实例调用clone()的时候会报错,暂时可以“Alt+Enter”选择第一个,此时自动在main方法后面加上了“throws CloneNotSupportedException”。

Java中有两种克隆:浅克隆(上述)、深克隆。

  • 浅克隆:拷贝出的新对象和原对象中的数据一模一样(引用类型拷贝的只是地址,所以指向的是一样的内容)。
  • 深克隆:
    • 对象中的基本类型的数据直接拷贝
    • 对象中的字符串数据拷贝地址
    • 对象中包含的其他对象,不拷贝地址,创建新对象

Objects类

一个工具类,提供了很多操作对象的静态方法。

equals(Object a, Object b)

先做非空判断,再比较两个对象。

  • 为什么官方选择Objects.euqals(s1,s2)而不是s1.equals(s2)呢?避免s1为null时的报错。

isNull(Object obj)

判断对象是否为null,为null返回true,反之。

  • 其实和“对象==null”效果一样,看起来高级。

nonNull(Object obj)

判断对象是否为null,为null返回true,反之。

  • 其实和“对象!=null”效果一样,看起来高级。

包装类

为什么要有?

  • 因为基本类型数据不是对象。为了实现“万物皆对象”,所以使用包装类用来把基本类型的数据包装成对象。
基本数据类型 对应的包装类(引用数据类型)
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

如何包装的?

  • valueOf(int i):例如,Integer a1 = Integer.valueOf(12);

Java中为了方便把基本类型的数据转换成对象,提供了两种方案:

  1. 自动装箱机制(自动把基本类型数据转换为对象)。例如,Integer a2 = 12;
  2. 自动拆箱(自动把包装类型对象转换为基本数据类型)。例如,int a3 = a2;

为什么重要?

  • 泛型和集合不支持基本数据类型,只支持引用数据类型。例如,Arraylist对而Arraylist错误。

包装类有什么特殊的方法

  1. 把基本类型的数据转换为字符串类型。例如,Integer a = 23; String rs1 = Integer.toString(a);和String rs2 = a.toString();的效果一样。(也可以用String rs3 = a + “”,所以这个方法应用不多。)

  2. 字符串类型的数值转换成数值本身对应的数据类型。例如,String ageStr = “29”; int ageI = Integer.parseInt(ageStr);//String scoreStr = “99.5”; double score = Double.parseDouble(scoreStr );。这样其实是麻烦的,直接使用valueOf,例如,int ageI = Integer.valueOf(ageStr);只需要记住一个函数即可。

    注意:转换前的数值一定要是对应类型,否则报错。

StringBuilder类

可变字符串对象。相当于一个容器,里面装的字符串是可以变的。用来操作字符串。

为什么要有(好处)?

  • 比String更适合做字符串修改的操作,效率更高,代码更简洁。

构造器

  1. 无参构造器。public StringBuilder()。创建一个空白的可变字符串对象,不包含任何内容。
  2. 有参构造器。public StringBuilder(String str)。创建一个指定字符串内容的可变字符串对象。

常用方法

  1. public StringBuilder append(任意类型)。添加数据并返回StringBuilder 对象本身。

    拼接内容。支持链式编程,例如,s.append(666).append(“hello”);。

  2. public StringBuilder reverse()。将对象的内容反转。

    反转操作。

  3. public int length()。返回对象内容长度。

  4. public String toString()。把StringBuilder对象又转换成String类型。

为什么操作字符串建议使用StringBuilder,而不用原来学过的String?

  • 效率高。
  • 对于字符串相关操作,如果频繁拼接、修改等,建议用StringBuilder,效率高。如果字符串较少,或者不需要操作,以及定义字符串变量,建议用String。

案例

设计一个方法,用于返回任意整型数组的内容,要求返回的数组内容格式如下:[11, 22, 33]。(需要用if判断是否到最后一个元素以确定数字后面的符号。)

StringBuffer类

与StringBuilder用法一样。但是StringBuilder是线程不安全的,StringBuffer是线程安全的。(就是很多人进入系统来用StringBuffer编程时不会出bug。)

StringJoiner类

解决的问题:StringBuiler虽然速度上去了,但是代码层面很麻烦(如前例,还要if来判断)。怎么高效、方便地拼接?

  • JDK8开始才有,和StringBuiler类似。
  • 好处:提高字符串的操作效率,在某些场景下代码更加简洁

构造器

  1. public StringJoiner(间隔符号)。创建StringJoiner对象,指定拼接时的间隔符号。
  2. public StringJoiner(间隔符号,开始符号,结束符号)。创建StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号。

常用方法

  1. public StringJoiner add(添加的内容)。添加数据,返回对象本身。
  2. public int length()。返回长度(字符串出现的个数)。
  3. public String toString()。返回一个字符串(该字符串就是拼接之后的结果)。

因此,可以将输出数组格式的代码简化。

Math类

数学,是一个工具类。提供对数据进行操作的静态方法。

常见方法

  1. public static int abs(int a)、public static double abs(double a)。获取参数绝对值。
  2. public static double ceil(double a)。向上取整。
  3. public static double floor(double a)。向下取整。
  4. public static int round(float a)。四舍五入。
  5. public static int max(int a, int b)。获取两个int值中的较大值。
  6. public static double pow(double a, double b)。返回a的b次幂的值。
  7. public static double random()。返回值为double的随机值,范围[0.0, 1.0)。

System类(了解)

程序所在的系统。工具类。

常见方法

  1. public static void exit(int status)。终止当前运行的Java虚拟机。
    1. 该参数用作状态代码;按照惯例,非零状态代码表示异常终止。
    2. System.exit(0); //人为地终止虚拟机(不要使用)。
  2. public static long currentTimeMills()。返回当前系统的时间毫秒值形式。从1970-1-1 0:0:0开始(小知识:为啥是这个时间开始?C语言的生日。)到此刻的毫秒值。
    1. 通常用作代码的性能分析。
    2. 想转换成秒数:time/1000.0。

Runtime类(了解)

程序所在的运行环境。是单例类。通过调用getRuntime()方法来得到对象。

常见方法

  1. public static Runtime getRuntime()。返回与当前Java应用程序关联的运行时对象。
  2. public void exit(int status)。终止当前运行的虚拟机。该参数用作状态代码。按照管理,非零状态码表示异常终止。(其实System类里面的exit方法就是调用的这里。)
  3. public int availableProcessors()。返回Java虚拟机可用的处理器数。
  4. public long totalMemory()。返回Java虚拟机中的内存总量。返回的是字节数,想看多少K,除以1024.0,多少M,再除以1024.0。
  5. public long freeMemory()。返回Java虚拟机中的可用内存。返回的是字节数。
  6. public Process exec(String command)。启动某个程序,并返回代表该程序的对象。
    1. 用法:拷贝exe程序的路径(右键-属性-安全-对象名称),作为参数传给exec。此时报异常,用“Alt+Enter”选第一个,自动抛出异常(在类定义处增加throw IOException)。程序就会帮我们打开指定的exe程序。
    2. 多说一点,可以直接传程序名,前提是系统环境变量里面配置程序的路径。
    3. 用Process类定义一个变量来接返回的程序对象,接到之后用destroy()方法关闭程序。

BigDecimal类

解决浮点型运算时,出现结果失真的问题(如,0.1+0.2的结果不是0.3)。

构造器

public BigDecimal(String val)。把String转成BigDecimal。是按照对应位置运算的。

常用方法

  1. public static BigDecimal valueOf(double val)。转换一个double成BigDecimal。
  2. public BigDecimal add(BigDecimal b)。加法。
  3. public BigDecimal substract(BigDecimal b)。减法。
  4. public BigDecimal multiply(BigDecimal b)。乘法。
  5. public BigDecimal devide(BigDecimal b)。除法。
  6. public BigDecimal devide(另一个BigDecimal对象,精确几位,舍入模式)。除法,可以控制精确到小数几位。
  7. public BigDecimal doubleValue()。将BigDecimal转换为double。
  • 推荐方式:使用时先toString()变成字符串对象,封装成BogDecimal对象,再运算。//或者调用valueOf进行简化。即BigDecimal a1 = new BigDecimal (Double.toString(a))简化为BigDecimal a1 = BigDecimal.valueOf(a)。
  • 做除法运算时,如果不能正好表达,就会报无法精确表达结果的错,所以就要用第二种除法方法。这只是解决精度问题的手段,最后还要转换为double类型的数据。
  • 注意:一般不用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象,因为存在精度损失风险,可能导致业务逻辑异常。有限推荐入参为String的构造方法,或者使用BigDecimal的valueOf方法,此方法内部执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断。

日期和时间(JDK8之前)

Date类

系统的日期和时间。(可以直接打印出来。)

构造器

  1. public Date()。 创建一个Date对象,代表的是系统当前此刻日期时间。
  2. public Date(long time)。 把时间毫秒值转换成Date日期对象。

常用方法

  1. public long getTime()。返回从1970年1月1日 00:00:00走到此刻的总的毫秒数。
  2. public void setTime(long time)。设置日期对象的时间为当前时间毫秒值对应的时间。

SimpleDateFormat类

简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式。

  • 允许格式化(日期-文本)、解析(文本-日期)和规范化。
  • 时间格式: xxxx-xx-xx xx:xx:xx。
  • 可以将Date或者时间毫秒值转化为上述格式。

构造器

public SimpleDateFormat(String pattern)。创建简单日期格式化对象,并封装时间的格式。可以自己看文档组装成想要的格式,例如,“yyyy-MM-dd HH:mm:ss EEE a”。

常用方法

  1. public final String format(Date date)。将日期格式化成日期/时间字符串。

  2. public final String format(Object time)。将时间毫秒值式化成日期/时间字符串。

    即,这个函数既可以扔进来一个SimpleDateFormat类,也可以直接扔进来系统时间毫秒值。

  3. public Date parse(String source)。把字符串时间解析成日期对象。

    使用:①创建SimpleDateFormat对象,指定的时间格式必须与被解析的时间格式一模一样;②把字符串扔到SimpleDateFormat对象中用parse()方法解析。此时还是要用“Alt+Enter”把异常抛出去。

常见符号

y年,M月,d日,H时,m分,s秒,EEE星期几,a上午/下午。

Calendar类

系统此刻时间对应的日历。

  • 通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。(注意月是从0开始的。)
  • 是一个抽象类。要用的话需要找它的子类(实现类)。
  • calendar是可变对象,一旦修改后其对象本身表示的时间将产生变化。

为什么要学习?

  • 从一个案例说起,需求是将2023年09月10日增加一个月。常用做法是:1、记住字符串,2、解析成Date日期对象,3、通过日期对象获取毫秒值,4、增加一个月的毫秒值,5、格式化得到结果。

常用方法

  1. public static Calendar getInstance()。获取当前日历对象。
  2. public int get(int field)。获取日历中的某个信息。例如,.get(Calendar .YEAR);
  3. public final Date getTime()。获取日期对象。
  4. public long getTimeInMillis()。获取时间毫秒值。
  5. public void set(int field,int value)。修改日历的某个信息。
  6. public void add(int field,int amount)。为某个信息增加/减少指定的值。

JDK8开始新增的日期、时间

为什么要学?(Java开发者的bug。)

  • JDK8之前传统的时间API:1、设计不合理,使用不方便,很多都被淘汰了。2、都是可变对象,修改后会丢失最开始的时间信息。3、线程不安全。4、只能精确到毫秒。
  • JDK8开始之后新增的时间API:1、设计更合理,功能丰富,使用更方便。2、都是不可变对象,修改后会返回新的时间对象,不会丢失最开始的时间。3、线程安全。4、能精确到毫秒、纳秒。

代替Calendar类

  1. LocalDate:本地日期(年、月、日、星期)。这是一个不可变对象。
    1. public static Xxxx now()。获取系统当前时间对应的该对象。
    2. public static Xxxx of(…)。获取指定时间的对象。例如,getYear()、getMonthValue()、getDayOfMonth()、getDayOfYear()、getDayOfWeek()等。
    3. withYear、withMonth、withDayOfMonth、withDayOfYear。直接修改某个信息,返回新日期对象。
    4. plusYears、plusMonths、plusDays、plusWeeks。把某个信息加多少,返回新日期对象。
    5. minusYears、minusMonths、minusDays,minusWeeks。把某个信息减多少,返回新日期对象。
    6. equals、isBefore、isAfter:判断两个日期对象,是否相等,在前还是在后 。LocalDate.of:获取指定日期的LocalDate对象。public static LocalDate of(int year, int month, int dayOfMonth)。
  2. LocalTime:本地时间(时、分、秒、纳秒)。这是一个不可变对象。
    1. public int getHour()、public int getMinute()、public int getSecond()、public int getNano()。获取小时、秒、纳秒。
    2. withHour、withMinute、withSecond、withNano。修改时间,返回新时间对象。
    3. plusHours、plusMinutes、plusSeconds、plusNanos。把某个信息加多少,返回新时间对象。
    4. minusHours、minusMinutes、minusSeconds、minusNanos。把某个信息减多少,返回新时间对象。
    5. equals、isBefore、isAfter:判断2个时间对象,是否相等,在前还是在后。
  3. LocalDateTime:本地日期、时间(年、月、日、星期、时、分、秒、纳秒)。这是一个不可变对象。
    1. 方法综合前两个。
    2. 特殊的:可以把LocalDateTime转换成LocalDate和LocalTime,使用toLocalDate()和toLocalTime()方法。而用LocalDateTime.of(LocalDate ld, LocalTime lt)可以再把它们合起来。
  4. ZoneId:时区Id。
    1. 常识:世界标准时间(UTC)是0时区,中国标准时间是世界标准时间(UTC) + 8小时。
    2. 表达方式:洲名/城市名,国家名/城市名。
    3. 常见方法:
      1. public static Set getAvailableZoneIds()。获取Java中支持的所有时区。(如果不记得时区Id怎么写可以调用这个看一下。)
      2. public static ZoneId systemDefault()。获取系统默认时区。然后可以用getId()方法/直接打印获取当前系统的默认时区。
      3. public static ZoneId of(String zoneId)。将指定时区Id封装成ZoneId对象。结合下面的ZonedDateTime使用。
  5. ZonedDateTime:带时区的时间。
    1. 常见方法:
      1. public static ZonedDateTime now() 。获取当前时区的ZonedDateTime对象。
      2. public static ZonedDateTime now(ZoneId zone) 。获取指定时区的ZonedDateTime对象。例如传入Clock.systemUTC()参数获取世界标准时间。
      3. getYear、getMonthValue、getDayOfMonth、getDayOfYeargetDayOfWeek、getHour、getMinute、getSecond、getNano。获取年月日、时分秒、纳秒等。
      4. public ZonedDateTime withXxx(时间) 。修改时间系列的方法。
      5. public ZonedDateTime minusXxx(时间) 。减少时间系列的方法。
      6. public ZonedDateTime plusXxx(时间)。增加时间系列的方法。

代替Date类

  1. Instant:时间戳/时间线。是一个不可变对象。
    1. 通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数 + 不够1秒的纳秒数。
    2. 可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点。传统的Date类,只能精确到毫秒,并且是可变对象;新增的Instant类,可以精确到纳秒,并且是不可变对象,推荐用Instant代替Date。
  2. 常用方法:
    1. public static Instant now()。获取当前时间的Instant对象(标准时间)。
    2. public long getEpochSecond()。获取从1970-01-01T00:00:00开始记录的秒数。
    3. public int getNano()。从时间线开始,获取从第二个开始的纳秒数 。
    4. plusMillis plusSeconds plusNanos。增加时间系列的方法。
    5. minusMillis minusSeconds minusNanos。减少时间系列的方法。
    6. equals、isBefore、isAfter。判断时间系列的方法。

代替SimpleDateFormat类

  1. DateTimeFormatter:用于时间的格式化和解析。(线程安全。)
  2. 常用方法:
    1. public static DateTimeFormatter ofPattern(时间格式)。获取格式化器对象。
    2. public String format(时间对象)。格式化时间。
    3. public String format(DateTimeFormatter formatter)。格式化时间。
    4. public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter)。解析时间。
  3. 正向格式化:formatter.format(now),反向格式化:now.format(formatter)。得到的结果是一样的。
  4. LocalDateTime提供的格式化、解析时间的方法:
    1. public String format(DateTimeFormatter formatter)。格式化时间。
    2. public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter)。解析时间。

其他补充

  1. Period:时间间隔(年,月,日)。用于计算两个 LocalDate对象相差的年数、月数、天。注意先写较前的时间,再写较后的时间。
    1. public static Period between(LocalDate start, LocalDate end)。传入2个日期对象,得到Period对象。
    2. public int getYears()。计算隔几年,并返回。
    3. public int getMonths()。计算隔几个月,年返回。
    4. public int getDays()。计算隔多少天,并返回。
  2. Duration:时间间隔(时、分、秒,纳秒)。计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间。
    1. public static Duration between(开始时间对象1,截止时间对象2)。传入2个时间对象,得到Duration对象。
    2. public long toDays()。计算隔多少天,并返回。
    3. public long toHours()。计算隔多少小时,并返回。
    4. public long toMinutes()。计算隔多少分,并返回。
    5. public long toSeconds()。计算隔多少秒,并返回。
    6. public long toMillis()。计算隔多少毫秒,并返回。
    7. public long toNanos()。计算隔多少纳秒,并返回。