API(application program interface)是指程序之间具有特定规范的接口。透过这些接口可以引用其他程序来协助完成整体机能。
其实JAVA当中引用package或class的概念也与此相同。以下介绍常见的class及其method:
Object是java中所有class的父类。
里面提供了一些通用方法
method名 | 说明 |
---|---|
boolean equals(Object obj) | 比较是否为同一个物件 |
final Class<?> getClass() | 返回此物件的class |
int 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());
}
}
执行结果
[I
Foo
本范例中使用getClass()取得实例化物件的来源class後,再使用getName()方法得到class的名称。
结果的第一行中,"["表示阵列,"I"则表示int型态。合起来即为储存int资料的阵列。
Foo则为class名称。
Object class里面的equals()方法用来比较两个物件是否为同一个。然而在String类中,这个方法却被用来比较值是否相等。
这是因为equals()方法在String类中被覆写了的关系。
下面几个范例,比较equals()在String,StringBuilder及Integer类中的不同。
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 : false
s1.equals(s2) : true
s1.equals(s3) : false
s1.equalsIgnoreCase(s3) : true
说明
s1与s2不是同一个物件,返回false
s1与s2的值相同,返回true
s1与s3的大小写不同,返回false
忽略大小写,返回true
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 :false
sb2.equals(sb3) :false
sb2.toString().equals(sb3.toString()) :true
说明
"==" 比较是否为同一物件,传回false。
StringBuilder的equals()未被覆写(跟Object类一样),比较是否为同一物件,传回false。
要比较StringBuilder的值,可以运用toString()方法转为String物件後,即可用equals()进行比较,传回true。
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 :true
val3 == val4 :false
val3.equals(val4) :true
val1 == val5 :false
val1.equals(val5) :true
val3.equals(val6) :false
val3.equals(val7) :false
val3.equals(val6.intValue()) :true
val3.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()也是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);
}
}
执行结果
Tom
Tom
Foo@368239c8
This is an object made from Bar.
说明
String和StringBuilder类的toString()都被覆写过,会传回其保存的文字列。
没被覆写过的toString()会传回物件的class名+@+hashcode。
也可以自定义要传回的文字列。
提供数学计算的一些方法,例如:
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 40
10 20 30 40 50
Tom 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
此类由java.time包提供,特徵如下:
java.time包的主要class
java.time.format包的主要class
来看看日期时间的范例吧:
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-25
LocalTime.now :19:24:11.679136400
LocalDateTime.now :2021-02-25T19:24:11.679136400
LocalDate.of :2021-02-25
LocalTime.of :21:03:20
LocalDateTime.of :2021-02-25T21:03:20
LocalDate.parse :2021-02-25
LocalTime.parse :21:03:20
LocalDateTime.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.799818400
ISO_DATE :2021-02-25
ofPattern() :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-25
After 3 day :2020-02-28
After 5 months :2020-07-25
After 2 weeks :2020-03-10
After 10 years :2030-02-25
函数型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 - 山本 道子
<<: How to Reset forgotten root password in RHEL/CentOS 7/8
>>: (PYTHON)请问 CKIPtagger 如何断"句"
0x1 前言 昨天订单总算建立完成了,今天来把回覆的讯息解开并验证 0x2 处理流程 回覆的结构如下...
在上一篇我们下载完了准备工具後 这篇我们要来开始架设我们的程序环境了 这一篇我们会教大家 如何下载P...
幸福时光~手作甜汤 地点:台南市新营区民权路118号 时间:14:00~20:30 这家店可以看作是...
今天就书中描述与我个人的开发经验,来谈谈该如何撰写测试吧。有时候我们可能会遇到,软件在开发之初并没有...
前言 上一篇中我们学习到了 GenericAPIView 以及 Mixins 的使用,让我们建立 R...