【左京淳的JAVA学习笔记】第七章 API

API(application program interface)是指程式之间具有特定规範的接口。透过这些接口可以引用其他程式来协助完成整体机能。
其实JAVA当中引用package或class的概念也与此相同。以下介绍常见的class及其method:

java.lang.ObjectDate and TimeCollection&Lambda式

Object是java中所有class的父类。
里面提供了一些通用方法

method名说明boolean equals(Object obj)比较是否为同一个物件final Class<?> getClass()返回此物件的classint hashCode()返回此物件的hashCode值String toString()返回物件的描述文字列。

範例:

class Foo {}class Sample7_1 {  public static void main(String[] args) {    int[] ary = {1,2,3};    Class obj1 = ary.getClass();    System.out.println(obj1.getName());    Foo foo = new Foo();    Class obj2 = foo.getClass();    System.out.println(obj2.getName());  }}

执行结果

[IFoo

本範例中使用getClass()取得实例化物件的来源class后,再使用getName()方法得到class的名称。
结果的第一行中,"["表示阵列,"I"则表示int型态。合起来即为储存int资料的阵列。
Foo则为class名称。

equals()方法

Object class里面的equals()方法用来比较两个物件是否为同一个。然而在String类中,这个方法却被用来比较值是否相等。
这是因为equals()方法在String类中被覆写了的关係。
下面几个範例,比较equals()在String,StringBuilder及Integer类中的不同。

String类的equals()方法

class Sample7_2 {  public static void main(String[] args) {    String s1 = "Tom";    String s2 = new String("Tom");    String s3 = "tom";    System.out.println("s1 == s2 : " + (s1 == s2));    System.out.println("s1.equals(s2) : " + s1.equals(s2));    System.out.println("s1.equals(s3) : " + s1.equals(s3));    System.out.println("s1.equalsIgnoreCase(s3) : " + s1.equalsIgnoreCase(s3));  }}

执行结果

s1 == s2 : falses1.equals(s2) : trues1.equals(s3) : falses1.equalsIgnoreCase(s3) : true

说明
s1与s2不是同一个物件,返回false
s1与s2的值相同,返回true
s1与s3的大小写不同,返回false
忽略大小写,返回true

StringBuilder类的equals()方法

class Sample7_3 {  public static void main(String[] args) {    //StringBuilder sb1 = "Tom";   //error    StringBuilder sb2 = new StringBuilder("Tom");    StringBuilder sb3 = new StringBuilder("Tom");    System.out.println("sb2 == sb3  :" + (sb2 == sb3));    System.out.println("sb2.equals(sb3)  :" + sb2.equals(sb3));    System.out.println("sb2.toString().equals(sb3.toString())  :" + sb2.toString().equals(sb3.toString()));  }}

执行结果

sb2 == sb3  :falsesb2.equals(sb3)  :falsesb2.toString().equals(sb3.toString())  :true

说明
"==" 比较是否为同一物件,传回false。
StringBuilder的equals()未被覆写(跟Object类一样),比较是否为同一物件,传回false。
要比较StringBuilder的值,可以运用toString()方法转为String物件后,即可用equals()进行比较,传回true。

Integer类的equals()方法

class Sample7_4 {  public static void main(String[] args) {    Integer val1 = 1;    Integer val2 = 1;    System.out.println("val1 == val2  :" + (val1 == val2));        Integer val3 = 150;    Integer val4 = 150;    System.out.println("val3 == val4  :" + (val3 == val4));    System.out.println("val3.equals(val4)  :" + val3.equals(val4));        Integer val5 = new Integer(1);    System.out.println("val1 == val5  :" + (val1 == val5));    System.out.println("val1.equals(val5)  :" + val1.equals(val5));        Long val6 = new Long(150);    Double val7 = new Double(150.0);    System.out.println("val3.equals(val6)  :" + val3.equals(val6));    System.out.println("val3.equals(val7)  :" + val3.equals(val7));        System.out.println("val3.equals(val6.intValue())  :" + val3.equals(val6.intValue()));    System.out.println("val3.equals(val7.intValue())  :" + val3.equals(val7.intValue()));  }}

执行结果

val1 == val2  :trueval3 == val4  :falseval3.equals(val4)  :trueval1 == val5  :falseval1.equals(val5)  :trueval3.equals(val6)  :falseval3.equals(val7)  :falseval3.equals(val6.intValue())  :trueval3.equals(val7.intValue())  :true

说明
第一行比较了val1和val2两个物件是否为同一物件,结果传回true。
这是因为当参照值为int形式,且值介于-128 ~127之间(储存空间小于1 byte),则参照此值的物件,都是参照记忆体上相同的位址,即同一物件。
第二行的值为150,超过了1 byte所能保存的範围,因此不是同一物件。需使用equals()比较值大小,才会传回true(第三行)。
这表示Integer类和String类的equals()方法一样,都被覆写为比较值的方法。
第四行&第五行:使用new()方法新增物件的话,即使值相同也不会被视为同一物件。因此val1和val5不是同物件,但值相同。
第六行以后比较Long,Double及Integer等不同类型的物件,由于无法直接比较,引此传回false。
利用intValue()方法将Long,Double类转为Integer类之后即可进行值的比较。

toString()方法

toString()也是Object提供的基本方法之一,会传回物件的class名+@+hashcode。不过依照各个class需求的不同,通常这方法会被覆写成其他样子。
请看以下範例:

class Foo {}class Bar {  public String toString(){    return "This is an object made from Bar.";  }}class Sample7_5 {  public static void main(String[] args) {    String obj1 = "Tom";    StringBuilder obj2 = new StringBuilder("Tom");    Foo obj3 = new Foo();    Bar obj4 = new Bar();    System.out.println(obj1);    System.out.println(obj2);    System.out.println(obj3);    System.out.println(obj4);  }}

执行结果

TomTomFoo@368239c8This is an object made from Bar.

说明
String和StringBuilder类的toString()都被覆写过,会传回其保存的文字列。
没被覆写过的toString()会传回物件的class名+@+hashcode。
也可以自定义要传回的文字列。

Math class

提供数学计算的一些方法,例如:
int num1 = 100;
int num2 = 200;
int max = int Math.max(num1,num2); //传回最大值
double randomVal = int Math.random(); //传回小于1的随机值

阵列方法

请看以下範例:

import java.util.*;class Sample7_6 {  public static void main(String[] args) {    int[] i_array = {30,10,20,50,40};        //使用arraycopy()方法複製阵列    int[] copy = new int[3];    System.arraycopy(i_array,2,copy,0,3);    for(int val: copy){      System.out.print(val + " ");    }System.out.println();        //使用sort()方法排序    Arrays.sort(i_array);    for(int val: i_array){      System.out.print(val + " ");    }System.out.println();        //使用asList()方法    String[] s_array = {"Tom","Hill","Cathy"};    List<String> list = Arrays.asList(s_array);    //list.add("Mary");    for(String val: list){      System.out.print(val + " ");    }System.out.println();  }}

执行结果

20 50 4010 20 30 40 50Tom Hill Cathy

说明
arraycopy()方法属于System类,文法为arraycopy(来源阵列,开始位置,目标阵列,开始位置,複製的长度)
sort()方法属于Arrays类(需先import),可依内容值的大小重新排列阵列。
asList()方法属于Arrays类(需先import),可将阵列转为List(固定长)。由于固定长的List无法增加长度,因此list.add("Mary");这行若执行的话会报错。
需要可变长的列表时,使用ArrayList如下例:

List<String> list = new ArrayList<>(Arrays.asList(s_array));list.add("Mary");

执行结果

Tom Hill Cathy Mary

Date and Time API的基本

此类由java.time包提供,特徵如下:

分别提供日期、时间以及日期+时间等classDate and Time的class为不可修改的物件,因此在多线程环境下可安全使用。提供充足的日期时间计算功能。

java.time包的主要class

LocalDateLocalTimeLocalDateTimePeriod(期间)

java.time.format包的主要class

DateTimeFomatter(负责日期时间的输出格式)

来看看日期时间的範例吧:

import java.time.*;class Sample7_7 {  public static void main(String[] args) {    LocalDate dateNow = LocalDate.now();    LocalTime timeNow = LocalTime.now();    LocalDateTime dateTimeNow = LocalDateTime.now();        LocalDate dateOf = LocalDate.of(2021,2,25);    LocalTime TimeOf = LocalTime.of(21,3,20);    LocalDateTime dateTimeOf = LocalDateTime.of(2021,2,25,21,3,20);        LocalDate dateP = LocalDate.parse("2021-02-25");    LocalTime TimeP = LocalTime.parse("21:03:20");    LocalDateTime dateTimeP = LocalDateTime.parse("2021-02-25T21:03:20");        System.out.println("LocalDate.now  :" + dateNow);    System.out.println("LocalTime.now  :" + timeNow);    System.out.println("LocalDateTime.now  :" + dateTimeNow);        System.out.println("LocalDate.of  :" + dateOf);    System.out.println("LocalTime.of  :" + TimeOf);    System.out.println("LocalDateTime.of  :" + dateTimeOf);        System.out.println("LocalDate.parse  :" + dateP);    System.out.println("LocalTime.parse  :" + TimeP);    System.out.println("LocalDateTime.parse  :" + dateTimeP);  }}

执行结果

LocalDate.now  :2021-02-25LocalTime.now  :19:24:11.679136400LocalDateTime.now  :2021-02-25T19:24:11.679136400LocalDate.of  :2021-02-25LocalTime.of  :21:03:20LocalDateTime.of  :2021-02-25T21:03:20LocalDate.parse  :2021-02-25LocalTime.parse  :21:03:20LocalDateTime.parse  :2021-02-25T21:03:20

日期格式範例

import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;class Sample7_8 {  public static void main(String[] args) {    LocalDateTime dt1 = LocalDateTime.now();        DateTimeFormatter fmt1 = DateTimeFormatter.ISO_DATE;    System.out.println("now()  :" + dt1);    System.out.println("ISO_DATE  :" + fmt1.format(dt1));        DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");    String target = "2021/02/25 21:03:20";    LocalDateTime dt2 = LocalDateTime.parse(target, fmt2);    System.out.println("ofPattern()  :" + dt2);  }}

执行结果

now()  :2021-02-25T19:34:43.799818400ISO_DATE  :2021-02-25ofPattern()  :2021-02-25T21:03:20

说明
ISO_DATE是标準的日期格式,使用DateTimeFormatter.format()方法将目标日期修改为标準格式。
自订格式可用DateTimeFormatter.ofPattern()方法来製作。
再用LocalDateTime.parse(目标日期,自订格式)来套用格式。

日期时间计算範例

import java.time.LocalDate;class Sample7_9 {  public static void main(String[] args) {    LocalDate date = LocalDate.of(2020,02,25);    System.out.println("date  :" + date);    System.out.println("After 3 day  :" + date.plusDays(3));    System.out.println("After 5 months  :" + date.plusMonths(5));    System.out.println("After 2 weeks  :" + date.plusWeeks(2));    System.out.println("After 10 years  :" + date.plusYears(10));  }}

执行结果

date  :2020-02-25After 3 day  :2020-02-28After 5 months  :2020-07-25After 2 weeks  :2020-03-10After 10 years  :2030-02-25

Collection&Lambda式

函数型interface
定义的抽象方法只有一个(包含static及default方法)的interface,称为函数型interface。

Lambda式
有些class只使用一次而不会在其他地方使用,此时可以不用特别定义class,而採用Lambda式来处理,文法如下:
{引数} -> {处理};
处理后的返回值,会被丢给函数型interface承接。
※函数型interface意指只含有一个抽象方法(或是static,default方法)的interface
请看下例:

import java.util.function.Function;public class Sample7_10 {  public static void main(String[] args) {    Function<String, String> obj = (String str) -> {      return "Hello " + str;    };    String str = obj.apply("Tom");    System.out.println(str);  }}

执行结果

Hello Tom

此範例中,从Function<String, String> obj 开始的三行程式码,相当于class定义。
在这个匿名class(没有名字的class)中使用了Lambda式{引数} -> {处理},然后把返回值丢给Function<String, String> obj。
Function是一个JAVA提供的函数型interface,因此里面只有一个抽象方法叫做apply()。
我们在Lambda式里面把这个抽象方法给覆写了,内容就是return "Hello " + str;

因此,当obj.apply()方法被执行时,"Tom"作为引数被丢进方法里,加工后返回。
※Function<String, String>的意思是Function<引数的型态, 返回值的型态>

JAVA SE8导入了以下几个函数型interface,有兴趣可以google一下。
Function<T,R>
Consumer
Predicate
Supplier
UnaryOperator

另外Lambda式还有各式各样的简写,範例如下:
未简写

(String str) ->

省略资料型态(因为interface那边已经宣告过了)

(str) ->

省略括号(引数只有一个时可省略)

str ->

没有引数的时候

() ->

接下来看->右边的简写
未简写

{  return "Hello" + str;}

省略中括号和retrun(处理只有一行时)

"Hello" + str;

简写后的範例如下:

import java.util.function.Function;public class Sample7_10 {  public static void main(String[] args) {    //函数型interface<T,R> obj = 引数 -> 处理内容;    Function<String, String> obj = str -> "Hello " + str;      String str = obj.apply("Tom");    System.out.println(str);  }}

再来看看其他函数型interface的使用範例吧

import java.util.*;import java.util.function.*;public class Sample7_11 {  public static void main(String[] args) {    List<String> words = Arrays.asList("Tom","Mary");    words.replaceAll( str -> str.toUpperCase());    System.out.println(words);  }}

执行结果

[TOM, MARY]

※replaceAll()是List interface提供的default方法

import java.util.*;import java.util.function.*;public class Sample7_12 {  public static void main(String[] args) {    List<Integer> data = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));    data.removeIf( i -> i % 2 != 0);    System.out.println(data);  }}

执行结果

[2, 4]

※removeIf是Collection提供的default方法

以上是第七章 API的学习心得,下一章会介绍例外的处理。

参考教材: JAVAプログラマSilver SE8 - 山本 道子


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章