Kotlin开发指南Kotlin官方文档Kotlin专题

kotlin中val和var不为人知的故事

2017-10-28  本文已影响252人  不灭汤包

前言

这么多天了,一直没有时间来更新内容了,因为为在应用kotlin的时候,遇到了诸多的坑,并且解决的也是很艰难,但是学习都是痛并快乐着,这段时间,又把kotlin学习了一遍,真是那句话,不到用处,不知学了干嘛!!所以希望把基础部分重新巩固一下,所以现在就来聊聊基础.当然比以前的我那糟糠似得理解稍微好了点,如果对kotlin的方面感兴趣的道友,可以一起看看,讨论,本人能力有限,错误请即时指正.蟹蟹.

今天说的内容不多,因为节约时间,大家学习时间都很宝贵,说一下网上视屏里说过的吧(具体说过啥我也不记得了)

Val和Var

先来个概括,val和var最大的区别是什么,val表示对象是常量,var表示对象是变量.

1.var变量定义:

变量是指可以改变的量,在kotlin里面你可以指明属性的数据类型,也可以不指明属性的数据类型,因为kotlin可以很智能的帮你区别这个属性的值,然后默认属性的类型比如说这样


fun main(args:Array){

var a:String

var b=""

}

那么a是String类型,b也是String类型,但是b没标明,系统已经自己进行标识

那么我们在转回,话题,var代表所申明的对象是可赋值的,也就是说:可变

也就是说我可以改变var对象的值,如同这样

var a="d"

a="ben"

其实在定义了var之后kotlin自己就给我们定义好了get()和set()方法了,所以就省去了很多很多java的坑长饿的代码,当然他默认是不显示的,但是我们可以自己定义啊!!!但是要注意使用的位置

var a:String=""

get(){

field="123"

return  field

}

set(value){value+"123"}

2.说清楚var,再来说说val,val很好理解了,它代表常量的定义,但是真的就这么简单?当然不是,就像你,一直用java里面的常量,却不知道为什么要有常量,你有没有想过,其实变量的功能完全能取代常量,你看你可以在你的程序中全部用变量,那为什么要用到常量的呢,其实说的再多都是为了节省内存,或则节省消耗,其实val 的全名叫做 运行时常量,也就是说在你运行的时候,这这属性就代表着常量,这一点我们可以通过解析.class 字节码的方式来获悉

kotlin:

val a=1000

val b=a

print(a)

字解码:

L1

LINENUMBER10L1

SIPUSH1000

ISTORE1

L2

LINENUMBER11L2

ILOAD1

ISTORE2

L3

LINENUMBER12L3

L4

GETSTATIC java/lang/System.out:Ljava/io/PrintStream;

ILOAD1

INVOKEVIRTUAL java/io/PrintStream.print(I)V

L5

L6

可以看出val a在赋值给b的时候它还是a,并没有用常量来代替它,所以它是在编译期,系统还不知道这个a到底是个什么东西,那么在java中,它又是怎么表达的呢,那么我们把代码反编译一下:

得到的java代码:

privatestaticfinalinta=1000;

privatestaticfinalintb=1000;

publicstaticfinalintgetA(){

returna;

}

publicstaticfinalintgetB(){

returnb;

}

我们先不看下面的get方法,我们发现上面两行代码我们很熟悉是不是(当然这要考虑val是不是在main方法里里面了),这就是我们熟悉的定义方法的方式,而下面的get方法也表示你可以获取他们的值.

那么我们既然知道了,存在运行时常量,那么肯定会存在编译器常量,编译期常量,那么编译期常量又该怎么编写呢?

其实是这样,也很简单,加个 const就行:

kotlin:

const  val a=1000

fun main(args:Array){

val b=a

print(a)

}

字解码:我们依旧通过字解码的方式来了解一下什么是编译期常量

L1

LINENUMBER11L1

SIPUSH1000

ISTORE1

L2

LINENUMBER12L2

SIPUSH1000

ISTORE2

通过找到对应的字解码,我们惊讶的发现了一个惊天大秘密,原来的 a在字解码里面已经变成了1000,哇,原来是这样,编译器已经认识了这个属性了,并给了它一个固定的身份证,那么我们反编译成java代码看一下

java:

publicstaticfinalinta=1000;

publicstaticfinalvoidmain(@NotNullString[]args){

Intrinsics.checkParameterIsNotNull(args,"args");

intb=true;

shortvar2=1000;

System.out.print(var2);

}

原来是这样:对吧,这个a和之前的a有什么区别呢,区别大着呢,因为他没有了get方法,也就是说它不再是一个量,而是一个数,也就是编译器已经肯定,他就是薛之谦是吧,当然不是,是常量,这也就是编译期常量.

不知不觉,已经这么久了,关于val和var 的故事就结束了?

当然是不存在的,val和var的用法区别也很大,像val 可以用属性代理,最典型的就是 by lazy{},var可以添加lateinit 让自己延迟操作等等,当然在这没时间讲了.

那么,我们再来说一个很常见的操作,就是kotlin的智能类型(val var 都行)

那么什么是智能呢,我们在java中属性只有基本类型和应用类型(区分可以根据,存储方式和作用机理),那么有没有这么玩过

fun main(args:Array){

val a={i:Int,j:Int->i+j}//lambda 表达式

val b=fun(b:Boolean){b=false}//匿名函数

val c=print("ben")//输出语句

val d=D()

//........像var e=if(bool){ "s"}else{"b"}等等

}

classD{}

哇,可以把属性定义为一个lambda表达式,一个匿名函数(当然函数也是可以的),一个类,甚至一个输出语句,这个世界怎么了,要疯了?不你没有事,这个世界也很好,只是kotlin有点漂移

过早的结束符

按照这速度估计发到大学毕业也发不到kotlin最精彩的协程(coroutine)和特殊语言领域(DSL),只能尽力而为,而估计kotlin的项目就没有机会和大家分享了,总结之前发的糟粕,觉得还是要细点比较好,这样也有利于大家交流,我这段时间也澄净了心.知道自己该学点什么,该怎么规划自己,所以乘着放假休息片刻,和大家分享了一下之前学过的东西,但是时间久了,可能有些错误的地方,也请包含,总之一句话,兴趣是一门学问,当你在其中痛苦不堪指之时,也许这时候是是你回忆中的快乐,所以快乐建立在"痛苦"之上,蟹蟹

上一篇下一篇

猜你喜欢

热点阅读