前言
久違的寫博客了!這段時間也算是加班完了累又不想學習,然後擱那瘋狂的摸魚。一直想開始記錄學習kotlin都沒時間,這次算是閒下來給自己個目標把kotlin學完吧!
基本使用
聲明變量
kotlin和java一樣都是有變量的,但是聲明的方式有挺大的區別
//java 聲明變量
int x; //默認值 0
String name; //默認值null
final int finalX = 5;
final String phone = "17712345678"
//kotlin
var x:Int = 0 //必須設置默認值
var name:String = "張三"
val finalX:Int = 5
val phone = "17712345678"
上面我們能看到區別,kotlin沒有默認值,聲明的時候必須設置值,統一用var
和val
作爲聲明 用:xxx
來說明參數的類型,甚至可以不聲明什麼對象讓系統自動識別出來對象的類型。還有就是int
變成了Int
部分相應的字段變化如下
java | kotlin |
---|---|
byte | Byte |
char | Char |
short | Short |
long | Long |
float | Float |
double | Double |
var number: Int = 1 // 👈還有 Double Float Long Short Byte 都類似
var c: Char = ‘c’
var b: Boolean = true
var array: IntArray = intArrayOf(1, 2) // 👈類似的還有 FloatArray DoubleArray CharArray 等,intArrayOf 是 Kotlin 的 built-in 函數
var str: String = “string”
我們發現基本都是使用了對象的形式,雖然原來的java也有但是我們一般都是用java自帶的,這邊要注意下使用對象形式的字段聲明
Null安全
上面我們看到kotlin是必須設置默認值的,就是爲了解決開發人員99%的崩潰異常(因爲基本都是NullPointerException崩潰[笑])
那我們就是要設置null初始對象呢其實也是可以的。
var x = null
var y:String? = null
lateinit var z: String //代表延遲初始化 需要在初始化中設置值
上面方式都可以設置爲null,但是要記得處理NullPointerException
那麼問題來了比如我們獲取到一段服務器的數據,肯定字段有可能爲空,我們應該如何處理呢!
class User {
var name:String? = null
var phone:String? = null
}
模擬使用如下
//模擬只獲取到了name字段沒有phone字段
var user = gson.fromJson("{name:\"李四\"}", User::class.java)
println("userName = ${user?.name}")
println("userPhone = ${user!!.phone}")
在使用的時候需要字段的時候加上?
或者!!
用來判斷是否爲空。
這兩個區別在於
"?"加在變量名後,系統在任何情況不會報它的空指針異常。
"!!"加在變量名後,如果對象爲null,那麼系統一定會報異常!
條件語句
if
我們在java中很常見的使用if也很簡單,kotlin其實也一樣只不過在這基礎上加了一些功能而已
//java
int c = 4
String reslut = ""
if(c == 2){
reslut = "正確"
}else if(c > 2){
reslut = "太大了"
}else{
reslut = "太小了"
}
//kotlin
var = 3
var reslut = if(c == 2){
"正確"
}else if(c > 2){
"太大了"
}else{
"太小了"
}
可以看到if是可以直接返回值的,幫助減少多餘的代碼
when
when可以理解爲java的switch,還是加強版
還是上面的案例
var reslut = when {
c == 2 -> "正確"
c > 2 -> "太大了"
else -> "太小了"
}
看着好像就是if的變化但是when其實是可以判斷類型或者直接在一個when中做多樣事情
var x = 11
var y = "kotlin"
var view:TextView? = null
when(view){
is TextView -> println("view is TextView")
is ImageView ,is ImageButton -> println("view is Image")
else -> println("I Do not know")
}
when {
x in 1..10 -> log("x in 1-10")
y.contains("k") -> println("$y contains k")
else -> println("I Do not know")
}
結果爲
I Do not know
kotlin contains k
我們可以看到不管是默認的switch判斷還是沒有對象的多種判斷(其實沒有對象判斷就是if-else的形式)when是一個很強大的條件語句
for
在原來java中我們for一般都是遍歷數組,kotlin中是可以快速遍歷數組和map等
我們這邊用1-10的遍歷寫下kotlin的一些常用功能
for(i in 1..10){
println(i) //1 2 3 ... 10
}
for(i in 1 until 10){
println(i) //1 2 3 ... 9
}
for(i in 1..10 step 2){
println(i) //1 3 5 ... 9
}
for(i in 10 downTo 1){
println(i) // 10 9 8 ... 1
}
for(i in 10 downTo 1 step 2){
println(i) // 10 8 6 ... 2
}
上面我們能看到一些變化
java | kotlin |
---|---|
1 <= 10 |
1 .. 10 |
1 < 10 |
1 until 10 |
i+=2 |
step 2 |
倒序遍歷(java需要自己手動修改) | downTo |
還有就是直接遍歷list和map的簡單示例
val array = arrayOf("a", "b", "c", "d")
for (value in array){
println(value) //a b c d
}
for (i in array.indices){
println(i) //0 1 2 3
}
for((i, value) in array.withIndex()){
println("$i=$value") //0=a 1=b ...
}
val map = mapOf("a" to 77, "b" to "kotlin", "c" to View(this))
for ((key, value) in map){
println("$key=$value") //a=77 b=kotlin c=android.view.View
}
函數
java中的方法全部在kotlin中改爲了fun
區別如下
//java
void main(){}
//kotlin
fun main(): Unit{} //Unit可以省略
fun main(){}
//java
int add(int a, int b){
return a + b;
}
//kotlin
fun add(a: Int, b: Int): Int{
return a + b
}
還有這邊要提一下kotlin中不給fun
設置可見修飾符private
、public
等默認情況是public
遇到個別關鍵字的時候就不是public
了
類
基本創建
java中創建類寫法和kotlin區別也是有的,具體情況如下
//java
public class JavaC {
private String name = "JavaC";
public JavaC() {}
public JavaC(String name) {
this.name = name;
}
}
//kotlin
class KotlinC {
var name: String = "KotlinC"
constructor()
constructor(name: String) {
this.name = name
}
}
java中我們的構造函數是直接寫類名而在kotlin中使用關鍵字constructor
代替
屬性的 getter/setter 函數
下面我們來說下屬性的get set
在java中我們可以使用setXXX getXXX來實現屬性的中轉,由於java中沒有空保護,所以我們一般都會在類的屬性get方法中加入類似如下方法
private String name;
public String getName() {
return name == null ? "" : name;
}
用於過濾掉Null錯誤,也可以在這邊實現強制修改值的功能等。在kotlin中我們需要在var的值下面直接調用get set方法和java區別挺大的,我們還是用上面的類做擴展 具體如下
public class JavaC {
private String name = "JavaC";
public JavaC() {
}
public JavaC(String name) {
this.name = name;
}
public String getName() {
return name + ".class";
}
public void setName(String name) {
this.name = "set " + name;
}
int add(int a, int b){
return a + b;
}
}
class KotlinC {
var name: String = "KotlinC"
//由於kotlin使用的是field代表變量所以必須直接寫在變量下方
get(){
return field + ".kt"
}
set(value) {
field = "set " + value
}
constructor()
constructor(name: String) {
this.name = name
}
}
//具體使用
JavaC javaC = new JavaC();
javaC.setName("JC");
println(javaC.getName()); //set JC.class
val kotlinC = KotlinC()
kotlinC.name = "KC"
println(kotlinC.name) //set KC.kt
類的繼承(: open override)
我們就用最常見的MainActivity用來說明
自動生成的代碼如下
//java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
//kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
我們看到extends
被:
替代、註解@Override
被關鍵字override
替代
這邊要說明下:
不僅可以代表extends
還可以代表implement
示例如下
interface Impl {}
//java
public class MainActivity extends AppCompatActivity implements Impl {}
//kotlin
class MainActivity : AppCompatActivity(), Impl {}
下面我們寫一個最經常使用BaseActivity類
abstract class BaseActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getLayoutId())
initView()
initData()
}
abstract fun getLayoutId(): Int
abstract fun initView()
abstract fun initData()
}
然後我們創建一個類繼承他
class NewActivity: BaseActivity() {
override fun getLayoutId(): Int {
return -1
}
override fun initView() {
}
override fun initData() {
}
}
我們發現和java中基本一致,只需要實現抽象的方法就可以了。
這邊我們說下override
在kotlin中是省略了protected
關鍵字,override
基本上是替代了protected
我們需要關閉override
的父類遺傳的話只需要在override
前面加上final
關鍵字關閉遺傳,比如之後我們在創建一個類繼承NewActivity時候發現錯誤
class NewActivity2: NewActivity() {
//報錯:This type is final, so it cannot be inherited from
}
發現類默認是final
修飾的,編譯器建議我們添加open
字段,代碼如下
open class NewActivity: BaseActivity() {}
之後我們新類就不會報錯了!open
打開了默認的final
鎖,而final
也可以鎖住override
的遺傳性
類型的判斷和強轉(is as)
在java中我們用instanceof
判斷參數是否是屬於該類在kotlin中是使用is
,示例如下
首先我們先在NewActivity類中加入一個新的方法test NewActivity2中也繼承並重寫方法
open class NewActivity: BaseActivity() {
...//其他代碼
open fun test(){
println("NewActivity test")
}
}
class NewActivity2: NewActivity() {
override fun test(){
println("NewActivity2 test")
}
}
然後我們調用方法
val new1:Activity = NewActivity()
val new2:Activity = NewActivity2()
if (new1 is NewActivity) {
new1.test() //NewActivity test
}
if (new2 is NewActivity) {
new2.test() //NewActivity2 test
}
我們發現kotlin幫我們省略了一些代碼 在java中需要((NewActivity) new1).test()
這樣實現
那麼我們直接強轉代碼如下
//java
((NewActivity) new1).test();
//kotlin
(new1 as NewActivity).test()
如果我們強轉失敗呢,as
明顯是可能轉換失敗的,這邊還是使用kotlin的?
用來直接進行Null保護
val new3: Activity = MainActivity()
(new3 as? NewActivity)?.test()
這段代碼直接就會不執行
總結
算是kotlin基礎開頭的學習吧!繼續學習了!