本帖最后由 1763982023 于 2017-12-15 22:19 编辑
前言
这么多天了,一直没有时间来更新内容了,因为为在应用kotlin的时候,遇到了诸多的坑,并且解决的也是很艰难,但是学习都是痛并快乐着,这段时间,又把kotlin学习了一遍,真是那句话,不到用处,不知学了干嘛!!所以安上次所讲的说的,希望把基础部分重新巩固一下,所以现在就来聊聊基础.当然比以前的我那糟糠似得理解稍微好了点,如果对kotlin的方面感兴趣的道友,可以一起看看,讨论,本人能力有限,错误请即时指正.蟹蟹.
今天说的内容不多,因为节约时间,大家学习时间都很宝贵,说一说官网视屏里说到的val和var吧(具体说过啥我也不记得了)
Val和Var
先来个概括,val和var最大的区别是什么,val表示对象是常量,var表示对象是变量.
1.var变量定义:
变量是指可以改变的量,在kotlin里面你可以指明属性的数据类型,也可以不指明属性的数据类型,因为kotlin可以很智能的帮你区别这个属性的值,然后默认属性的类型比如说这样
- fun main(args: Array<String>) {
- var a:String
- var b=""
- }
复制代码
那么a是String类型,b也是String类型,但是b没标明,系统已经自己进行标识
那么我们在转回,话题,var代表所申明的对象是可赋值的,也就是说:可变
也就是说我可以改变var对象的值,如同这样
其实在定义了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
- LINENUMBER 10 L1
- SIPUSH 1000
- ISTORE 1
- L2
- LINENUMBER 11 L2
- ILOAD 1
- ISTORE 2
- L3
- LINENUMBER 12 L3
- L4
- GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
- ILOAD 1
- INVOKEVIRTUAL java/io/PrintStream.print (I)V
- L5
- L6
复制代码
可以看出val a在赋值给b的时候它还是a,并没有用常量来代替它,所以它是在编译期,系统还不知道这个a到底是个什么东西,那么在java中,它又是怎么表达的呢,那么我们把代码反编译一下:
得到的java代码:
- private static final int a = 1000;
- private static final int b = 1000;
- public static final int getA() {
- return a;
- }
- public static final int getB() {
- return b;
- }
复制代码
我们先不看下面的get方法,我们发现上面两行代码我们很熟悉是不是(当然这要考虑val是不是在main方法里里面了),这就是我们熟悉的定义方法的方式,而下面的get方法也表示你可以获取他们的值.
那么我们既然知道了,存在运行时常量,那么肯定会存在编译器常量,编译期常量,那么编译期常量又该怎么编写呢?
其实是这样,也很简单,加个 const就行:
kotlin:
- const val a=1000
- fun main(args: Array<String>) {
- val b=a
- print(a)
- }
复制代码
字解码:我们依旧通过字解码的方式来了解一下什么是编译期常量
- L1
- LINENUMBER 11 L1
- SIPUSH 1000
- ISTORE 1
- L2
- LINENUMBER 12 L2
- SIPUSH 1000
- ISTORE 2
复制代码
通过找到对应的字解码,我们惊讶的发现了一个惊天大秘密,原来的 a在字解码里面已经变成了1000,哇,原来是这样,编译器已经认识了这个属性了,并给了它一个固定的身份证,那么我们反编译成java代码看一下
java:
- public static final int a = 1000;
- public static final void main(@NotNull String[] args) {
- Intrinsics.checkParameterIsNotNull(args, "args");
- int b = true;
- short var2 = 1000;
- System.out.print(var2);
- }
复制代码
原来是这样:对吧,这个a和之前的a有什么区别呢,区别大着呢,因为他没有了get方法,也就是说它不再是一个量,而是一个数,也就是编译器已经肯定,他就是薛之谦是吧,当然不是,是常量,这也就是编译期常量.
不知不觉,已经这么久了,关于val和var 的故事就结束了?
当然是不存在的,val和var的用法区别也很大,像val 可以用属性代理,最典型的就是 by lazy{},var可以添加lateinit 让自己延迟操作等等,当然在这没时间讲了.
那么,我们再来说一个很常见的操作--我们在java中属性只有基本类型和引用类型(区分可以根据,存储方式和作用机理),那么有没有这么玩过
- fun main(args: Array<String>) {
-
- val a={i:Int,j:Int->i+j} //lambda 表达式
- val b=fun(b:Boolean){b=false} //匿名函数
- val c= print("ben") //输出语句
- val d=D()//类
- val e=if(bool){"str"}else{"int"}
- //.......................(还有像when等等,只要觉得可行,基本就可行)
- }
- class D{}
复制代码
哇,可以把属性定义为一个lambda表达式,一个匿名函数(当然函数也是可以的),一个类,甚至一个输出语句,这个世界怎么了,要疯了?不你没有事,这个世界也很好,只是kotlin有点漂移
过早的结束符
按照这速度估计发到毕业也发不到kotlin最精彩的协程(coroutine)和特殊语言领域(DSL),只能说我看看,能不能发吧,总结之前发的"乱糟糟"一堆,觉得还是要讲的细点比较好,这样也有利于大家交流,我这段时间也澄净了心.知道自己该学点什么,该怎么规划自己,所以乘着休息片刻,和大家分享了一下之前学过的东西,但是时间久了,可能有些错误的地方,也请包含,总之一句话,兴趣是一门学问,当你在其中痛苦不堪指之时,也许这时候是是你回忆中的快乐,所以快乐建立在"痛苦"之上,蟹蟹晚安 |
|