本篇文章主要對比Java跟Kotlin中的類和介面的寫法。
目錄
一、類的宣告
二、建構函式
三、函式的引數
四、建立類的例項
五、資料類
六、列舉類
七、屬性
八、內部類
九、可見性修飾符
十、繼承
十一、介面
一、類的宣告
Java宣告一個類
public class Foo {}
複製程式碼
Kotlin宣告一個類
class Foo
複製程式碼
如果只宣告一個空的類,Java和Kotlin的區別還是不大的。在Kotlin中如果沒有類體,Kotlin可以省略大括號{}
。
二、建構函式
一個類當中可以有一個主建構函式和多個次建構函式。
1.主建構函式
在Java中,如果不指定構造方法,編譯器會預設生成一個不帶引數的構造方法
public class User{
public User() {//預設生成
//可以在構造方法裡修改程式碼
}
}
複製程式碼
在Kotlin中,主建構函式是類頭的一部分:它跟在類名後
class User constructor(userName: String) {
}
複製程式碼
如果主建構函式沒有任何註解或者可見性修飾符,可以省略這個 constructor 關鍵字
class User(userName: String) {
}
複製程式碼
Kotlin的主建構函式不能包含任何的程式碼。初始化的程式碼可以放到以 init 關鍵字作為字首的程式碼塊中
class User(userName: String) {
init {
//...
}
}
複製程式碼
2.次建構函式
Java中的構造方法
public class User {
public User(String userName) {
}
//次建構函式
public User(String userName, int age) {
}
//次建構函式
public User(String userName, int age, String sex) {
}
}
複製程式碼
Kotlin的次建構函式前面必須加constructor關鍵字
class User(userName: String) {
//主建構函式的實現部分
init {
println(userName)
}
//次建構函式,可通過this調主建構函式
constructor() : this("czh")
//次建構函式,可通過this調主建構函式
constructor(age: Int) : this("czh") {
println(age)
}
//次建構函式,通過this調主建構函式
constructor(sex: String, age: Int) : this("czh") {
println("$sex$age")
}
}
//例項化User
User()
User("Czh")
User(2)
User("男",22)
複製程式碼
執行程式碼,得到結果:
注意:在例項初始化期間,可以有多個init程式碼塊,按照它們出現在類體中的順序執行,如:
init {
println(1)
}
init {
println(3)
}
init {
println(2)
}
複製程式碼
執行該段程式碼,列印順序就是1->3->2
三、函式的引數
1.Kolin函式中的預設引數
Kotlin支援預設引數,在呼叫函式時不指定引數,就會使用預設引數,而Java並不支援預設引數。舉個例子:
class User(userName: String = "Czh", age: Int = 22)
複製程式碼
如果我們在例項化User的時候不傳入引數,userName預設就是Czh,age預設就是22,如下所示:
var user = User()
複製程式碼
如果在設定了預設值後,不想用預設值的話可以在建立例項時傳入引數,如下所示:
var user = User("ABC" , 123)
複製程式碼
2.Kolin函式中的命名引數
如果一個預設引數在一個無預設值的引數之前,那麼該預設值只能通過使用命名引數呼叫該函式來使用,如下所示:
class User(userName: String = "Czh", age: Int)
var user = User(age = 22)
複製程式碼
四、建立類的例項
Java使用關鍵字new
建立類的例項:
new User();
複製程式碼
Kotlin沒有new關鍵字,所以直接建立類的例項:
User()
複製程式碼
五、資料類
在Kotlin中,存在資料類這樣一個概念,我們經常建立一些儲存資料的類,並標記為 data,相當於Java中擁有Set和Get方法的實體類。下面來作個對比: Java實體類:
public class User {
String userName;
int age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
if (age != user.age) return false;
return userName != null ? userName.equals(user.userName) : user.userName == null;
}
@Override
public int hashCode() {
int result = userName != null ? userName.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", age=" + age +
'}';
}
}
複製程式碼
對應的Kotlin資料類:
data class User(var userName: String, var age: Int)
複製程式碼
資料類用關鍵字data
標識,會自動建立下面的方法:
getter/setter
方法;equals()
/hashCode()
對;toString()
格式是"User(name=Czh, age=22)"
;componentN()
函式 按宣告順序對應於所有屬性;copy()
函式。
建立資料類需要注意的是:
- 主構造方法至少要有一個引數,且引數必須標記為val或var
- 資料類不能用open、abstract、sealed(封閉類)、inner標識
獲取資料類例項後,直接可以呼叫這些方法:
簡單解釋一下copy()函式。在很多情況下,我們需要複製一個物件改變它的一些屬性,但其餘部分保持不變。 copy() 函式就是為此而生成。舉個例子:
var user = User("Czh2",22)
var user1 = user.copy(age = 23)
Toast.makeText(this, user1.toString(), Toast.LENGTH_SHORT).show()
複製程式碼
執行程式碼,彈出toast:
六、列舉類
Java的列舉類跟Kotlin的列舉類非常相似。 Java定義一個列舉類
enum Color {
RED, GREEN, BLUE
}
複製程式碼
Kotlin定義一個列舉類
enum class Color {
RED, GREEN, BLUE
}
複製程式碼
Java為列舉類指定數值
enum Color {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
private Color(int rgb) {
}
}
複製程式碼
Kotlin為列舉類指定數值
enum class Color(rgb: Int) {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF)
}
複製程式碼
Java列舉類與Kotlin列舉類除了基本語法不同,其他都非常相似。
七、屬性
Kotlin的類可以有屬性。 屬性可以用關鍵字var 宣告為讀寫的,用關鍵字val宣告為只讀的。
1.宣告屬性
Java中的宣告屬性:
public class User {
String userName;
final String sex = "男";
}
複製程式碼
對應的Kotlin程式碼:
class User {
var userName: String
val sex: String = "男"
}
複製程式碼
####2.呼叫屬性
Java需要加上getter方法和setter方法才可以呼叫
new User().getSex();
new User().setUserName("Czh");
複製程式碼
Kotlin在語法上支援屬性,不用為屬性定義getter和setter方法。要使用一個屬性,只要用名稱引用它即可。
User().sex //getter
User().userName = "Czh" //setter
複製程式碼
3.屬性的getter與setter
雖然Kotlin在語法上支援屬性,但我們仍然可以在屬性中使用getter和setter。舉個例子:
class User {
var name = "Czh"
var userName: String
get() = name //呼叫User().userName,得到結果是 Czh
set(value) {
//呼叫User().userName = "Czh" 把name設為 Czh
//然後再呼叫呼叫User().userName,得到結果是 Czh
name = value
}
//用val只讀標識只讀
val sex: String
get() = "男"//呼叫User().sex,得到結果是 男
}
複製程式碼
- field識別符號
上面例子的User類中定義了一個name來儲存屬性的值,如果不想定義一個欄位來儲存屬性的值,可以使用field識別符號,如下所示:
class User {
var userName: String = "Czh"
get() = field
set(value) {
field = value
}
}
複製程式碼
通過Kotlin提供的field識別符號能夠更簡便地讀寫屬性值。
八、巢狀類
巢狀類指的是在類中定義的類,如下所示: Java中的巢狀類
class User {
int age;
static class UserName{
}
}
User.UserName user= new User.UserName();
複製程式碼
Kotlin用inner
關鍵字標記巢狀類
class User {
var age: Int = 0
inner class UserName {
}
}
var userName: User.UserName = User().UserName()
複製程式碼
當我們用inner
關鍵字標記巢狀類時,可以通過外部類的例項呼叫巢狀類。
九、可見性修飾符
Java中的可見性修飾符:
可見性修飾符 | 訪問級別 | 同類 | 同包 | 子類 | 不同包 |
---|---|---|---|---|---|
public | 公開 | √ | √ | √ | √ |
protected | 受保護 | √ | √ | √ | × |
default | 預設 | √ | √ | × | × |
private | 私有 | √ | × | × | × |
Kotlin中的可見性修飾符:
- private ——本類內部(包含其所有成員)都可見
- protected ——只在本類內部+子類中可見
- public ——能見到類宣告的任何客戶端都可以見到其public成員
- internal——能見到類宣告的本模組內的任何客戶端都可以見到其public成員
與Java可見性修飾符的可見性修飾符不同的是,多了一個internal
,少了一個default
。 internal
意味著該成員只在相同模組內可見。更具體地說, 一個模組是編譯在一起的一套 Kotlin 檔案:
- 一個 IntelliJ IDEA 模組;
- 一個 Maven 專案;
- 一個 Gradle 源集;
- 一次 <kotlinc> Ant 任務執行所編譯的一套檔案。
十、繼承
1.類的繼承
Java類的繼承
class UserActivity extends AppCompatActivity {}
複製程式碼
Kotlin類的繼承
class UserActivity: AppCompatActivity()
複製程式碼
Java跟Kotlin都是單繼承的,也就是說,都只能有一個父類。不同的是,Kotlin使用冒號:
繼承,而且Kotlin的class預設不允許繼承,如果想讓類可以被繼承,需要用open關鍵字來標識該類,如下所示:
open class Food //用open關鍵字來標識該類
class Fruits : Food()
複製程式碼
2.重寫方法
在Kotlin中,方法也是預設不可重寫的。如果子類要重寫父類中的方法,要在父類的方法前面加open關鍵字,然後在子類重寫的方法前加override關鍵字,如下所示:
//父類
open class Food {
open fun banana() {}
}
//子類
class Fruits : Food(){
override fun banana() {
super.banana()
}
}
複製程式碼
十一、介面
Java介面跟Kotlin介面都是用interface關鍵字宣告
interface A{}
interface B{}
複製程式碼
Java用implements實現介面
class Foods implements A, B {}
複製程式碼
Kotlin用冒號:
實現介面
class Food : A, B {}
複製程式碼
如果Kotlin中同時存在繼承類和實現介面
//繼承Food類和介面AB
class Fruits: Food,A, B {}
複製程式碼
一個類可以實現多個介面,而且介面中的屬性和方法都是open的,不用另外加open標識。
- 介面中的方法體
Kotlin介面中的方法可以有預設方法體,有預設方法體的方法可以不重寫。而Java不支援介面裡的方法有方法體。舉個例子:
interface UserImpl {
fun getName(): String
fun getAge(): Int{
return 22
}
}
//實現介面UserImpl,可以不重寫getName()
class User :UserImpl{
override fun getName(): String {
return "Czh"
}
}
複製程式碼
總結
本篇文章主要對比了Kotlin和Java中對於類和介面的區別,相對來說Kotlin加了一些語法糖,讓程式碼編寫更方便。
參考文獻:
Kotlin語言中文站、《Kotlin程式開發入門精要》
推薦閱讀:
從Java到Kotlin(一)為什麼使用Kotlin
從Java到Kotlin(二)基本語法
從Java到Kotlin(三)類和介面
從Java到Kotlin(四)物件與泛型
從Java到Kotlin(五)函式與Lambda表示式
從Java到Kotlin(六)擴充套件與委託
從Java到Kotlin(七)反射和註解
從Java到Kotlin(八)Kotlin的其他技術
Kotlin學習資料總彙
更多精彩文章請掃描下方二維碼關注微信公眾號"AndroidCzh":這裡將長期為您分享原創文章、Android開發經驗等! QQ交流群: 705929135