Android

三、Kotlin 基本数据类型与类型系统

2018-01-22  本文已影响0人  Tenderness4
  1. 类型(type)本质上就是内存中的数值或变量对象的逻辑映射,也可以说是对较低层次的逻辑单元进行高层次的逻辑抽象。

    类型系统用于定义如何将编程语言中的数值表达式归类为许多不同的类型,如何操作这些类型,这些类型如何相互作用等。提供的主要功能有安全性、最优化、可读性、抽象化。下面针对安全性解释一下

    • 安全性

        "hello"+3//is right
        3+"hello"//is error,因为没有对Int的+进行重载
      
  2. Kotlin 是一门强类型的、静态类型、支持隐式类型的显示类型语言

    • 强类型语言在转换过程中需要显示调用
    • 静态类型检查是基于编译器来分析源码本身,能让很多bug在编码早期就被捕捉到,并优化运行
  3. 根类型Any

    和Java中的Object一样,区别是Object不包括基本类型:byte int long等,但是Kotlin直接统一,所有类型都是引用类型,统一继承父类Any

  4. 基本类型

    • 数字类型
      • 十进制:123

      • Long类型用大写L标记:123L

      • 十六进制:0x0F

      • 二进制:0b00001011

      • 不支持八进制

      • Kotlin对于数字没有隐式拓宽转换(例如Int不能隐式转成Long类型)

      • 显示转换

          val a:Int? = 1
          val b:Long? = a//error 不能隐式转换
          val b:Long? = a.toLong()//true
        
      • 每个数字类型都继承Number抽象类,定义了如下这些转换函数

          toDouble():Double
          toFloat():Float
          toLong():Long
          toInt():Int
          toChar():Char
          toShort():Short
          toByte():Byte
        
      • 运算符+重载

        缺乏隐式类型转换并不显著,因为类型会从上下文推断出来,而算术运算会有重载做适当转换,例如:
        
        ``` kotlin
        val l = 1L + 3 // Long + Int => Long
        ```
        
        这个是通过运算符`+`重载实现的。我们可以在Long类的源代码中看到这个`plus` 运算符函数的定义:
        
        ```
            public operator fun plus(other: Byte): Long
            public operator fun plus(other: Short): Long
            public operator fun plus(other: Int): Long
            public operator fun plus(other: Long): Long
            public operator fun plus(other: Float): Float
            public operator fun plus(other: Double): Double
        ```
        也就是说, 编译器会把`1L + 3` 翻译成 `1L.plus(3)`,然后这个传入的参数类型必须是Byte、Short、Int、Long、Float、Double中的一种。例如,我们传入一个字符`Char`参数,编译器就会直接抛错
        缺乏隐式类型转换并不显著,因为类型会从上下文推断出来,而算术运算会有重载做适当转换,例如:
        
        ``` kotlin
        val l = 1L + 3 // Long + Int => Long
        ```
        
        这个是通过运算符`+`重载实现的。我们可以在Long类的源代码中看到这个`plus` 运算符函数的定义:
        
        ```
            public operator fun plus(other: Byte): Long
            public operator fun plus(other: Short): Long
            public operator fun plus(other: Int): Long
            public operator fun plus(other: Long): Long
            public operator fun plus(other: Float): Float
            public operator fun plus(other: Double): Double
        ```
        也就是说, 编译器会把`1L + 3` 翻译成 `1L.plus(3)`,然后这个传入的参数类型必须是Byte、Short、Int、Long、Float、Double中的一种。例如,我们传入一个字符`Char`参数,编译器就会直接抛错
    * 运算
        
        
        Kotlin支持数字运算的标准集,运算被定义为相应的类成员(但编译器会将函数调用优化为相应的指令)。
        
        对于位运算,没有特殊字符来表示,而只可用中缀方式调用命名函数(`infix fun`),例如:
        
        ``` kotlin
        val x = (1 shl 2) and 0x000FF000
        ```
        
        这是完整的位运算列表(只用于 `Int` 和 `Long`):
        
        * `shl(bits)` – 有符号左移 (Java 的 `<<`)
        * `shr(bits)` – 有符号右移 (Java 的 `>>`)
        * `ushr(bits)` – 无符号右移 (Java 的 `>>>`)
        * `and(bits)` – 位与
        * `or(bits)` – 位或
        * `xor(bits)` – 位异或
        * `inv()` – 位非
        
        Kotlin支持数字运算的标准集,运算被定义为相应的类成员(但编译器会将函数调用优化为相应的指令)。
        
        对于位运算,没有特殊字符来表示,而只可用中缀方式调用命名函数(`infix fun`),例如:
        
        ``` kotlin
        val x = (1 shl 2) and 0x000FF000
        ```
        
        这是完整的位运算列表(只用于 `Int` 和 `Long`):
        
        * `shl(bits)` – 有符号左移 (Java 的 `<<`)
        * `shr(bits)` – 有符号右移 (Java 的 `>>`)
        * `ushr(bits)` – 无符号右移 (Java 的 `>>>`)
        * `and(bits)` – 位与
        * `or(bits)` – 位或
        * `xor(bits)` – 位异或
        * `inv()` – 位非
        
        Kotlin支持数字运算的标准集,运算被定义为相应的类成员(但编译器会将函数调用优化为相应的指令)。
        
        对于位运算,没有特殊字符来表示,而只可用中缀方式调用命名函数(`infix fun`),例如:
        
        ``` kotlin
        val x = (1 shl 2) and 0x000FF000
        ```
        
        这是完整的位运算列表(只用于 `Int` 和 `Long`):
        
        * `shl(bits)` – 有符号左移 (Java 的 `<<`)
        * `shr(bits)` – 有符号右移 (Java 的 `>>`)
        * `ushr(bits)` – 无符号右移 (Java 的 `>>>`)
        * `and(bits)` – 位与
        * `or(bits)` – 位或
        * `xor(bits)` – 位异或
        * `inv()` – 位非
    * 字符

        字符用 `Char` 类型表示。它们不能直接当作数字,但是它重载了对Int的plus方法
            
            kotlin
                fun check(c: Char) {
                    if (c == 1) { // 错误:类型不兼容
                    // ……
                    }
                }
        public static int getLength1(String str) {
                return str.length();
        }
    
    
    我们已经习惯了在这样的Java代码中,加上这样的空判断处理:
    
    
        public static int getLength2(String str) throws Exception {
                if (null == str) {
                    throw new Exception("str is null");
                }
        
                return str.length();
        }
        
    
    而在Kotlin中,当我们同样写一个可能为`null`参数的函数时:
    

        fun getLength1(str: String): Int {
                return str.length
         }
    
    当我们传入一个`null`参数时:
    

    
        @Test fun testGetLength1() {
            val StringUtilKt = StringUtilKt()
            StringUtilKt.getLength1(null)
        }
    
    
    编译器就直接编译失败
* kotlin.Unit类型
    
    Kotlin中的`Unit`类型实现了与Java中的`void`一样的功能。不同的是,当一个函数没有返回值的时候,我们用`Unit`来表示这个特征,而不是`null`。

    大多数时候,我们并不需要显式地返回`Unit`,或者声明一个函数的返回类型为`Unit`。编译器会推断出它。

        fun unitReturn() {
            return Unit
        }
    
        fun unitReturn(): Unit {
        }
        //  上述两种写法都是一样的
*  kotlin.Nothing类型

    在Kotlin类型层次结构的最底层就是类型`Nothing

    正如它的名字Nothing所暗示的,`Nothing`是没有实例的类型

        >>> Nothing() is Any
        error: cannot access '<init>': it is private in 'Nothing'
        Nothing() is Any
        ^
注意:Unit与Nothing之间的区别:  Unit类型表达式计算结果的返回类型是Unit。Nothing类型的表达式计算结果是永远不会返回的(跟Java

中的void相同)。

    例如,throw关键字中断的表达式的计算,并抛出堆栈的功能。所以,一个`throw Exception` 的代码就是返回`Nothing`的表达式。代码示例:

        
        fun formatCell(value: Double): String =
            if (value.isNaN()) 
                throw IllegalArgumentException("$value is not a number")  // Nothing
            else 
                value.toString()
  1. 类型检测与类型转换
    • is

        val a:int = 1
        a is Int //true
      
    • instanceof

      str instanceof String,如果返回true,则str将拥有String类型的所有方法,相当于Java内的强制转换

    • as

      代码示例:

        >>> open class Foo
        >>> class Goo:Foo()
        >>> val foo = Foo()
        >>> val goo = Goo()
        
        
        >>> foo as Goo
        java.lang.ClassCastException: Line69$Foo cannot be cast to Line71$Goo
        
        >>> foo as? Goo
        null
        
        >>> goo as Foo
        Line71$Goo@73dce0e6
      

      我们可以看出,在Kotlin中,子类是禁止转换为父类型的。代码示例:

        >>> open class Foo
        >>> class Goo:Foo()
        >>> val foo = Foo()
        >>> val goo = Goo()
        
        
        >>> foo as Goo
        java.lang.ClassCastException: Line69$Foo cannot be cast to Line71$Goo
        
        >>> foo as? Goo
        null
        
        >>> goo as Foo
        Line71$Goo@73dce0e6
      

      我们可以看出,在Kotlin中,子类是禁止转换为父类型的。

这一节主要是写Kt的数据类型,预热,下一节再介绍集合类

上一篇下一篇

猜你喜欢

热点阅读