Kotlin基础概念

522 阅读7分钟

简介

与Java对比,学习一些常用的Kotlin用法,后续会使用具体的开发实例进行训练。

对象

Java写法:MainActivity.this

Kotlin写法:this@MainActivity

Java写法:MainActivity.class

Kotlin写法:MainActivity::class.java

继承

Java写法:

public class MainActivity extends AppCompatActivity {
}

Kotlin写法:

class MainActivity: AppCompatActivity() {
}

变量

Java写法:

Intent intent = new Intent();

Kotlin写法:

Intent intent = Intent();

常量

Java写法:

final String text = "text";

Kotlin写法:

var text = "text"

静态常量

java写法:

public class MainActivity extends AppCompatActivity {
	final static String TEXT = "text";
}

kotlin写法:

const val TEXT = "text"
class MainActivity : AppCompatActivity() {
}

定义方法

Java写法

public void method(String message) {
	//body
}

kotlin写法:

fun method(message: String) : Unit {
	//body
}

//Unit表示空返回值,可以省略
fun method(message: String) {
	//body
}

重载方法

Java写法:

public class MainActiity extends AppCompatActivity {
	@Override
  	protected void onCreate(@Nullable Bundle savedInstanceState) {
  		super.onCreate(savedInstanceInstance);
  	}
}

kotlin写法:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState);
    }
}

基本数据类型

Java写法

int i =1;
long l = 2;
boolean b = true;
double d= 2.0;
float f = 1.0f;
char a = 'a';
String s = "text";

kotlin写法:

var i : Int = 1
var l : Long = 2
var b : Boolean = true
var d : Double = 2.0
var f : Float = 1.0F
var a : Char = 'a'
var s : String = "text"

// kotlin提供类型推断,可不说明类型
var i = 1
var l = 2
var b = true
var d = 2.0
var f = 1.0F
var a = 'a'
var s = "text"

比较类型

Java写法:

if ("" instanceOf String) {
}

Kotlin写法

if ("" is String) {
}

转换符

Java写法:

int number = 100;
System.out.println(String.format("The number is %d", number);

Kotlin写法:

var number = 100
println("The number is ${number}")
//换一种简单的写法
println("The number is $number")

字符串比较

Java写法

String s1 = "text";
String s2 = "text";
if (s1.equals(s2)) {
	//do something
}

kotlin写法:

kotlin中==比较的是数值是否相等, 而===比较的是两个对象的地址是否相等

var s1 = "text"
var s2 = "text"
if (s1 == s2) {
	//do something
}

数组

java写法

int[] array1 = {1, 2, 3}
float[] array2 = {1f, 2f, 3f}
String[] array3 = {"1", "2", "3"}

kotlin写法

val array1 = intArrayOf(1, 2, 3)
val array2 = floatArrayOf(1f, 2f, 3f)
val array3 = arrayListOf("1", "2", "3")

循环

Java写法

String[] array = {"1", "2", "3"};
for (int i = 0; i < array.length; i++) {
	System.out.println(array[i]);
}

kotlin写法

val array = arrayListOf("1", "2", "3");
for (i in array.indices) {
	println(array[i]};
}

//使用角标循环
for (i in IntRange(1, array.size - 1)) {
	println(array[i]};
}

//更简洁的写法1
for (i in 1..array.size - 1) {
	println(array[i]};
}

//更简洁的写法2
for (i in 1 unitl array.size) {
	println(array[i]};
}

高级循环

Java写法

String[] array = {"1", "2", "3"};
for (String item : array) {
	System.out.println(item);
}

Kotlin写法

var array = arrayListOf("1", "2", "3");
for (item in array) {
	println(item);
}

判断器

Java写法:

int count = 1;
switch(count) {
    case 0:
        System.out.println(count); 
        break;
    case 1:
    	//fall through
    case 2:
    	System.out.println(count); 
    	break;
    default:
    	System.out.println(count); 
    	break;
}

kotlin写法:

var count = 1
when(count) {
    0 -> {
        println(count)
    }
    int 1..2 -> {
        println(count) 
    }
    else -> {
        println(count) 
    }
}

//只有一条语句,可以省略括号
when(count) {
    0 -> println(count)
    int 1..2 -> println(count)
    else -> println(count)
}

构造函数

Java写法

public class MyView extends View {
    private MyView(Context context) {
        this(context, null);
    }
    
    public MyView(Context context, @Nullable AttributSet attrs) {
        this(context, attrs, 0);
    }
    
    public MyView(Context context, @Nullable AttributSet attrs, int defstyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

Kotlin写法:

class MyView : View {
    constructor(context: Context) : this(context, null) {
    }
    
    constructor(context : Context, attrs : AttributSet?) : this(context, attrs, 0) {
    }
    
    constructor(context : Context, attrs : AttibuteSet?, defStyleAttr : Int) : 
    	super(context, attrs, defStyleAttr) {
    }
}

//括号内容为空,可以省略
class MyView : View {
    constructor(context: Context) : this(context, null)
    
    constructor(context : Context, attrs : AttributSet?) : this(context, attrs, 0)
    
    constructor(context : Context, attrs : AttibuteSet?, defStyleAttr : Int) : 
    	super(context, attrs, defStyleAttr)
}

//只有一种构造函数
class MyView(context : Context?) : View {
}

类创建

java写法

public class Person {
    String name;
    int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Person person = new Person("King", 37);
person.setName("James");
person.setAge(38);
System.out.println("name is " + person.getName() + 
        ", age is " + person.getAge());

Kotlin写法

如果不想暴露变量的set方法,可以将var改为val

class Person {
    var name : String? = null
    	get() = field
    	set(value) {field = value}
    var age : Int = 0
    	get() = field
    	set(value) {field = value}
}

//更简单的写法
class Person(var name : String, var age : Int)

var person = Person("King", 37)
person.name = "James"
person.age = 38
println("name is {$person.name}, age {$person.age}")

私有化set方法

Java写法

public class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    private void setAge(int age) {
        this.age = age;
    }
}

kotlin写法

class Person {
    var name : String ? = null
    private set
    
    var age : Int = 0
    private set
}

私有化get方法

Java写法

public class Person {

    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;
    }

    private int getAge() {
        return age;
    }

    private void setAge(int age) {
        this.age = age;
    }
}

kotlin写法:

class Person {
    private var name : String ? = null
    
    private var age : Int = 0
}

枚举

Java的写法

enum Color {
    RED(0x000), BLUE(0x222)
    Color(int value) {}
}

Kotlin写法

enum class Color (var value: Int) {
    RED(0x000), BLUE(0x222)
}

接口

Java写法

public interface Callback {
    void onSuccess();
    void onFail();
}

kotlin写法

interface Callback {
    fun onSuccess();
    fun onFail();
}

匿名内部类

Java写法:

new Callback() {
    @Override
    public void onSuccess() {
    }
    
    @Override
    public void onFail() {
    }
}

Kotlin写法:

object:Callback {
    override fun onSuccess() {
    }
    
    override fun onFail() {
    }
}

内部类

Java写法:

public class MainActivity extends AppCompatActivity {
    public class MyInnerClass {
    }
}

Kotlin写法:

class MainActivity : AppCompatActivity {
    inner class MyInnerClass {
    }
}

内部类访问外部类同名变量

Java的写法

String name = "king"

public class MyInnerClass {
    String name = "james";
    public void test() {
        System.out.println(name + ", outer name is " + MainActivity.this.name);
    }
}

Kotlin写法

var name = "king"

inner class MyInnerClass {
    var name = "james"
    
    fun show() {
        println("name is $name, outer name is ${this@MainActivity.name})
    }
}

抽象类

Java写法

public abstract class BaseActivity extends AppCompatActivity implements Runnable {
	abstract void initViews();
}

Kotlin写法

abstract class BaseActivity : AppCompatActivity(), Runnable {
    abstract fun initViews();
}

静态变量和方法

Java写法

public class Toastutils {
    public static Toast sToast;
    public static void show() {
        sToast.show();
    }
}

kotlin写法

kotlin中使用伴生对象带他static field或static function

companion object ToastUtils {
    var sToast : Toast ? null
    
    fun show() {
        sToast!!.show()
    }
}

可变参数

java写法

public init add(int ... array) {
    int count = 0;
    for (int i : array) {
        count += i;
    }
    return count;
}

kotlin写法

fun add(vararg array: Int) : Int {
    var count = 0;
    array.forEach {
        count += it
    }
    return count
}

泛型

Java写法

public class Bean<T extends String> {
    T data;
    public Bean(T t) {
        this.data = t;
    }
}
Bean<String> bean = new Bean<>("123123");

Kotlin写法

class Bean<T : Comparable<String>> (t: T) {
    var data = t
}
var bean = Bean<String>("123123")
// 更简洁的写法
var bean = Bean("123123");

代码块

Java写法

public class MainActivity extends AppCompatActivity {

    int number;

    {
        number = 1;
    }
}

Kotlin写法

class MainActivity : AppCompatActivity() {
    var number = 1
    init {
        number = 1
    }
}

静态代码块

Java写法

public class MainActivity extends AppCompatActivity {

    static int number;

    static {
        number = 1;
    }
}

kotlin写法

class MainActivity : AppCompatActivity() {
    companion object {
        var number = 0
        init {
            number = 1
        }
    }
}

方法块

Java写法

void test(){
    {
        int a = 1;
    }
}

Kotlin写法

fun test() {
    run {
        int a = 1
    }
}

可见修饰符

java写法

修饰符作用范围
public所有类可见
protected子类可见
default同一包下的类可见
private仅对自己可见

kotlin写法

修饰符作用范围
public所有类可见
internal同Module下可见
protected子类可见
private仅自己可见

Lambda

textView.setOnClickListener(View.OnClickListener {
            fun(v : View) {
                View.GONE.also { v.visibility = it }
            }
        })

textView.setOnClickListener { v -> v.visibility = View.GONE }

函数变量

val result = fun(number1 : Int, number2 : Int) : Int {
	return number1 + number2
}

print(result(1, 2))

空安全

类型被区分为可以使用null和不能使用null的情况

var string : String = "Kotlin"
string = null //error

var string : String? = "Kotlin"
string = null //ok

安全调用

string?.length

var len = string?.length ?: -1

!!操作符

代码会主动抛出NullPointerException

var len = string!!.length

当string为null的时候,代码执行时会抛出NullPointerException

安全转换

var string: String? = "kotlin"
var int: Int? = string as? Int

如果string不是Int类型,那么int为null

可空集合

如果list包含null

val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList : List<Int> = nullableList.filterNotNull()

方法支持添加默认参数

Java中扩展方法

public void toast(String text) {
    toast(this, text, Toast.LENGTH_SHORT);
}

public void toast(Context context, String text) {
    toast(context, text, Toast.LENGTH_SHORT);
}

public void toast(Context context, String text, int time) {
    Toast.makeText(context, text, time).show();
}

toast("弹个Toast");
toast(this, "弹个Toast");
toast(this, "弹个Toast", Toast.LENGTH_LONG);

Kotlin中可以在方法上直接定义参数的默认值

fun toast(context : Context = this, text : String, time : Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, text, time).show()
}

toast("弹个Toast");
toast(this, "弹个Toast");
toast(this, "弹个Toast", Toast.LENGTH_LONG);

类方法扩展

例:不改变String的情况,扩展方法

fun String.handle() : String {
    return this + " extension"
}

print("xyz: ".handle())

扩展函数

扩展函数时为了简化一些代码产生,主要包括:let、with、run、apply、also

let函数

// 作用1:使用it替代object对象去访问其公有的属性 & 方法
object.let{
   it.todo()
}

// 作用2:判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
   it.todo()
}

// 注:返回值 = 最后一行 / return的表达式

//使用1
var result : Int = "king".let {
     print(it.length)
     1000
}
print(result)

//使用2
mCanvas?.let {
    mCanvas.drawCircle()
    mCanvas.drawLine()
}                  

also函数

类似let函数,但区别在于返回值:

  • let函数:返回值 = 最后一行 或 return的表达式
  • also函数:返回值 = 传入的对象的本身
//let
var result : Int = "king".let {
     print(it.length)
     1000
}
// result值为1000

//also
var result : Int = "king".also {
     print(it.length)
     1000
}
// result值为 字符串 king

with函数

调用同一个对象的多个方法 / 属性时,可以省去对象名重复,直接调用方法名 / 属性即可

var p = Person("king", 17)
with(p) {
    print("name is $name, age os $age")
}

run函数

结合了let、with两个函数的作用,即:

  • 调用同一个对象的多个方法 / 属性时,可以省去对象名重复,直接调用方法名 / 属性即可
  • 定义一个变量在特定作用域内
  • 统一做判空处理
p?.run {
    print("name is $name, age os $age")
}

apply函数

与run函数类似,但区别在于返回值:

  • run函数返回最后一行的值 / 表达式
  • apply函数返回传入的对象的本身
var result1 = p.run {
    print("name is $name, age os $age")
    1024
}
//result1值为1024

var result2 = p.apply {
    print("name is $name, age os $age")
    1024
}
//result2值为 p对象