Kotlin: Convert Java to Kotlin issue

java cooperation with korlin:
Kotlin最後也還是會轉換成java.
所以一個專案裡面有java有kotlin是正常的事 .
兩者可以互相工作正常.
且android studio有提供一個功能,能把java檔案轉成Kotlon.

-----
注意事項與小故事:

轉換一家新工作,跟convert java to kotlin一樣,會有很多未預期的事發生.
比如說幾年前我曾經到一家千x淨水公司,賣飲水器的公司上班,
那次新工作經歷給我的觀感就非常不好.

那時我很努力寫android app,甚至還做出一套檢測BLE狀態的工具app.
我超努力的,每天都做到很累,
結果那單位主管有一次把我叫到會議室,突然就說要安排寫ios的engineer當我主管,要在我上面,
我當然拒絕,因為那位ios engineer個性古怪,平常都不跟人溝通的.能力也普普.
我拒絕後,他就跟我說你就自己離職吧.做到這周.
然後就被迫離職了.然後他們很扯的的是不給資遣費,叫我自願離職.

後來我才知道,安排新主管只是他們設的一個陷阱,
我答應不答應都是一個坑.
而且那主管也知道我不會答應的,
利用這逼迫我離職.

然後他們馬上就花錢請另一個工程師.
這也讓我知道我們工程師非常不受尊重,
努力只是白費,被糟蹋了.

當我們選擇新創公司工作就是這樣,工作很容易不保,有時不是自己的問題,
遇到不好的主管或同事都是家常便飯.

轉換java到kotlin也是一樣,
常常??沒自動加上,執行時app就自主當機了.
轉換完後的kotlin非常不可信,需要再三檢查一遍. 

-----
Convert Java to Kotlin
With a Java file open in the editor, 
go to main menu and select Code | Convert Java File to Kotlin File
(or press Ctrl+Alt+Shift+K )

----

很方便快速,但當Java轉換Kotlin 後, 

我就發生執行app發生error:  

Caused by: java.lang.ClassNotFoundException: Didn't find class 

但這個file是之前從java 轉換到kotlin.

很神奇的是這只有在執行時才會出錯, compile 時卻可以通過android studio 編譯.

-----

solution:

從原本的java 專案在經歷轉換到Kotlin後,需要新增一些build.gradle code,不然會出現此類錯誤:

buildscript {

ext.kotlin_version = '1.7.10'
repositories {
mavenCentral()
google()
jcenter()
maven
{
url 'https://maven.google.com/'
name 'Google'
}
maven { url "https://jitpack.io" }
mavenLocal()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
classpath 'com.google.gms:google-services:4.+'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

另一個build.gradle要加:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'

android {
....
}


這樣重新build後再執行就可以了.

----

android studio在轉換java到Kotlin, 另一個問題: 

2022-07-20 11:51:59.515 6652-6652/com.mark.electricitybillcalculator E/AndroidRuntime: FATAL EXCEPTION: main

    java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter arg1

        at com.mark.electricitybillcalculator.fragment.Fragment_elec_fee_home_degree$onCreateView$2.onItemSelected

還是會當機!!!

solution:

看了之後原來是: spinner_months1!! -->要換成spinner_months1?

// 設定adapter
spinner_months1!!.adapter = adapter_months1
spinner_months1!!.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
arg0: AdapterView<*>?,
arg1: View,
position: Int,
arg3: Long
) {
b_month1_is_summer = func_elec_price.check_is_summary(position + 1)
if (ck_fee_follow_tw_power_corp!!.isChecked) {
fee_desctiption_was_change(rootView, true)
}
func_elec_price.hideSoftKeyboard(activity)
calcute_fee_result()
}

override fun onNothingSelected(arg0: AdapterView<*>?) {
// TODO Auto-generated method stub
}
}

改了之後就不會當了.

// 設定adapter
spinner_months1?.adapter = adapter_months1
spinner_months1?.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
arg0: AdapterView<*>?,
arg1: View,
position: Int,
arg3: Long
) {
b_month1_is_summer = func_elec_price.check_is_summary(position + 1)
if (ck_fee_follow_tw_power_corp!!.isChecked) {
fee_desctiption_was_change(rootView, true)
}
func_elec_price.hideSoftKeyboard(activity)
calcute_fee_result()
}

override fun onNothingSelected(arg0: AdapterView<*>?) {
// TODO Auto-generated method stub
}
}

這樣就不會當了.

因為spinner_months1在剛開始初始化時有可能是null, 而!!運算子會強制執行, 當然遇到null就當掉.所以改用? ,當spinner_months1未完成初始化時若是null 時就不要執行.



----
除此之外,當轉換成Kotlin後,
這個以前java用的檢查null判斷也可變成:
if (pair != null && pair.first != null) {
Log.d(SystemProperties.TAG, "total elec fee day=" + Math.round(pair.first!!))
}

Null-checks replaceable with safe-calls:
if (pair?.first != null) {
Log.d(SystemProperties.TAG, "total elec fee day=" + Math.round(pair.first!!))
}
很簡單對吧?!

Safe calls:
Your second option for accessing a property on a nullable variable is using the safe call operator ?.:

val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) // Unnecessary safe call

This returns b.length if b is not null, and null otherwise. The type of this expression is Int?

To perform a certain operation only for non-null values, you can use the safe call operator together with let: 

val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
    item?.let { println(it) } // prints Kotlin and ignores null
}


----
還有靜態常數的部分:

public class appdefine {

public static final int RESULT_CODE_APP_UPDATE = 0x9992;
}
轉換後變成:

object appdefine {

const val RESULT_CODE_APP_UPDATE = 0x9992
}
public class變成了 object
static final int 變成了const val

使用上還是一樣 appdefine.RESULT_CODE_APP_UPDATE

但對java使用者來說,這kotlin語法可能要習慣一下.

留言

這個網誌中的熱門文章

最爛的銀行服務-玉山銀行

SMR疊瓦式hdd致命缺陷被解決????!!!

Mark App Design Apps - Terms and Privacy Policy (服務條款,隱私權政策)

更改google drive預設存放目錄位置Change Google Drive Default Folder Location in Windows

ios app 上架時app icon要注意事項

Gmail 永久刪除大型電子郵件

舊有app在Android 12 閃退問題& app Splash screens

app bundle and bundletool. 關於aab安裝問題

關於google play console app應用程式簽署

google play 正式發布前測試報告...非常好用.