Android Java语言转Kotlin语言学习指导实用攻略
Android Java语言转Kotlin语言学习指导实用攻略
一、前言
Kotlin七八年前也学习过但是很少用过,现在一看发现大部分知识都忘记了;
为啥要学习kotlin,因为系统开发的代码也有很多用到了kotlin代码:
比如:
//系统应用 SystemUI 和 PackageInstaller
# frameworks/base/packages$ find . -name *.kt
./SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerKt.kt
./SystemUI/shared/src/com/android/systemui/shared/hardware/InputManager.kt
./SystemUI/shared/src/com/android/systemui/shared/hardware/InputDevice.kt
...
./PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallActionListener.kt
./PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
./PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt//系统权限管理 permission
# frameworks/base/services$ find . -name *.kt
./permission/java/com/android/server/permission/access/permission/PermissionService.kt
./permission/java/com/android/server/permission/access/permission/Permission.kt
./permission/java/com/android/server/permission/access/permission/DevicePermissionPersistence.kt
...
上面是Android15 的源码代码,比之前Android13的代码kotlin代码多了好几倍;
Android13好像只有 SystemUI 部位代码是kotlin,后续系统代码估计会更多kotlin代码了!
所以说学习kotlin是非常有必要的。
kotlin有些代码看起来不难,比如下面一段代码:
var name: String = "John" // 可变变量
val age: Int = 30 // 不可变变量(类似 final)
if (age > 15) {Log.i(TAG, "成年人了")
}
大致能看懂,主要内容:
kotlin定义的变量关键字和Java不一样,使用var或者val;
kotlin后面不需要分号; ,if、else 那些逻辑写法是一样的;
但是复杂的kotlin就比较难懂了,比如下面一段代码:
@Composable
fun Greeting(name: String) {Card(modifier = Modifier.padding(16.dp).fillMaxWidth(),elevation = 8.dp) {Column(modifier = Modifier.padding(16.dp)) {Text(text = "Hello, $name!",fontSize = 24.sp,fontWeight = FontWeight.Bold)Spacer(modifier = Modifier.height(8.dp))Button(onClick = { /* 处理点击事件 */ },modifier = Modifier.align(Alignment.End)) {Text("Click Me")}}}
}
上面是一段动态修改UI并且添加点击监听事件的代码;好像完全看不懂!写法也太简易了。
关键字:fun、Greeting、modifier、Modifier、Card、Column、Spacer 这些都是Java没有的;
如果没有深入学习过是不会懂的。之前学习基本用法好像没有学习过这些内容!
好吧,现在打算重新温习一下之前的知识学习看看kotlin其他知识吧。
本文主要让大家知道kotlin相关知识,和如何入门学习kotlin。
二、Kotlin 学习攻略:从入门到实战的系统指南
下面是kotlin各阶段主要相关知识:
第一阶段:基础语法与核心特性(1个月)
必学内容
- 变量与类型系统:
val/var
声明、类型推断、可空类型(String?
)、类型安全转换(as?
) - 函数与 Lambda 表达式:具名函数、匿名函数、高阶函数(如
forEach
)、函数引用(::println
) - 类与对象系统:主构造函数、
data class
、单例模式(object
关键字)、继承与接口实现 - Kotlin 特色语法:
- 空安全:
?.
(安全调用)、!!
(非空断言)、?:
( Elvis 操作符) - 扩展函数:为现有类添加功能(如
String.toChineseDate()
) - 中缀表达式:
1 to "one"
- 解构声明:
val (a, b) = pair
- 空安全:
实践建议
- 完成 Kotlin 官方入门教程
- 用 Kotlin 重写 Java 基础程序(如计算器、文件操作)
- 实现简单数据结构(链表、栈)理解泛型语法
第二阶段:Android 集成与进阶特性(2 个月)
核心技术栈
- 协程(Coroutines):
- 结构化并发(
launch
/async
)、作用域管理(CoroutineScope
) - 异步流处理(
flow
/stateFlow
) - 结合 Retrofit 实现网络请求
- 结构化并发(
- Jetpack 组件集成:
- ViewModel + LiveData + DataBinding
- Room 数据库(Kotlin DSL 查询)
- WorkManager(协程版 API)
- Compose 声明式 UI:
- 状态驱动 UI(
mutableStateOf
) - 组合函数(
@Composable
) - 动画与布局系统
- 状态驱动 UI(
进阶语法
- 泛型编程:
in/out
型变、类型约束(where T : Comparable
) - 元编程:注解处理(KotlinPoet)、反射(
KClass
) - 运算符重载:实现
+
、[]
等操作符
第三阶段:架构实践与性能优化(1个月)
工程实践
- 架构模式:
- MVVM(结合 Hilt 依赖注入)
- Clean Architecture(领域模型设计)
- Multi-Module 项目结构
- 性能优化:
- 内联函数(
inline
)与反编译分析 - 密封类(
sealed class
)替代状态枚举 - 协程上下文复用(
Dispatchers
优化)
- 内联函数(
跨平台开发
- Kotlin Multiplatform(KMP)基础
- 与 iOS/Swing/JS 的互操作
上面知识展示kotlin大概的知识,细节上的很多知识需要自己搜索学习,比如kotlin很多不同的关键字;
看完上面kotlin主要内容才知道,之前学习的kotlin都是第一阶段的知识;
还有很多kotlin相关的知识没有去学习,其实普通项目开发第一和第二阶段的知识已经够用了;
所以我目前也是打算温习第一阶段知识,学习一下第二阶段知识;
如果是大的kotlin项目会用到第三阶段的知识,小应用没必要写得太复杂。
上面是学习kotlin的大纲知识,只是一个大概的学习路线,更多更详细的学习资料需要另外寻找;
下面是学习kotlin的技巧。
三、Java转Kotlin学习技巧
现在从Android Java想要学习kotlin其实没有那么难,因为:
1、现在新版本的Android Studio兼容Java代码和Kotlin代码;
2、Android Studio新建一个Kotlin项目代码,里面不同的类可以写Java代码也可以写Kotlin代码,
3、xml布局的控件kotlin和Java代码都可以find和控制;
4、Android原生提供的api接口,在Java和Kotlin是一样调用的,有些UI相关的api,Kotlin是做替换了关键字;
5、另外Java代码可以调用到Kotlin的类,Kotlin的类也可以调用Java的代码;
6、另外,Kotlin的代码复制到Java的类,会提示是否转换为Kotlin的代码;
7、最狠的一个:Java文件代码的类可以右键一键转换成Kotlin文件代码(虽然不一定完全准确)。
所以基于以上了解,学习kotlin就不会很吃力的,
只要你会写Java代码,那么学习kotlin第一和第二阶段的知识是没啥问题的;
kotlin学习只要难点无非就是关键字不认识,不懂什么意思;
看到上面第7点:Java代码文件可以转换成Kotlin代码文件,
你在Android Studio写一个Java可以运行的代码,转换成kotlin就可以了;
另外使用AI工具或者在线网址,也可以一键转换Java和kotin的代码,虽然有时候会不准确,稍微修改一点就可以用了。
上面只是学习kotlin的一些技巧,如果要学好kotlin还是需要多看多学多练。
三、其他
1、Java代码转换成Kotlin示例
Android Studio 创建一个kotlin项目,可以在里面写Java代码是没啥问题的,
并且Java调用Kolin对象,Kotlin调用Java对象都是没啥问题的。
两个语言在Android Studio中转换也是比较简单的,下面简单讲解一下:
(1)Java代码片段转换kotlin代码
下面框的地方是Java代码,复制到kt文件中,会提示是否自动转换成kotlin代码。
点击“Yes”转换后,会变成kotlin,如下图所示;
可以看到该有的逻辑都在,打印代码也在,代码变得简便一下了。
所以某个Java方法如果需要加在kotlin代码中,但是又不是很熟悉的情况,
就可以用Android Studio自动转换的方式,获取kotlin代码后加入。
注意:kotlin代码 复制到Java文件代码中,是没有提示的,会有很多报错。
(2)Java代码文件整个转换成kt文件
选择kt文件后,右键最下面就有“ Convert Java File to Kotlin File ”可以转换成kotlin文件的选择
上面本来是Java代码,点击转换后:
可以看类文件左边的小图标会发生变化,点击代码文件可以看到是kotlin的代码。
Android Studio中查看了一下只有Java转换Kotlin的工具和选项,
没看到Kotlin转换成Java的选项,网上搜到的都是假的;
其实不用慌,现在AI搜索工具非常发达,Kotlin转Java或者Java转Kotlin 都是没啥问题的。
2、Java和Kotlin 共存 demo代码实现
下面写了一个demo,两个一样的Activity界面,功能也是一样;
但是一个界面的代码使用的是Java代码,另外一个界面的逻辑使用的是Kotlin代码实现;
(1)效果
如下动图所示:
主要功能是:两个数相乘在后台计算后显示在右边;添加一个和上面数值相关的列表显示;
点击上面的标题,就会跳转到另外一个Activity。
(2)主要相关代码结构
如下图所示:
kotlin的项目就是要在gradle中配置一下支持kotlin,并且添加相关依赖就可以编译kotlin代码了;
上面把kt单独放在一个目录区分,主要是为了更好看,实际也可以不用区分,正常编译运行时没啥问题的。
可以看到 DebugLog.java工具类 在Java代码和kotlin代码都是可以调用的。
上面的Adapter和Item bean类也是可以共用的,这里只是为了多学习所以多写两个看看。
(3)主要代码
xml布局没啥好说的,一个 主界面是:LinearLayout布局,加上一个普通的item布局
Java相关代码:
①MainActivity.java
Java主界面代码
package com.liwenzhi.webview;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import com.liwenzhi.webview.kt.MainKotlinActivity;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private TextView tv_title;private TextView tv_result;private EditText et_num1;private EditText et_num2;private Button btn_calc;private RecyclerView rv_list;private JavaAdapter mAdapter;private List<JavaItem> mItemList;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);DebugLog.info("");initView();initData();initEvent();}private void initView() {tv_title = findViewById(R.id.tv_title);tv_result = findViewById(R.id.tv_result);et_num1 = findViewById(R.id.et_num1);et_num2 = findViewById(R.id.et_num2);btn_calc = findViewById(R.id.btn_calc);rv_list = findViewById(R.id.rv_list);}private void initData() {tv_title.setText("Java Demo");rv_list.setLayoutManager(new LinearLayoutManager(this));mItemList = new ArrayList<>();mAdapter = new JavaAdapter(mItemList);rv_list.setAdapter(mAdapter);}private void initEvent() {tv_title.setOnClickListener(this);btn_calc.setOnClickListener(this);}@Overrideprotected void onResume() {super.onResume();DebugLog.debug("");}@Overridepublic void onClick(View v) {DebugLog.info("view = " + v.getId());switch (v.getId()) {case R.id.tv_title:startActivity(new Intent(this, MainKotlinActivity.class));finish();break;case R.id.btn_calc:getResult();generateData();break;}}private void getResult() {// 使用线程池和回调Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {// 后台任务final String result = fetchData();// 回到主线程runOnUiThread(new Runnable() {@Overridepublic void run() {tv_result.setText(result);}});}});}//数值相乘求结果private String fetchData() {String num1 = et_num1.getText().toString();String num2 = et_num2.getText().toString();String result = "";try {result = "" + Integer.parseInt(num1) * Integer.parseInt(num2);} catch (NumberFormatException e) {DebugLog.error("NumberFormatException num1 = " + num1 + ", num2 = " + num2);return "error";}DebugLog.debug("result = " + result);return result;}//生成列表数据private void generateData() {mItemList.clear();int intNum1 = 0;int intNum2 = 0;String num1 = et_num1.getText().toString();String num2 = et_num2.getText().toString();try {intNum1 = Integer.parseInt(num1);intNum2 = Integer.parseInt(num2);} catch (NumberFormatException e) {DebugLog.error("NumberFormatException num1 = " + num1 + ", num2 = " + num2);}for (int i = 0; i < 10; i++) {mItemList.add(new JavaItem(intNum1 + i, intNum2 + i));}mAdapter.notifyDataSetChanged();}}
上面的代码都是比较简单易懂的,除了写了一个线程池的写法比较少用到。
② JavaAdapter.java
RecyclerView 的适配器的代码
package com.liwenzhi.webview;import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import java.util.List;public class JavaAdapter extends RecyclerView.Adapter<JavaAdapter.MyViewHolder> {private List<JavaItem> itemList;public JavaAdapter(List<JavaItem> itemList) {this.itemList = itemList;}@NonNull@Overridepublic MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);return new MyViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull MyViewHolder holder, int position) {JavaItem item = itemList.get(position);holder.tv_info.setText("" + item.getInfo());holder.tv_result.setText("" + item.getResult());}@Overridepublic int getItemCount() {return itemList.size();}public static class MyViewHolder extends RecyclerView.ViewHolder {public TextView tv_info;public TextView tv_result;public MyViewHolder(@NonNull View itemView) {super(itemView);tv_info = itemView.findViewById(R.id.tv_info);tv_result = itemView.findViewById(R.id.tv_result);}}
}
③ JavaItem.java
普通的item代码
package com.liwenzhi.webview;public class JavaItem {private int num1 = 0;private int num2 = 0;JavaItem(int num1, int num2) {this.num1 = num1;this.num2 = num2;}public String getInfo() {return num1 + " * " + num2 + " = ";}public int getResult() {return num1 * num2;}
}
kotlin代码:
Kotlin的代码文件后缀不再是java而是Kotlin的简称kt
④ MainKotlinActivity.kt
kotlin写的界面代码
package com.liwenzhi.webview.ktimport android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.liwenzhi.webview.DebugLog
import com.liwenzhi.webview.R
import java.util.concurrent.Executorsclass MainKotlinActivity : AppCompatActivity(), View.OnClickListener {private lateinit var tv_title: TextViewprivate var tv_result: TextView? = nullprivate var et_num1: EditText? = nullprivate var et_num2: EditText? = nullprivate var btn_calc: Button? = nullprivate var rv_list: RecyclerView? = nullprivate var mAdapter: KotlinAdapter? = nullprivate var mItemList: ArrayList<KotlinItem>? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)initView()initData()initEvent();}override fun onResume() {super.onResume()DebugLog.debug("")}private fun initView() {tv_title = findViewById(R.id.tv_title)tv_result = findViewById(R.id.tv_result)et_num1 = findViewById(R.id.et_num1)et_num2 = findViewById(R.id.et_num2)btn_calc = findViewById(R.id.btn_calc)rv_list = findViewById(R.id.rv_list)}private fun initData() {tv_title?.text = "Kt demo"mItemList = ArrayList() //kotlin 没有new关键字mAdapter = KotlinAdapter(mItemList as ArrayList<KotlinItem>) // 不加 as ArrayList<KotlinItem> 会报错!因为Kotlin 没有泛型数组,只有泛型列表rv_list?.layoutManager = LinearLayoutManager(this) // 布局管理器绑定到列表,必须加,不然不显示rv_list?.adapter = mAdapter // 适配器绑定到列表,这种写法就很怪!因为Kotlin 没有setAdapter方法,只有adapter属性}private fun initEvent() {tv_title?.setOnClickListener(this)btn_calc?.setOnClickListener(this)}override fun onClick(v: View) {DebugLog.info("view = " + v.id)when (v.id) {R.id.tv_title -> {DebugLog.debug("点击了标题")startActivity(Intent(this, MainKotlinActivity::class.java))finish()}R.id.btn_calc -> getResult()}}private fun getResult() {generateData() // 生成列表数据,并更新列表// 使用线程池和回调Executors.newSingleThreadExecutor().execute { // 后台任务val result = fetchData()// 回到主线程runOnUiThread { tv_result!!.text = result }}}//数值相乘求结果private fun fetchData(): String {val num1 = et_num1?.text.toString()val num2 = et_num2?.text.toString()var result = ""try {result = "" + num1.toInt() * num2.toInt()} catch (e: NumberFormatException) {DebugLog.error("NumberFormatException num1 = $num1, num2 = $num2")return "error"}DebugLog.debug("result = $result") //可以写成Java一样,Kotlin也可以写成 这种类似C的写法return result}//生成列表数据private fun generateData() {mItemList?.clear()var intNum1 = 0var intNum2 = 0val num1 = et_num1!!.text.toString()val num2 = et_num2!!.text.toString()DebugLog.debug("num1 = $num1, num2 = $num2")try {intNum1 = num1.toInt()intNum2 = num2.toInt()} catch (e: java.lang.NumberFormatException) {DebugLog.error("NumberFormatException num1 = $num1, num2 = $num2")}for (i in 0..9) {mItemList?.add(KotlinItem(intNum1 + i, intNum2 + i))}DebugLog.debug("mItemList size = " + mItemList?.size + " , " + mAdapter)mAdapter?.notifyDataSetChanged()}}
上面的代码还是比较简单明了的,逻辑上可以对比Java代码。
上面的代码对比Java主要区别:
1、继承和实现接口不用区分,不用关键字,使用逗号,区分分隔;
2、变量定义的关键字不同,Kotlin只用var和val;
3、kotlin没有void,只能用fun;
4、kotlin没有new,直接省略就行;
5、kotlin没有switch只有when;
6、kotlin对象基本都要添加问号?或者两个说明号::进行判空;
7、线程池和普通回调使用可以省略很多关键字;
8、RecyclerView 的赋值Adapter不能用set,用变量赋值就行。
⑤ KotlinAdapter.kt
kotlin写的 RecyclerView的适配器的代码
package com.liwenzhi.webview.ktimport android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.liwenzhi.webview.Rclass KotlinAdapter(private var itemList: List<KotlinItem>) :RecyclerView.Adapter<KotlinAdapter.MyViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// val view = LayoutInflater.from(parent.context).inflate(R.layout.item_layout, parent, false)val view = View.inflate(parent.context, R.layout.item_layout, null)return MyViewHolder(view)}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val item = itemList[position]holder.tv_info.text = "" + item.infoholder.tv_result.text = "" + item.result}override fun getItemCount(): Int = itemList.sizeclass MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var tv_info: TextView = itemView.findViewById(R.id.tv_info)var tv_result: TextView = itemView.findViewById(R.id.tv_result)}
}
上面可以看到kotlin的构造方法可以直接声明在类定义的地方。
⑥ KotlinItem.kt
kotlin写的item bean类代码
package com.liwenzhi.webview.ktclass KotlinItem internal constructor(num1: Int, num2: Int) {private var num1 = 0private var num2 = 0init {this.num1 = num1this.num2 = num2}val info: Stringget() = "$num1 * $num2 = "val result: Intget() = num1 * num2
}
为啥这里的构造方法需要添加关键字:internal constructor,上面Adapter不需要?
其实也可以不使用这两个关键字也可以的,这里作用只是为了限制使用范围;
internal 类似 protected 的作用,但是作用范围又大一些,
当构造函数需要对库内部可见,但对外部隐藏时使用。
比如使用了internal constructor关键字,变成的jar包,其他应用导入后不能new这个构造方法。
Kotlin 提供四种访问修饰符:public
、private
、protected
、internal
。
这个demo也是学习kotlin的一个简单演示,更多的还需要自己去实践磨练。
可以把写过的Android demo 使用kotlin写一遍,基本就能掌握kotlin第一阶段的内容了;
3、Android Kotlin 用法对比Java使用小结
本文介绍一些入门级的Kotlin简单用法,可以对Kotlin的代码使用有个大致了解。
以下是 Kotlin 与 Java 在 Android 开发中核心差异的详细对比:
https://blog.csdn.net/wenzhi20102321/article/details/148797427