A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 1763982023 初级黑马   /  2017-10-26 23:07  /  2040 人查看  /  1 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 1763982023 于 2017-12-15 22:19 编辑

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

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


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


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

  1. fun main(args: Array<String>) {
  2.     var a:String
  3.     var b=""
  4. }
复制代码


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

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


  1. var a="d"
  2. a="ben"
复制代码



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


  1. var a:String=""
  2. get() {
  3.     field="123"
  4.     return field
  5. }
  6. set(value) {value+"123"}
复制代码



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


  1.     val a=1000
  2.     val b=a
  3.     print(a)
复制代码



字解码:

  1. L1
  2.     LINENUMBER 10 L1
  3.     SIPUSH 1000
  4.     ISTORE 1
  5.    L2
  6.     LINENUMBER 11 L2
  7.     ILOAD 1
  8.     ISTORE 2
  9.    L3
  10.     LINENUMBER 12 L3
  11.    L4
  12.     GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
  13.     ILOAD 1
  14.     INVOKEVIRTUAL java/io/PrintStream.print (I)V
  15.    L5
  16.    L6
复制代码



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


  1. private static final int a = 1000;
  2.    private static final int b = 1000;
  3.    public static final int getA() {
  4.       return a;
  5.    }
  6.    public static final int getB() {
  7.       return b;
  8.    }
复制代码



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

那么我们既然知道了,存在运行时常量,那么肯定会存在编译器常量,编译期常量,那么编译期常量又该怎么编写呢?
其实是这样,也很简单,加个 const就行:
   kotlin:

  1. const val a=1000
  2. fun main(args: Array<String>) {
  3.     val b=a
  4.     print(a)
  5. }
复制代码



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


  1.   L1
  2.     LINENUMBER 11 L1
  3.     SIPUSH 1000
  4.     ISTORE 1
  5.    L2
  6.     LINENUMBER 12 L2
  7.     SIPUSH 1000
  8.     ISTORE 2
复制代码


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


  1. public static final int a = 1000;
  2.    public static final void main(@NotNull String[] args) {
  3.       Intrinsics.checkParameterIsNotNull(args, "args");
  4.       int b = true;
  5.       short var2 = 1000;
  6.       System.out.print(var2);
  7.    }
复制代码



原来是这样:对吧,这个a和之前的a有什么区别呢,区别大着呢,因为他没有了get方法,也就是说它不再是一个量,而是一个数,也就是编译器已经肯定,他就是薛之谦是吧,当然不是,是常量,这也就是编译期常量.
不知不觉,已经这么久了,关于val和var 的故事就结束了?
当然是不存在的,val和var的用法区别也很大,像val 可以用属性代理,最典型的就是 by lazy{},var可以添加lateinit 让自己延迟操作等等,当然在这没时间讲了.
那么,我们再来说一个很常见的操作--我们在java中属性只有基本类型和引用类型(区分可以根据,存储方式和作用机理),那么有没有这么玩过


  1. fun main(args: Array<String>) {
  2.    
  3.     val a={i:Int,j:Int->i+j} //lambda 表达式
  4.     val b=fun(b:Boolean){b=false} //匿名函数
  5.     val c= print("ben")  //输出语句
  6.     val d=D()//类
  7.     val e=if(bool){"str"}else{"int"}

  8.      //.......................(还有像when等等,只要觉得可行,基本就可行)
  9. }
  10. class D{}
复制代码



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


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

1 个回复

倒序浏览
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马