kotlin中val和var不为人知的故事
前言
这么多天了,一直没有时间来更新内容了,因为为在应用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的项目就没有机会和大家分享了,总结之前发的糟粕,觉得还是要细点比较好,这样也有利于大家交流,我这段时间也澄净了心.知道自己该学点什么,该怎么规划自己,所以乘着放假休息片刻,和大家分享了一下之前学过的东西,但是时间久了,可能有些错误的地方,也请包含,总之一句话,兴趣是一门学问,当你在其中痛苦不堪指之时,也许这时候是是你回忆中的快乐,所以快乐建立在"痛苦"之上,蟹蟹