Kotlin 怎麼學 ?遇到過哪些坑?

2021-02-20 鴻洋

作者:kotlon

連結:

https://www.jianshu.com/p/dcf6cd7c59a3

本文由作者授權發布。

kotlin 在 17 年 google io 大會上確定為親兒子,android studio canary 3.0 版本開始,直接支持 kotlin 語言,不需要額外安裝 as plugin。

kotlin 的出現,給 android 開發者帶來了極大的活力,現在的 android 工業開發,講究的是語法糖,效率,性能,高質量,以及可拓展性,而 kotlin 的出現給 java 開發者帶來了極大的福音。

kotlin 官網教程英文 

https://kotlinlang.org/docs/reference/basic-types.html

kotlin 官網教程中文 

https://www.kotlincn.net/docs/reference/

閱讀此文章大約半小時~

如何閱讀?

瀏覽kotlin 優勢和kotlin 坑這兩大章節,然後去學習 kotlin 基礎語法,根據第三章,kotlin 普及裡的建議,可以在實際開發中,開幹了。

避免 npl以及非空判斷更優雅

kotlin 默認是非空的,如果你需要聲明一個可能為空的變量,那麼如下:

private  var mName:String = "kk"
private  var mSubName:String? = null

這裡的 mName 變量聲明為,String 類型;mSubName 聲明為 String?。前者不能為 null,後者可以為 null。

然後,你可能經常在 java 中寫這樣的代碼:

if (mANRPA != null) {
    mANRPA.stop();
}

那麼在 kotlin 你這要這樣寫就行了:

使用 ?.  的效果和上面的 java 代碼是一樣的,表示該變量可能為空,如果不為空則執行後面的表達式。

參考地址:

https://www.kotlincn.net/docs/reference/null-safety.html

java 語法完全兼容 kotlin

你可以通過幾個小時學習 kotlin 的基礎語法,包括:

怎麼定義變量

怎麼定義方法

怎麼定義類

等等.

然後就可以像 java 一樣使用 kotlin,當然這不是我們的最終目的,因為 kotlin 的語法糖才是我們最後的目標。

google 發布了 kotlin 簡易教程,大概只需要幾個小時,就可以看完:

在實際的開發中,大概第一個星期內,你寫代碼的速度會下降一些,但是一個星期之後,完全上手了,寫代碼的速度是有很大的提升的。

1.extension-擴展函數和擴展屬性

關於 擴展函數的說明:

https://www.kotlincn.net/docs/reference/extensions.html

android ktx 庫提供了一系列的優秀的擴展函數 官方說明

https://android.github.io/android-ktx/core-ktx/index.html

簡單的說,擴展函數是什麼呢?先來看一個例子,在java 裡面 你要 remove 一個 View 的 Parent,你可能會這樣寫:

if(mLoadingView.getParent() != null){
    ((ViewGroup)mLoadingView.getParent()).removeView(mLoadingView);
}

但是每次都這樣寫,貌似比較重複,對吧;然後你就可能考慮寫一個靜態方法,類似如下,比如在 ViewUtils 類似命名裡寫一個靜態函數:

public static void removeSelf(View view){
    if(view == null) return;
    if(view.getParent() != null){
        ((ViewGroup)view.getParent()).removeView(view);
    }
}

但是在 kotlin 中,使用擴展函數,可以更巧妙更直接的實現這個功能。

寫在某個文件裡面,編寫一個頂級的擴展函數,如下:

inline fun View.removeSelf(): Boolean {
    if (this.parent != null && this.parent is ViewGroup) {
        (this.parent as ViewGroup).removeView(this)
        return true
    }
    return false
}

然後在需要調用的地方,你直接這樣寫就行了:

當然 kotlin 擴展函數的作用並不僅僅在此,它的思想主要是豐富實際類的語法。

例如,現在讓你設計一個功能,點擊一個按鈕,然後發起一個網絡請求,但是需要注意在 View 的生命周期內,如果View 銷毀了,取消這個網絡請求,並且不會更新UI。那麼常規的 java 代碼,寫起來可能就是一堆的回調,但是使用 kotlin 的 擴展函數+代理,封裝之後,你看到的就是下面一行代碼。


mJumpBitmap.onClickAutoDisposable { 
    
}

2.Delegate And Delagate Properties -委託以及委託屬性

代理在設計模式上是非常優秀的,例如 retrofit 框架裡,大量的使用動態代理這種設計模式;然後 kotlin 在語法層面去支持了代理,包括代理和代理屬性。

代理屬性的話,kotlin 支持一些標準的代理屬性,例如 by lazy,Observable,Storing;其中 by lazy,提供三種類型的懶加載,包括非線程安全,synchronized 同步線程安全,以及cas 操作線程安全。

示例如下,例如在 PushProto.java 中,需要對 ProtoBuf 解析單例進行初始化,並且要求是線程安全的,原先 java 代碼如下,也就是一個 double check 的單例模式。


private static volatile com.google.protobuf.Parser<PushProto> PARSER;

if (PARSER == null) {    synchronized (com.yy.hiyo.proto.PushProto.class) {
   if (PARSER == null) {
       PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);
            }
    }

如果是用 kotin 則只需要使用 by lazy 懶加載委託屬性便能實現類似的效果,kotlin 代碼如下:


val initProtoInstance by lazy<DefaultInstanceBasedParser> {
  
    DefaultInstanceBasedParser();
}

注意:實際上這裡使用的並非是是 double check 的模式,而是類似的一種線程安全模式,源碼如下:


public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

@kotlin.jvm.JvmVersion
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
        when (mode) {
            LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
            LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
            LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
        }

private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE
    
    private val lock = lock ?: this

    override val value: T
        get() {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }
            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                }
                else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null
                    typedValue
                }
            }
        }

    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE
}

by lazy 的三種模式如下:

LazyThreadSafetyMode.SYNCHRONIZED 類似 double check 線程安全,synchronized 悲觀鎖

LazyThreadSafetyMode.PUBLICATION 線程安全,使用 cas 鎖,多個線程可以同時執行初始化代碼塊,但是只返回第一個執行完成的數值,作為初始化

LazyThreadSafetyMode.NONE 單線程先可用,等於 java 懶漢式單例

其後,其它兩種標準屬性,參考官方教程。

3.語法層面支持懶加載-by lazy 和 lateinit


懶加載是經常使用的一個功能,傳統的 java 懶加載,可能是在使用的是判斷一下對象是否為空,但是在 kotlin 裡,提供了語法層次的懶加載,表示該變量在使用之前一定會被初始化。

by-lazy 上面說到了,lateinit 簡單用法如下:

lateinit var mStirng: String


mString = "some"


if(TestActivity::mStirng.isLateinit){
  
}

4.比 java 更強大的類型判斷


在 java 中,泛型和反射都是使用頻率極高的語法,使用泛型或者接口編程之後,我們經常要使用 instance of 做判斷,如下代碼:

if (instance instanceof BasePresenter) {
    ((BasePresenter) instance).onInit(mMvpContext); 
}

在kotlin 裡面,只需要寫如下代碼:


fun checkSting(content:Any){
  
    if(content is String){
      
        content.substring(1)
    }
}

在泛型和接口編程使用廣泛的情況下,kotlin 的類型安全存在以下優勢:

is 操作符,支持非操作,比 java 更簡潔,在語法層次表面的 非該類型;其次 is 類型判斷符,作用域類,類型會智能轉換,也就是例子中說的。需要注意是,val 和 var 類型,支持的 is 操作不一樣。

as 操作符,支持空類型轉換,也就是 as?,可以轉換為 String? 等可空類型,類似 java 操作是 先要判斷該對象是否為該類型,然後強轉,語法比較繞,然而 kotlin 直接支持可為空類型的轉換


5.functions and lambdas - 函數和 lambdas 表達式

在 kotlin 裡面函數是第一公民,java 8 也把加入了該特性,但是遠遠沒有 kotlin 的函數功能強大,kotlin 的函數功能如下:

參數值和變量可以是函數

函數參數支持默認參數

支持命名參數

支持 lambda

支持內聯函數

支持強大的擴展函數

編譯器支持內聯優化

函數可以有一個接收者

函數和 lambdas 表達式對實際開發帶來極大的方便,也豐富了編程思想,更多的細節,可以參考官方教程。

6.強大的集合功能


在 kotlin stdlib 裡面,支持了強大的集合功能,支持各種高階函數,主要的高階函數如下:

具體可以參考一個專欄 kotlin 學習之路

https://zhuanlan.zhihu.com/LearningKotlin

或者可以直接在 AS 裡面搜索類 _Collection.kt,裡面可以看到該類的所有的高階函數.

下面是一個簡單的示例,比如你在 java 中需要對一個後端返回的 List 進行排序,java 中常見的實現方案有

1. Collections 中static <T extends Comparable<? super T>> void sort(List<T> list)傳入該 List,但是 List 中的元素需要實現 Comarable 接口,並且重寫 compareTo()方法

2. Collection中,static <T> void sort(List<T> list, Comparator<? super T> c) 入該 List 和 一個Comparator。

3. java 中,支持 lambda 表達式之後,你可以這樣寫

ballList.sort(Comparator.comparing(Ball::getHits));

表示使用 Ball 的 hits 欄位進行比較

4. java 8 中可以使用 stream

如果使用 kotlin,這裡支持各種各樣的sort() 方式,如下 api:

那麼上面的例子中,kotlin 中這個排序只要使用 Collections 裡面的擴展函數就可以做了。


ballList.sortByDescending {it.hits}

所以其實寫到這裡,我們已經見識到了,kotlin 的開發者幫助我們考慮了各種語法場景,我們站立在一個偉大的開發團隊上,自然而然能更快的寫出更高質量的代碼。

7.Standard Lib標準庫

Kotlin的標準庫提供了一系列提高開發效率的函數,例如 apply{} ,run{},let{} 等,這裡的解釋都比較簡單,具體自己看一下 api 就行了,位於 Standard.kt 文件中,使用例子如下:

EnterRoomConfig.RoomlistEventBean eventBean = new EnterRoomConfig.RoomlistEventBean();
eventBean.setColumn(String.valueOf(position + 1));
eventBean.setRow(baseRoomEventListBean.getRow());
eventBean.setPositionId(String.valueOf(position + 1));
eventBean.setToken(token);
eventBean.setModelId(baseRoomEventListBean.getModelId());

你可能不斷的為訪問 java bean 或者某個對象的屬性或者方法,則需要不停的寫 對象實例.屬性 或者 對象實例.方法。在 kotlin 中,你完全可以釋放自己的雙手,如下:

val enterRoomConfig = EnterRoomConfig("").apply {
  //這裡有個 this 指向前面new 出來的 EnterRoomConfig() 實例
  //其實等於 this.isGuideEnter 
    isGuideEnter = false
    isQuickMatch = true
    followUid = followUid
    pwd_token = ""
}

apply() 的源碼如下:

public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

這裡包含,contract 用法和 帶接受者的函數,block() 函數的接收者是T,kotlin 這裡其實是提供了一種方便的建造者模式,在 java 裡面,你實現建造者模式,需要自己手動去編寫接口和 Builder 實現,在 kotlin 則使用這些高階函數,方便你隨意的實現 Builder 模式。

8.編寫單例更快了

你只需要使用 Object  就可以編寫單例了,如下:

object CloUtils {
    fun test(){
    }
}

那麼kotlin 上的單例和 java 的各種單例模式,性能上有什麼區別嗎?kotlin 使用 object 關鍵字聲明的單例,翻譯成 java 如下:

public final class CloUtils {
   public static final CloUtils INSTANCE;

   public final void test() {
   }

   static {
      CloUtils var0 = new CloUtils();
      INSTANCE = var0;
   }
}

也就是 java 常見的類似 餓漢式的單例,這種單例是線程安全的,可能存在一定問題:

1. 在類加載的時候,單例會被初始化,所以不要在初始化代碼塊,做太多操作

2. 不能直接在構造函數傳遞參數,其實是 object 不能夠有一個 constractor

    

那麼實際上我們可以使用其它方式實現我們需要的效果,例如 懶漢式和 double check 等模式,類似 by lazy。

9.kotlin 和 android-android extension插件

實際上,kotlin 是一門全棧的語言,可以寫基於 jvm 的,例如 android 和 後端,也可以寫前端,但是在 android 上的表現,可能是最亮眼的,如是說:

在某個 module 的 gradle 文件中:

apply plugin: 'kotlin-android-extensions'

然後你就可以使用 android extension 全家桶了,可以幫你做啥呢?

View Binding 取代繁瑣的 findViewById()方法

例如某段 java 代碼:

//數據域聲明各種View
private YYTextView titleTv, roomNameTv, onlineTv, tagTv;
private YYImageView moreIv, lockIv;
private YYLinearLayout titleLayout;
private ViewGroup onlineCountLayout;
private BubblePopupWindow mPopupWindow;

//然後各種 findViewByID
titleTv = findViewById(R.id.tv_title_when_popup);
titleLayout = findViewById(R.id.layout_title_main);
roomNameTv = findViewById(R.id.tv_room_name);
onlineTv = findViewById(R.id.tv_online_count);
tagTv = findViewById(R.id.tv_tag);
moreIv = findViewById(R.id.iv_more);
lockIv = findViewById(R.id.iv_lock);
onlineTv.setTypeface(FontUtils.getTypeFace(FontUtils.FontType.DINMittelschriftAlternate));
roomNameTv.setOnClickListener(this);
tagTv.setOnClickListener(this);
findViewById(R.id.iv_back).setOnClickListener(this);
moreIv.setOnClickListener(this);

在 kotlin 中,你使用 extension 插件,就可以在這樣訪問控制項:


import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    val tag = "MainActivity"

    @RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initBut()
    }

    private fun initBut(){
      
        mJumpBitmap.setOnClickListener {
            val intent = Intent(this@MainActivity, BitmapAcitivty::class.java)
            startActivity(intent)
        }
        mJumpFresco.setOnClickListener {
            val intent = Intent(this@MainActivity, FrescoRecyvlerActivity::class.java)
            startActivity(intent)
        }
    }

原理很簡單,就是 extension 插件幫你 findViewById 了類似其它注入框架。

這裡有幾點注意的,你可以在 Activity 或者 Fragment 或者自定義View 或者 ViewHolder 裡面使用這個特性,無需任何其它操作。其次 這個是有Cache 的,每次直接訪問id,並不會每次都去 findViewById,只要第一次才會 findViewByID,然後後面會存起來。

使用註解實現 Pracelable


在實際開發中,你可以給一個類實現系列化,但是中途可能增加欄位,傳統的 java 編寫中,或者使用 ide 插件編寫,增加欄位也是非常辛苦,需要在 writeToParcel() 和  createFromParcel() 方法添加代碼,如果使用 extension 插件,只需要開啟這個設置:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    ..
    androidExtensions{
        experimental = true
    }
}

然後在實現 Parcelable 的類上增加一個註解 @Parcelize,代碼如下:

@Parcelize
data class Ball(var hits: Int) : Parcelable {
}

實際上,gradle 插件會為你自動加上  Parcelable 的實現。

還有其它 experimental 的特性等待你去挖掘

參考文檔:https://kotlinlang.org/docs/tutorials/android-plugin.html

kotlin Coroutine -kotlin 協程庫

Coroutine 協程,是kotlin 上的一個輕量級的線程庫,對比 java 的 Executor,主要有以下特點:

更輕量級的 api 實現協程

async 和 await 不作為標準庫的一部分

suspend 函數,也就是掛起函數是比 java future 和 promise 更安全並且更容易使用

那麼實際本質上和線程池有什麼區別呢?我的理解是這樣的,協程是在用戶態對線程進行管理的,不同於線程池,協程進一步管理了不同協程切換的上下文,協程間的通信,協程掛起,對於線程掛起,粒度更小,而且一般不會直接佔用到CPU 資源,所以在編程發展的過程中,廣義上可以認為 多進程->多線程->協程。

協程並不會映射成內核線程或者其他這麼重的資源,它的調度在用戶態就可以搞定,任務之間的調度並非搶佔式,而是協作式的。

協程庫的強大,不言而喻,這裡是我之前寫過的關於協程庫的分享,文檔連結:

https://www.jianshu.com/p/c531eefef4c6

Kotlin -anko 在代碼中使用 dsl 編寫布局

anko 庫,你可以在在代碼中編寫布局,如下:


verticalLayout {
    backgroundColor = Color.parseColor("#eeeeee")
    layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)

}

同樣的 anko 這邊有個插件,可以支持實時預覽-你需要在編寫代碼之後,build 一下,然後就可以預覽布局。

由於anko 存在預覽問題,並且層級嵌套的時候,不好優化,所以暫時不建議使用 anko 去編寫布局.

對於 java 的程式設計師,kotlin 開發者提供了一種方式,幫助開發者去理解 kotlin,也就是可以把 kotlin 編譯出來的字節碼,反翻譯成 java 代碼,具體操作 tools-show kotlin bytecod-然後在右側會看到 kotlin 文件編譯之後的字節碼文件-然後點擊Decompile ,接著就可以看到 kotlin "翻譯出"java 的文件,之前講述 編寫單例模塊裡面,就是一個例子。

舊的 java 代碼怎麼辦

一段時間之後,大家寫 kotlin 都寫得很爽了,那麼總是有一個舊的代碼是用 java 寫的,那怎麼辦?如果你想把 java 改成 kotlin,也很簡單:

選中你的 java 文件,點擊 AS 導航欄 code-covert Java File To Kotlin File,這樣就可以轉過去了,然後進行簡單的修改,也就是把一些報錯和 waring 去掉(一般不會有報錯)。轉換之後的文件可以完美的運行的,這個你不用擔心。

當然 在使用 kotlin 過程中,會發現一些問題或者成本。

成本問題

對個人而言:

第一周使用 kotlin 在你的工作中,你會覺得效率下降,而且有點不知所措,甚至有點抵抗 kotlin,但是在兩三個星期之後,你一定是這樣的:

對於團隊而言


針對問題二,kotlin 的開發者正在優化,同時我們可以在構建的時候,監聽構建task 花費的時間,讓數據去評測,是否值得引入 kotlin。

選取了某個項目中的 module ,該 module 的基本為 kotlin 代碼編寫,使用 kotlin 構建時間增加了:

        1% :app:kaptGener…ReleaseKotlin (0:07.775)
        1% :app:kaptReleaseKotlin (0:05.872)
    ▇  2% :app:compileReleaseKotlin (0:21.167)

如果是 java 代碼的話,上述的時間可能是一半(猜測是這樣的),但是從實際數據看,該 module 有幾百個 kotlin 文件,編譯所花費的時間,也不過是增加了十幾秒,所以並不是特別大的問題。

1.java null 問題

習慣寫 java 的同學,一般是不會寫這樣的聲明的,去聲明一個參數是可為空的:

fun printSome(content:String?){

}


一般你是這樣聲明的:

fun printSome1(content:String){
}

在 kotlin 裡面,是沒問題的,即便是你傳入 null,編譯器也會提示你,不可以傳入null,但是一旦在 java 去調用這個 printSome1() 方法,一旦你傳入了 null,如下:


CloUtils.INSTANCE.printSome1(null);

依舊是ok的,但是一旦運行的時候,就會報錯:


2019-05-05 11:09:05.705 11674-11674/com.yy.yylite.kotlinshare E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.yy.yylite.kotlinshare, PID: 11674
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.yy.yylite.kotlinshare/com.yy.yylite.kotlinshare.bitmapcompress.BitmapAcitivty}: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter content
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2740)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2801)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1548)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:163)
        at android.app.ActivityThread.main(ActivityThread.java:6368)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:791)
     Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter content
        at com.yy.yylite.kotlinshare.collectionutils.CloUtils.printSome1(CloUtils.kt)
        at com.yy.yylite.kotlinshare.flow.ff.testJavaCallKotlin(ff.java:31)
        at com.yy.yylite.kotlinshare.bitmapcompress.BitmapAcitivty.onCreate(BitmapAcitivty.kt:29)
        at android.app.Activity.performCreate(Activity.java:6861)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2693)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2801) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1548) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:163) 
        at android.app.ActivityThread.main(ActivityThread.java:6368) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:791) 

具體的原因在於,編譯器層會幫我們加這樣一行代碼:

Intrinsics.checkParameterIsNotNull(content, "content");

如果傳入的參數為 null,則會直接拋出一個異常。

同樣的,在 kotlin 裡面,如果執行這樣的代碼:

var nonNullStr:String = null 

2.java 方法 Exception 問題

在之前某次迭代中,A  同學寫了這樣一行代碼:


val gson = Gson()
fastSpeech!!.words = gson.fromJson(words, object : TypeToken<List<String>>() .type)
 hotWordPopupWindow?.setData(fastSpeech!!.words, fastSpeech!!.classId)
....

作為一個老道的程式設計師都知道,使用 GSON 的方法,沒有 try catch 是不安全的,何況 fromJson 方法籤名就有 throw 異常的,如下:

public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {}

然而你使用 java 的時候,編譯器會提示你需要 catch 異常,但是在 kotlin 裡面,確實不會有的。

原因是因為 kotlin 開發者,認為所有的 Exception 都是 unchecked 的,編譯器不會提示你 catch 住,但是在過去的 java 開發裡面,effect java 認為,處理 checked Exception 是優雅合理的;

原文如下:

Checked Exceptions
In Kotlin, all exceptions are unchecked, meaning that the compiler does not force you to catch any of them. So, when you call a Java method that declares a checked exception, Kotlin does not force you to do anything。

在過去的實踐裡發現,在處理 json,網絡,IO  的時候,需要開發者關注,是否需要 try catch,當然了,這可能也是一個好處,畢竟寫代碼的人關心的細節更多了。

關於 java 和 kotlin 互調參考 

https://kotlinlang.org/docs/reference/java-interop.html

需要團隊成員去學習官網教程 或者 google 提供的快速學習的教程,當然這裡只是快速瀏覽就行了,主要還是得靠實踐,先熟悉基本的語法,然後找時間對語法糖進行了解,最後在實踐開發中使用高階特性。

官網教程-中文

https://www.kotlincn.net/docs/reference/

官網教程-英文

https://kotlinlang.org/docs/reference/basic-types.html

快速入門教程

幾小時上手 kotlin

然後可以在一段時間內需要通過 review 代碼,提高大家對 kotlin 的認識和用法,大概持續一個開發周期,之後基本可以很順暢的寫代碼了。

最後就是規則~怎麼讓 java 和 kotlin  共存

最後就是 IDE 對 kotlin 的友好支持,就是你在 commit 的時候,會對代碼進行一個 增量的 code analyse,然後虎會給出你一個更好的建議,其中就包括 kotlin 語法的糾正。如下展示:

然後點擊 commit 之後,點擊review

最後 IDE 會給出更 合理的代碼提示,一般可以改的儘量改一下,如下,這裡提示這一行命名是多餘的:

最後推薦一下我做的網站,玩Android: wanandroid.com ,包含詳盡的知識體系、好用的工具,還有本公眾號文章合集,歡迎體驗和收藏!

推薦閱讀:

J 神的ButterKnife竟然還隱藏著這樣的黑科技?

掃一掃 關注我的公眾號

如果你想要跟大家分享你的文章,歡迎投稿~

┏(^0^)┛明天見!

相關焦點

  • C++ 初始化的坑,你也遇到過嗎?
    陷阱1:默認初始化的坑請看一下代碼,你能知道哪些變量的值是確定的?所謂定義於函數體之外的變量,其實就是全局變量,這裡拓展說一下:初始化過的全局變量,由編譯器將其保存於靜態存儲區的data段,並且這樣的值越多,程序就越大,作業系統會在程序啟動時,將全局變量的值複製到data段中,即完成變量的初始化。
  • C++初始化的坑你也遇到過嗎?
    陷阱1:默認初始化的坑請看一下代碼,你能知道哪些變量的值是確定的?所謂定義於函數體之外的變量,其實就是全局變量,這裡拓展說一下:初始化過的全局變量,由編譯器將其保存於靜態存儲區的data段,並且這樣的值越多,程序就越大,作業系統會在程序啟動時,將全局變量的值複製到data段中,即完成變量的初始化。
  • Kotlin Native 詳細體驗,你想要的都在這兒
    其實我第一次看到 Native 這個名字的時候很自然的想到了 Jni,Kotlin 跑在 Jvm 上面,使用 Jni 與底層代碼交互是一件再正常不過的事情了,至於搞這麼大動靜麼,不過等我進行了一番了解之後才發現,Kotlin 項目組的野心真是不小,Java 誕生這麼多年了,也沒有做過編譯成除 Java 虛擬機字節碼以外的字節碼的事情,Kotlin 才出來多久啊,果然具有革命性。
  • kotlin-android-extensions插件也被廢棄了?扶我起來
    在開始介紹ViewBinding之前,我還是想先討論一下,為什麼kotlin-android-extensions插件會被廢棄。雖說Google的技術迭代頻率常常會讓我們直呼學不動了,但是Google也絕對不會無緣無故去廢棄一個之前主推的技術,說明kotlin-android-extensions插件肯定還是存在問題的。
  • Jetpack 成員 Hilt 實踐 (一) 啟程過坑記 | 開發者說·DTalk
    本篇文章的案例已經上傳到 GitHub 歡迎前去查看 AndroidX-Jetpack-Practice/HiltSimplehttps://github.com/hi-dhl/AndroidX-Jetpack-Practice研究 Hilt 時遇到一些坑,有些坑在 Google 文檔上也沒有提到,我會在文中特別強調,並在文末總結部分進行匯總
  • kotlin如何解決java開發痛點,讓程式設計師happier
    【當然,這裡並不是貶低java,java不僅是優秀的也是偉大的,java迭代了24+年,java的生態是眾多語言無法比擬的,也正是java的優秀才有了kotlin、Clojure、groovy等一系列優秀的語言,java的偉大也是無法複製的】,我猜這裡肯定有人要跳出來說,批評大叔,php才是最好的語言,讓大叔去學php~ 好吧,大叔有空再學學~大叔身邊有很多小夥伴,在猶豫到底學kotlin
  • IT 工程師做自由職業者會遇到哪些坑?
    作為 IT 自由職業者,了解這一行業裡有哪些坑,還有相應的解決辦法,將大大提高你成功的概率。我們採訪了一些曾經和正在從事 IT 自由職業的人,收集了一些他們在單幹時遇到的意想不到的難題。下面列舉了他們的觀點,如何把「自由」給工作帶來的消極影響最小化。
  • Kotlin學習筆記——基礎篇
    之前Kotlin沒有正式寫過,年後組內聽過一次分享,03月份開始真正用Kotlin寫業務需求。
  • git revert 還有這種坑?你遇到過嗎
    流程圖具體的 git 代碼分支管理看這個好了:https://nvie.com/posts/a-successful-git-branching-model/怎麼回事?到底怎麼就被 git 版本回滾給坑了呢?不急,待我慢慢道來。
  • 推薦系統中遇到的各種坑
    小編最近在瀏覽知乎大佬文章的時候,發現了一個有意思的話題:"在你做推薦系統的過程中都遇到過什麼坑?"。吸引了3,091關注者、被瀏覽192,713次,多位知乎大佬參與了回答。今天小編特意為大家推薦幾個知乎大佬高贊的答案,大家一起來看看,這些坑你是否曾經也踩過吧~~其實推薦系統是一個技術遠遠達不到需求的領域。今日頭條已經算是國內推薦領域的相當不錯的水平了,仍然頗受詬病。
  • Kotlin和Java混合開發總結(基於Kotlin1.3.0版本)
    我本來是不想學習kotlin的,但是現在的形勢,很多公司都在使用kotlin開發,可以說學會kotlin也是無奈之舉,既然是潮流,谷歌也在大力推廣,所以還是只能硬著頭皮逼迫自己學一下,也能更快適應公司的需要。正所謂:「識時務者為俊傑」,改變不了公司的發展,那就改變自己。廢話少說,直接上正題。本文主要講解kotlin和java混合開發的一個初探。
  • 海量衛星影像數據交付中遇到過的那些坑(硬碟篇)
    地圖數據  |  作者 /  水中天  整理  /  白水概述為了避免重蹈覆轍,我們將在為客戶交付海量衛星影像數據時遇到過的那些坑作一個總結今天,我們就先來講一下我們在海量衛星影像數據交付時遇到過的關於硬碟的坑,順便再為大家分享一些關於硬碟的相關常識。影像數據交付中遇到的硬碟坑在國慶大假之前,有客戶希望我們能儘快把數據做好,在國慶上班第一天就要把硬碟寄出,因為項目上急著用。為了避開出行高峰,小編原本就計劃3號出行,因此這個任務就落在了小編身上。
  • 打獨立運行包遇到無法trim咋解決
    背景介紹工作中我用到kotlin寫代碼,在orm上ktorm是一款非常優秀的操作db的框架,我喜歡用它所以我寫了一個插件能夠增加我的工作效率,這款idea插件的主體邏輯是.net開發的(沒錯是跨平臺的.net)。因為db-schema的解析邏輯我很在以前寫的一個visualstudio的插件就搞過了,所以改改就行了!
  • 強大的Kotlin也能搞定,測試利器MockK你不能不知道
    關鍵字在 Kotlin 裡面 when是關鍵字,Mockito 的when ,必須加上反引號才能使用:`when`(xxxx).thenReturn(xxx)如果看起來不舒服,也可以捨棄 Mockito 改用 mockito-kotlin。
  • Java vs Kotlin,Android開發人員應該選擇哪種語言?
    其次,目前Java也擁有自己強大的開源社區,當你遇到問題就能通過這些找到答案。作為初學者,會遇到很多技術問題,當我們在Google搜索問題時,肯定會得到答案;相對Kotlin來說,還是一種新的程式語言,很多開源項目還未成熟,並且也相對稀少。
  • 寫給 Java 開發者的 Kotlin 教程 (1) - 概述
    = null   由於 Kotlin 知道哪些變量可以為空,哪些變量不可為,因此它可以在編譯時檢測和禁止不安全的調用,否則會在運行時導致NullPointerException (JDK8 - Optional 同樣解決這個問題,不過並沒有編譯器上解決)明確
  • Kotlin教程(一):走進Kotlin的世界
    不過,有些開發者似乎過度解讀Google的意圖,認為Kotlin要取代Java成為Android開發的標配,大會上說的是official support kotlin,並非replace java with kotlin。
  • 使用 psycopg2 時遇到的兩個坑
    儘可能不要使用 psycopg2-binary官方文檔說了,psycopg2-binary 不需要編譯,可以認為是綠色版,是為了初學者用 Python 快速和 PostgreSQL 進行連接而用的, 如果你在 pypi 上發包,也不應該依賴 psycopg2-binary,應該直接依賴 psycopg2。
  • 使用Jenkins部署.Net Core遇到的幾個坑
    搞過CI/CD的同學一定吃過不少苦頭,或者說遇到不少坑,但是對自動化的執著住擋不了前進的步伐,如果你缺少了運維這一塊知識,那麼你的流水線總是不那麼完美,本文記錄的是自己躺過的坑,希望對你有所幫助。安裝Jenkins比較簡單,這裡略過……Step1.創建一個自由風格的Jenkins項目,這一步比較簡單略過(pipeline項目是一項更加挑戰,也許運維高手更需要熟悉,這裡跳過)Step2.在配置git源碼路徑的時候報錯
  • 利用python爬蟲爬取網站音樂遇到的坑
    下面,我就跟大家分享一下我在用python爬蟲時遇到的坑。下面,我以爬取某易雲音樂為例,介紹一下我時如何學習python爬蟲的:思路:音樂從哪裡來?---網站的伺服器裡怎麼從網址裡得到音樂?---向網站發起網絡請求刪選音樂文件下載音樂文件具體實現1.