Kotlin语法详解与实践教程,区分JAVA以及如何闭坑

背景:kotlin

kotlin在今天的Android市场已占领了一部分开发语言的份额,大公司在面试或者项目中已涉及到kotlin,下面我将简单介绍一下kotlin的写法与坑是如何规避。该文档江不断更新与优化,下面会从大概到详细的一个过场。以及kotlin的在Android中的写法与使用技巧!

kotlin比较混淆的地方语法使用

var与val:var是定义一个变量,var a:Int=1,在后期使用可以,val是定义一个常量,后期将不可修改。

标识:"?" 、"!!"

people?

people?.name?:"name is null"

people!!.name

Switch与when

三目运算A=a>b?c:d,A=if(a>b)c else d

interface A{

public void log();

public void print(String msg);

}

interface A{

public void log();

public void print(msg:String){

println(msh)

}

}

open:

class A constraction(title:String){

var a;

set(){

//修改set参数

}

get(){

}

init(){

//初始化模块

}

}

in 和 is

in:是遍历数字,类似java foreach中的":"

kotlin:in

for( temp in arry){

}

Java: ":"

for(String value: arry){

}

is:是类型的判断,类似java instanceof,

kotlin: if(a is String)

java: if(a instanceof String)

三目运算

kotlin的语法不支持三目运算,因为?在kotlin中有特殊用法,如果一个参数a?,表示如果该参数为null,将返回一个null值。

Java: a>b?a:b

kotline: var max=if(a>b) a else b;

类的方法、函数扩展扩展:

kotline支持动态方法扩展,无须在类中提前定义好一个类,

class MyInfo{

}

//在其他地方给MyInfo新增一个新的方法,可以通过类名+“.”+ 方法名

fun MyInfo.getName():String{

return "li si"

}

这样就可以使用了

var info:MyInfo=MyInfo()

println(info.getName())

println(MyInfo().getName())

单利:kotlin的单利用关键字object来修饰的

object +类名

object DateUtil{
    var name="nihao"
    fun get():String{

        return name;
    }
}

关于类的继承:

JAVA:extends

kotline: ":"

kotlin的继承需要将该父类通过open来修饰,且继承通过":"+类名+()

如果 class A{

}

open class B{

}

如果A类需要继承B类,首先通过open关键字来修饰,然后继承即可

class A:B(){

}

类的构造器:

在kotlin中,如果参数需要在初始化时,需要通过类的沟通传入参数,需要通过关键字"constructor"来申明

class A constructor(a :Int,b:Int){

init{

     print("a=$a,b=$b")

}

}

上面的构造器属于一级构造器,如果针对Java中的方法重载,只要参数不同,但是kotlin的构造器只有一个主的,所以想要不同参数的构造器,只能通过二级构造器来完成。

open class MyConstraction constructor(name: String) {

       //重写构造器
    constructor(name: String, age: Int) {

    }
       //重写构造器
    constructor(name: String, age: Int, sex: Boolean) {
        
    }
    
    
}

二级构造器会造成误解,以及init方法会被多次调用,所以也可以将二级构造器变成一级使用

open class MyConstraction {

    constructor(name: String) {
        
    }

    constructor(name: String, age: Int) {

    }

    constructor(name: String, age: Int, sex: Boolean) {

    }


}

也可以通过默认参数构造器:只需要在类的后面新增参数即可,无须通过constructor关键字

open class MyConstraction (msg:String){
    

    constructor(name: String, age: Int) {

    }

    constructor(name: String, age: Int, sex: Boolean) {

    }


}

如果在Java文件中引用了默认参数类。new一个对象,发现报错,应该用 @JvmOverloads去修饰

open claa A @JvmOverloads constructor(name: String, age: Int){

}

默认参数初始值:
fun ok(msg:String="default"): String {

    return msg
}

可变参数:vararg

在Java中,可变参数通过...来定义,且放在参数最后一位,

public void test(String... list);

在Kotlin中,可变参数需要通过一个关键字来申明:vararg

fun test(vararg arry:String){

}

数组:

Java在定义数组int[] arry=new int[2]{1,2};

var  intarry:IntArray= intArrayOf(1,2,3,4,5)

格式:定义一个变量名:数组类型=赋值

String数组:

String 素组和其他数组有一点区别,按数据格式如下

var string_arry:Array<String>=arratOf("A","B","C")

但是一些版本中可能存在问题:提示错误

正确如下:

第一种:var string_arry=arrayOf("A","B","C",1,2,3,c)

或者

第二种

var string_arry:Array<String>

 string_arry=arratOf("A","B","C")

第一种写法,里面的内容可以是任何类型,第二种因为var已定义类型是String,所以在赋值只能是String类型,否则会报错,因为泛型已指定String导致。

字符拼接:

在java中,字符拼接常见如下

String a="ABC",b="abc";

b=b+c;结果是b="ABCabc",

或者StringBuild sb=new StringBuild();

sb.append("ABC").append("abc");

在kotlin中:

var a="ABC"

var b="abc is$a"

连接是通过美元符号$来链接你要拼接的内容。不需要+号

System.err.println("字符串长度${a.length}" )

如果拼接设计到对象属性,需要通过{}来包起来

由于美元符是特殊字符,打印该符号如下:${'$'}或者"\$"

容器:

在Java中,容器我们常见的有map,set等,在kotline里也有,但是kotlin的容易分为可变集合和只读集合

Java中:我们定义一个set,

Set set=new Set();

set.add(1);

set.add(2);

set.add(3);

这时,set里有三个值:1,2,3

在kotlin中,

var set:Set<String>

set=setOf(1,2,3,4);

这时set里有四个值,如果需要新增元素,通过如下plus()方法

set.plus(5),你打印发现并没有同步到set容器中,是因为plus()源码如下
public operator fun <T> Set<T>.plus(element: T): Set<T> {
    val result = LinkedHashSet<T>(mapCapacity(size + 1))
    result.addAll(this)
    result.add(element)
    return result
}

新增值以后,会生成一个新的result,这个result和原来的set已不是一个对象,并且在plus调用会返回,如果想保持一致,只需要再每次调用都把结果赋值给当前set,如果:

set=set.plus(5),这时候,set里面是5个数据集合

可变集合:

MutableSet:是set的可变即可。多了一个add方法

所以var mset:MutableSet<String>=mutableSetOf("A","B","C")

mset.add("D")

不可变通过plus一样可实现一个临时新的变量,MutableSet可变多一个add

List和MutableList也是参考Set的用法。同时,容器本身也支持排序:

sortBy和sortByDescending

Map的使用:

java中,map提供了key和value,

kotline写法:

var map:Map<String,String>
// 第一种
map= mapOf("a" to "65","b" to "66","c" to "67" );
//
map= mapOf(Pair("A","96"),Pair("B","97"),Pair("C","99"))
如果是可变MutableMap,依旧可以通过add来新增,如果不是,只能通过plus()来管理

容器的迭代:

1.in的使用

在Java中,我们迭代使用的for很多

for(int a=0;a<list.size();a++)或者for(String item:list)

但是在kotlin中,使用in来处理

for(item in list),也支持java的写法

for (index in list.indices) {
    println(     list.get(index))
}

2.Iterator

Java和kotlin都支持Iterator,写法也基本一样

Java:

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    String item=iterator.next();
}

Kotlin:

val  iterator=set.iterator();
while (iterator.hasNext())
{
    var value=iterator.next();
    
}

3.forEach,只要在for循环中定义一个容器类型的临时对象即可

Java中的forEach:

for(String item:list)

kotlin:容器本身提供一个forEach方法,item为内部的it对象,直接引用即可

set.forEach {  print(it)}

备注:如果使用$it连接符,需要注意,该连接符是连接"$it",后面不可连续接未定义的对象,

比如:print("值为:$it的数字"),这样会报错

正确:print("值为:$it 的数字")或者print("值为:${it}的数字")

需要通过{},把定义的变量引用到指定的位置

条件语句

1.if的使用

kotlin的if语句,不仅可以作为条件判断,还可以作为三目运算

类似Java的三目运算,因为kotlin不支持三目运算

var resullt=if(3>2){"3>2"}else{"3<2"}

其他就是正常的条件判断:

if(3>2){

printf("3>2");

}else{

printf("3<2");

}

2.when的语句

when语句和Java中的Switch语句一样,但是when语句支持的条件比Switch更多

Java:

switch (2)
{
    case 1:
        
        break;
            
            
}

kotlin:

when (text) {
    1 -> {
        println("1")
    }
    2 -> {
        println("2")
    }
    3 -> {
        println("3")
    }
    else -> {

        println("defaule:")
    }
}

java是从case,但是kotlin不需要,直接 "text->"格式,如果没命中,java是default,kotlin是else 

3.for循环 in的高阶用法

kotlin for循环非java的for(int index0;index<size;index++)

kotlin for特性如下:

3.1 until,从A到B,但是不包括B,【10,100),左边是闭区间,右边是开区间

for(item in 0 until 100)

tem=[0,100)

3.2 step:步长的意思,类似java for(a;,b;c)中c的条件

for(temp 0..100 temp 4)

这里面的".."连接,0..100=[0,100],step是步长

until 也可以配合temp一起使用:for(item in 0 until 100 temp 4)

3.3downTo:递减的意思

for ( item in 10 downTo   0)
从高到底递减,类似--

备注:这里面的特性如果没有特意写temp 的值,默认步长都是1,

也就是说:for ( item in 10 downTo 0)=for ( item in 10 downTo 0 temp 1)

4.while循环和do/while的使用:

Java和kotlin的是一样用法,可以参考java,

5.跳出多重循环break和continue与标记位@。

这两种的基本用法和java一样,但是kotlin多一个标记位,可以通过@ 来标记循环体的开始位置,直接跳转到该位置

var index: Int = 0
flag@ while (index < 10) {

    var j = 0
    secend@ while (j < 10) {
        if (j == 5) {
            break@secend
        }
        print("index=${index},j=${j}\n")
        j++
    }

    index++

}

在这里,我们定义了两个标记:flag和secend,在第二层嵌套while循环break到secend,也就是说如果j==5,跳出里面的循环,继续往下执行,如果break @flag,j==5,跳出整个循环体。这是break用法

continue也可以使用标记,但是请注意,continue使用标记可能会出现死循环,所以如果把上面的break换成continue,

var index: Int = 0
flag@ while (index < 10) {

    var j = 0
    secend@ while (j < 10) {
        if (j == 5) {
            continue@secend
        }
        print("index=${index},j=${j}\n")
        j++
    }

    index++

}

那么,当j=5时,由于j++在continue下面,continue跳转到secend标记位,这样j==5一直没变,导致进入死循环。所以在把continue与标记位结合,注意

6.字符串的有效判定

isNullOrEmpty:为空指针或者字符串长度为0返回true

isNullOrBlank:为空指针、字符串长度为0或者权威空格返回true

isEmpty:字符串长度为0

isBlank:字符串长度为0或者全为空格

isNotEmpty:字符串长度大于0

isNotBlank:字符串导航度大于0缺不全是空格

7.空对象的规避与使用

var a:string?=null

表示a可为null,即使你在使用直接返回是null ,而不会报空指针

包括方法参数也是如此fun test(txt:String?),表示txt可为null,否则ied会提示错误

即在参数后面加上?:a?.length返回null

7.1很多时候我们不想要null,想要默认值,可以通过"?:"来规避

(a?.length?:0)->如果a为null,那么返回的是null,这时,通过?:来达到三目运算符返回0

a?这种写法的好处是不会抛出空指针,但是会返回null

7.2 "!!"运算符,是变量从可控转向非可空,但是如果对象为null,需要自己去判断,否则会报空指针

var people:People?=null
people=People()
println(people.name?:"")//返回空
println(people.name)//返回null

8.==和equals的对比,“===”又是什么?

println("a"=="a") true
println("a".equals("a")) true

Java中==是对象的空间地址比较,kotlin比较的是当前对象的值,属于结构对比,简称值的比较。

那么"==="是什么呢?

var  p1:People= People()
var  p2:People=People()
println(p1===p2) false
println(p1!==p2) true
println("a"==="a") true

可以看出===和java中的==是一致的,是对象地址对比,!==和java中!=是一个效果,都是针对地址控件的判定

9.对象的类型判断 is 和!is

println("a" is String) true
println("a" !is String) false

10.函数的使用与定义

java :public void methodName(String name)或者public String methodName(String name)

这种是比较常见的使用,前面是无返回值,后一个是返回一个string

kotline: fun methodName(name:String)或者fun methodName(name:String):String

函数申明:fun ,函数名(参数),如果有返回值,在参数括号外新增“:返回类型”,:String=返回一个String

//无返回值

fun a(name:String){

printf(name)

}

//有返回值

fun add(txt:Int):Int{

var result=txt+10

return result

}

10.1方法继承

在Java中,如果继承一个类,实现该类的一个方法

@Override

public void log(String txt){

}

kotlin中,与java不一致,是小写override在fun前面

override fun log(txt:String){

}

10.2 类的继承

//父类

open class Base{
    open fun log(log:String?){

    }
}

//子类

class MyBase: Base() {

//方法的重写
    override fun log(log: String?) {
        super.log(log)
    }



}

父类在申明作用范围时,采用open,类似java public 。

继承直接用":",如果想使用父类的方法,该方法也必须修饰成open

10.3抽象类:

参考下方资料

10.4接口与接口的继承

参考下方资料

10.5形参默认值,

在函数中,我们经常会说形参与实参。形参默认值是很少听说,java中,形参不支持默认值,如果未传,默认传的就是null。但是kotlin与java还是有区别的

fun test(txt:String="你好"){

printf(txt)

}

如果调用了该方法,你即使不传值,默认也是调的通,打印"你好",Java就不行了。

调用有三种:

1.aa(txt = "hello") //打印:hello 
2.aa("哈喽")//打印:哈喽
3.aa()//打印:你好

第一种属于命名参数,可以指定多个参数中一个参数的值,其他是默认

10.6可变参数:

在Java中,如果我们定义一个可变参数,可用"..."来修饰,String... list,定义一个list字符数组

在kotlin中,依旧支持这种行为,通过关键字vararg来形容

Java:

public void log(String... log){

}

kotlin:

fun log(vararg log:String){

}

10.7匿名函数

匿名函数类型和lambda表达式非常详解,不需要定义一个完整的函数,通过lambda表达式来完成。可以参考下方资料

10.8泛型函数

泛型在JAVA中,使用的是对象构造时已指定,不能通过方法来构造,但是kotlin,可以通过方法来构造

Java:

public class MyTest1<T> {
    public static void main(String[] args) {
        MyTest1<Integer> test1 = new MyTest1<Integer>();
        System.out.println(test1.getLog(123));

    }


    public T getLog(T name) {

        if (name instanceof Integer) {
            System.out.println("name is Int");
        }
        return name;
    }

}

kotlin:

fun <T> myLog(txt: String, name: T): T {

    return name;

}

10.9内联函数

inline fun <reified T : Number> setTextValue(arry: Array<T>) {
    for (item in arry) {
        if (item is Int) {
            println("item is int value=${item}")
        }
    }

}

格式:inline fun<reified T:参数>方法名(value:T)

T是内联泛型,

调用:

setTextValue<Int>(arry),指定泛型类型,通过方法名<T>(参数)

10.10简化函数

//下面是1到100求和

fun add(n: Int): Int {
    if (n <= 1) {
        return n
    } else {
        return n + add(n - 1)
    }
}


//简化函数求和
fun add1(n: Int): Int=if (n<=1)  n else n+ add(n-1);

10.11尾递归函数

尾递归函数是指尾部值重复调用自身函数,在fun 关键字前加一个tailrec来修饰。

//如果是尾递归函数,编译器会利用循环替代递归,避免溢出(死循环)

tailrec fun  cons(x:Double=1.0) :Double{
    if (x==Math.abs(x))
        return x
    else return cos(Math.abs(x))

}

 

10.12高阶函数

 
运行将表达式作为参数传进来,形成高阶,如下:
 
fun <T> maxLength(arry: Array<T>, grate: (T, T) -> Boolean): T? {
    var max: T=arry[0]
    for (item in arry) {
        if (item == null || grate(item, max)) {
            max = item;
 
        }
    }
 
    return max;
}计算长度最大值,grate: (T, T) -> Boolean是高阶函数的参数,该写法属于lambda的匿名写法。

调用如下:

var list: Array<String>
list = arrayOf("lisi", "zhangshan", "wangwu", "jck")
var max=maxLength(list) { a, b -> a.length > b.length }
println("max=${max}")

函数后接表达式参数写法:{ a, b -> a.length > b.length }

{ a, b -> a.length > b.length }是lambda写法等同如下:

fun maxLengtj(a:T,b;t):Boolean{

var maxResult=if(a.length>b.length){

a

}else{

b

}

rreturn maxResukt

}

10.13扩展函数:

扩展函数是对函数自身的进行扩展,在java中,如果一个类提供了指定函数后,如不在原来类里进行扩展,该类将无法提供额外函数:

public void Log{

public void log(String log){

system.out.printf(log);

}

}

Log类只提供了一个方法,kotlin可以在原来类上进行扩展。

如果我们想对String这个函数新增一个方法,如下

fun 类名.方法名

fun String.hello(){

var value=toString()
print("hello value=${value}")

}

这个时候我们就新增了一个hello方法,

调用如下:

var  txt:String="nihao"
txt.hllo()

备注:扩展函数内部可以通过this来引用自己。

10.14日期函数

 格式:

1. yyyy=表示年份

2.MM=表示月份

3.dd:表示日期天

4.HH=表示24小时制

5.hh=表示12小时制

6.mm=表示分

7.ss=表示秒

8.sss-毫秒

如何使用:

//扩展函数

fun Date.newTime(): String {
    var time = SimpleDateFormat("HH:mm:ss:sss")
    return time.format(this)

}
//常见的使用
fun time() {
    var time = SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss")
    var result = time.format(Date())
    println(result)
}

调用如下:

time()

println(Date().newTime())

10.15单利对象:

单利对象在Java用比较常见,kotlin也支持单利模式,通过object关键字来修饰类。

object DataUtil {



    var newTime: String = ""
        get() {
            var  time=SimpleDateFormat("yyyy-MM-dd")
            return time.format(Date())
        }
    
}

利用对象get()方法重写,可以省去定义方法,也可以通过方法,效果一样

11.类的继承与构造

1.类在使用的使用,常见的就是构造器,继承,初始化

Java:

1.继承 ,通过extends来修饰,

public class V extends B

2.构造,参考方法的重载,即方法名相同,参数不同

kotlin:

继承:通过 “:”来修饰

class MyBase :BaseA(){
    override fun log() {
        super.log()
    }
}

基类需要通过open来修饰,该作用类似public,

open class BaseA {
   open fun log(){

        println(javaClass.name)
    }
}

构造器:

kotlin提供了一个默认的

init{

}

这个类,在构造器之前被执行

class MyBase constructor() {

    init {
        println("MyBASES")
    }

    constructor(aa: String) {

    }

    constructor(aa: String, bb: String) {

        println("MyBASES constructor=${aa}${bb}")
    }


}

构造器可以在类的后面接入,或者方法体中新增,支持多构造。

2.内部构造器的继承

kotlin中,继承通过":"来标识的,构造器也支持,

class MyBase constructor(aa: String) {

    init {
        println("MyBASES")
    }

    constructor() : this("") {
        println("MyBASES1 constructor=")
    }

    constructor(aa: String, bb: String) : this("") {
        println("MyBASES1 constructor=")
    }


}

如果你想调用其他构造器,通过:+this指向构造器,参数匹配即可

但是这里有个问题,如果构造器使用了this 指向,那么就需要其他构造器也要继承,否则会报错

Primary constructor call expected

上面的案例提供了三个构造器,而且只能方法体可以使用方法体内的或者类名默认构造器,类跟着构造器无法引用内部的。

3.类构造器的写法

class myBean(aa:String,bb:String){

}

或者

class MyBase constructor(aa: String) {

}

可以通过constructor来修饰,也可以省略

4.构造器的分类

kotlin的构造器分为主构造器和二级构造器,主构造器类名后面接的构造器,该构造器可以通过constructor来修饰,也可以直接省略该关键字。

二级构造器:除了主构造器,类的内部构造器都叫二级构造器,通过constructor来修饰,二级构造器可以引用主枸杞子,或者引用二级构造器,通过this,但是主构造器无法引用二级构造器。

主构造器没写constructor也叫默认构造器。

5.参数set和get修改

kotlin与Java不同,如果在定义一个可变参数,默认提供set和get方法,

class MyPeople {

    var name: String
        set(value) {
          println(value)
        }
        get() :String {
            return name
        }
}

我们可以在set和get修改值,注意有一点:var name:String后面不能加";"号,否则该语句算结束了,不能再提供set和get方法了,

这里面只要调用name就会调用set,不能在set中引用name变量,否则会死循环。所以在set中,不要处理当前变量名,否则会互相调用,进入死循环。

12.伴生对象

kotlin取消了static静态修饰,采用了伴生对象,这是一个内部修饰,用 companion object来修饰

class MyPeople {
companion object NameTag {
    fun tag(name: String): String {
        if (name.startsWith("a")) {
            return "A";
        } else if (name.startsWith("b")) {
            return "b"
        } else if (name.startsWith("c")) {
            return "c";
        } else {
            return "d";
        }
    }
}

}

调用如下:

println(MyPeople.NameTag.tag("a"))
println(MyPeople.tag("b"))

13.抽象类

Java中存在抽象类,abstract来修饰,抽象类只提供了抽象方法,不提供具体方法体,在kotlin中,同样也有抽象类这一修饰。也是通过abstract

abstract class Animation(kind: String = "") {

    var mkind = "";

    init {
        mkind = kind;
    }

    abstract fun getName():String;

    fun log() {
        print(mkind)
    }
}
class Kid(name: String = "") : Animation() {

    var mName = "";

    init {
        mName = name;
    }

    override fun getName(): String {
//        TODO("Not yet implemented")
        return mName;
    }


}

   备注:如果参数已赋默认值,在调用时,可以不传值。

构造器值的使用:主构造器的值不可以直接使用,只能在

init{

}

//中引用,如果构造器有默认参数值,可以省略不传。

抽象类和抽象方法都是通过abstract来修饰,用法和Java一样原则

14.接口

kotlin也支持接口,但是接口不支持构造器,但是接口支持的东西比较杂,

 interface KotlinInterface {

    fun log() {

    }

    abstract fun getName():String

    open fun setValue(name:String="")


}

class TestInterface : KotlinInterface {

    override fun getName(): String {
//        TODO("Not yet implemented")
        return "hello"
    }


    override fun setValue(name: String) {
//        TODO("Not yet implemented")
    }

}

14.1支持方法实现体,并可以,Java的接口是不支持方法的实现体,支持抽象方法,支持方法不实现方法体。

所以kotlin的接口实现丰富,和Java的有所区别。

14.2接口作为回调

如果接口作为回调,就不能设置抽象方法,否则提示报错。以下是接口作为参数回调使用

interface MyClickListener {

    fun log() {

    }

//    abstract fun getName():String

    open fun setValue(name:String="")

}

class TestMyClick {

    var clickListener: MyClickListener? = null

    fun setClick(click: MyClickListener) {
        clickListener = click

    }


    fun setName(name: String) {
        clickListener?.setValue(name)
    }


}


fun main() {
    var  item=TestMyClick()
    item.setClick(object :MyClickListener{
        override fun setValue(name: String) {
            TODO("Not yet implemented")
        }
    })

}

15.嵌套类

和Java一样,kotlin也支持内部类

Java:

publi class A{

public class B{

}

}

kotlin:

class TestInllClass {
    
    class Child {
        var name = ""
    }

}

fun main() {
    var item = TestInllClass.Child()
    item.name = "你好"
    print(item.name)
}

嵌套类和内部类只差一个修饰inner

1.内部类:inner

class TestInllClass {

    inner class Child {
        var name = ""
    }

}

inner关键字修饰表示内部类
嵌套类属于静态类和外部类没任何关系
内部类使用this,访问外部类的变

inner class Child(kids: String = "child") {
    var name = ""

    var tag = "child"

    fun getname(): String {
//外部对象
        return "${this@TestInllClass.tag}"
    }


    fun getOun(): String {
//自己
        return "${this.tag}"
    }
}

16.枚举

枚举在Java中支持,在kotlin也支持,都是通过enum来修饰,但是Java和kotlin的写法有点不同如下

Java

public enum People {
    One,Two,Three,Four
}

kotlin

enum class Peoples {
    One,Two,Three,Four
}

kotlin支持构造器写法,也就是给不同的item赋不同值

enum class Peoples(name:String="默认值") {
    One("1"),Two("2"),Three("3"),Four
}

17.密封类

密封类的用法和枚举差不多,更像Java中的枚举用法,通过sealed关键字类修饰

sealed class MifengClass{
    class One(var name: String) : MifengClass()
    class Two(var name: String) : MifengClass()
    class Three(var name: String) : MifengClass()
}
fun main() {
    print(MifengClass.One("12").name)
}

18.数据类

数据类是对java bean的一个新的封装,我们在Java中,经常对数据解析都需要定义一个数据bean,然后在解释,在kotlin中,只需要把这个类申明为数据类,在主构造器申明变量,系统会自动为他们设置set和get方法

data class MyInfo(var name: String, var age: Int, var address: String)

我们定义一个基本的人的信息数据

使用如下:

fun main() {
    var people = MyInfo("zhangshan", 20, "jiangsu nanjing")
    print(people.info())

}

//给Myinfo新增一个方法,以上的demo已介绍过该种写法
fun MyInfo.info(): String {
    return "name={$name},age={$age},address={$address}"

}

备注:

1.数据类至少有一个参数,不存在空属性。即不存在一个对象没有属性。

2.构造器参数与类构造器不同,需要通过var或者val修饰。

3.支持copy方法,支持一模一样的数据。

17.类型转换 :as

Java中类型转换,只需要强转(TypeClass)item即可。kotlin也支持转换,需要通过as

(a asPeople):转出来就是People的对象

Android:Kotlin库Anko的使用与语法使用

Anko库:简单描述,结合语法,详细会出一篇文字

布局引入,直接使用:

1.在Android中,布局引入后,对控件的使用需要通过findViewById或者new一个对象来使用,但是kotlin提供一个anko库,可以直接把当前页中的布局注入并直接使用

kotlinx.android.synthetic.main.

import kotlinx.android.synthetic.main.layout_kotline_one.*;
格式:import kotlinx.android.synthetic.main.layoutname.*;

layoutname是当前需要引入的layout文件名,后面的*是指当前布局下所有view 的id,如果你只想引入某一个控件,把*换成对应的view 的id name即可,*代表全部注入

如果使用控件:

例如:

2.方法的简洁:

正常我们设置一个监听:

btn_one.setOnClickListener( object : View.OnClickListener{
    override fun onClick(v: View?) {
        //TODO("Not yet implemented")

    }

})

anko库,直接如下:

btn_one.setOnClickListener {
    btn_one.text="变化"
}

2.1对象字段赋值

//原生Android

 btn_one.setText("sssss")

//kotlin直接引用字段

btn_one.text="变化"

2.2监听支持返回值,在设置监听,会提供两种,一种是anko库的写法,还有一种是kotlin的对象写法

btn_one.setOnLongClickListener(object : View.OnLongClickListener {
    override fun onLongClick(v: View?): Boolean {
        //TODO("Not yet implemented")
        showToast("asd");true
    }
})

//这种写法也是延续java 的lambda表达式

toast(String msg) 或者toast(int resid)是kotlin自动支持的。

 toast显示默认有两种时间间隔,toast提供是短时间,长时间使用

longToast("123")

1.接口设置:

匿名函数

        btn_one?.setOnClickListener { v -> toast("你好")
    
        }

        btn_one?.setOnClickListener { object:View.OnClickListener{
            override fun onClick(v: View?) {
//                TODO("Not yet implemented")
            }
        } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值