Java中的基本数据类型
首先我们回顾下Java中的8种基本数据类型:
int a; //整型
float b; //单精度浮点型
double c; //双精度浮点型
long d; //长整型
short e; //短整型
byte f; //字节型
char g; //字符型
boolean h; //布尔型
以及它们对应的引用数据类型封装类:
Integer aa ;
Float bb;
Double cc;
Long dd;
Short ee;
Byte ff;
Character gg;
Boolean hh;
Kotlin中的基本数据类型
然而Kotlin官网告诉我们,Kotlin中的所有的基本类型都是对象(即有对应的类来表示这些类型),比如下图Int型在Kotlin中对应类的部分截图:
imageKotlin中把基本数据类型大致分为:
数值型:
var a: Int = 0 //整形
var b: Float = 0.0f //单精度浮点型
var c: Double = 0.0 //双精度浮点型
var d: Long = 0L //长整型
var e: Short = 0 //短整型
var f: Byte = 0 //字节型
字符型:
var char: Char = 'a' //字符型
布尔型:
var bool: Boolean = true //布尔型
字符串:
var str:String = "" //字符串型
数组:
//方式1
var arrInit: (Int) -> Int = fun(i: Int): Int { return i }
var arr1: Array<Int> = Array(3, arrInit)
//方式
var arr2: Array<Int> = arrayOf(1, 2, 3)
难疑解惑
1、既然Kotlin中所有的类型都是对象,那么是不是Kotlin中没有了Java中的基本数据类型和引用数据类型之分?
-
不是的,对于Kotlin提供的基本类型来说,其在语法层面上使用?号来区分该变量是引用数据类型,还是基本数据类型。
在定义基本类型变量时,在类型的后面紧跟?号,那么它的类型对应的就是Java中的基本类型的装箱类。例如:
image其实,由于Kotlin语言也是运行在Jvm虚拟机上的,最终肯定会编译为.class字节码文件,我们通过反编译该字节码文件可以查看到对应的Java代码实现形式,比如上面的Kotlin代码反编译其字节码文件后的Java代码里就是Integer类型:
image我们也可以通过以下例子来证明:
//测试1 var a: Int = 128 var b: Int? = a var c: Int? = a println(b == c) // 双等于:比较值相等 true println(b === c) // 三等于:比较内存地址(引用)相等 false //测试2 var aa: Int? = 128 var bb: Int? = aa var cc: Int? = aa println(bb == cc) // 双等于:比较值相等 true println(bb === cc) // 三等于:比较内存地址(引用)相等 true
-
测试1结果:
-
== 比较结果true,b、c的值都相等,不难理解;
-
=== 比较结果false,不妨结合加?号的类型对应Java中的Integer封装类,那么a是基本数据类型int,b,c都是Integer引用数据类型,将a赋值给b,c会触发自动装箱操作,那么jvm会分别为b,c开辟新的内存地址,再比较b,c的引用地址时,自然为false.
-
-
测试2结果:
-
== 比较结果true,原因和测试1一样;
-
=== 比较结果true,由于aa、bb、cc都加了?号,所以它们之间的赋值操作都是引用传递,最后再比较引用地址自然相同。
-
(注:测试该问题时,请使用-128至127以外的数字,因为该整数段在JVM常量池中,不会开辟新的内存空间。)
-
2、为什么Kotlin的Char类型不能划分为数值型?Java中的char不是可以直接转换为Ascii码进行数值计算吗?
-
是的,在Kotlin中我们不能再像Java那样把字符型直接看作数值型了,官方认为字符型就是字符型,不应该与其他类型混淆。
像下面这样的Java代码在Kotlin中是会报错的:
image image那么是不是Kotlin中的Char类型就不能进行数值运算呢?不是的,Kotlin中的Char类型也能进行数值运算,只不过计算结果和Java有所不同
image image- Java中 c+1 返回的是int类型,因为int(32位)大于char(16位),所以精度由小转为大,最终为int型数据。
- Kotlin中认为Char型进行运算,其结果当然应该也是Char型。
我们不妨反编译Kotlin的字节码,看看它的Java代码是如何做的:
image好吧,原来是把计算结果又强制转换为了char类型,手动滑稽-_-!
3、难道Kotlin中就不能把Char类型转换为Ascii码进行计算吗?
-
显然不是的,要不然Kotlin怎么好意思说完全兼容Java呢。
Kotlin中为所有基本数据类型都提供了显示的互相转换函数:
toByte() Byte toShort() Short toInt() Int toLong() Long toFloat() Float toDouble() Double toChar() Char
我们可以通过toInt()函数将一个字符转换为对应的Assic码:
image
4、Kotlin中的Boolean类型与Java对比,有什么区别吗?
- 没什么太大区别,取值依旧是true和false,添加?号申明后支持null(Java的Boolean装箱类).
5、Kotlin低精度转高精度的隐式转换问题?
-
Kotlin只支持运算时隐式精度转换
什么意思呢,我们看一段Java代码:
image再看Kotlin:
image一对比,大家应该明白了,那为什么Kotlin不支持赋值时的隐式转换呢?官方举了下面这个例子:
// 这是些伪代码,不能编译的 val a: Int? =1 // 一个装箱过的 Int (java.lang.Integer) val b: Long? = a // 一个隐式装箱的 Long (java.lang.Long) print( a == b )// 很惊讶吧 这次打印出的是 'false' 这是由于 Long 类型 的 equals() 只有和 Long 比较才会相同
大致的意思是说由于Kotlin双等于的实现是通过调用equals()函数来实现的,然而无论Int类型还是Long类型,他们最终调用的还是Java的Integer类和Long类中的equals()方法,我们不妨看下Java中Integer类equals()方法的实现:
image原来不是同一种类型,直接会返回false,或许官方在这里的处理也是一种妥协,并提供显示函数形式进行转换。
6、Kotlin的String类型与Java对比又有哪些区别?
-
基本用法没变,添加了些更方便的新玩法
-
1、支持索引访问元素
var str: String = "abcdefg" println(str[1]) //打印 b
-
2、支持for循环迭代(for循环格式与Java有所不同,在流程控制篇章再探讨)
var str: String = "abcdefg" for (c in str) { println(c) }
-
3、支持段落字符串
var pStr = """line1 \tline2 line3 line4""" println(pStr)
打印:
image(注:段落字符串中不支持转义字符)
-
4、支持字符串模版
val name: String = "zhangsan" val age: Int = 3 println("My name is $name , age is ${age * 10}")
再也不用像Java那样的使用+号来拼接字符串了,使用【$变量】或者【${表达式}】的形式可以轻松的拼接字符串,并且更易于阅读。
-
7、怎么感觉Kotlin定义一个数组更麻烦了呢?
-
是的,如果你已经习惯了Java的数组表示形式,那么Kotlin的数组的确会让你有所不舒服,这跟Kotlin的设计理念相关,官方认为Kotlin中的所有类型都应该是对象,所以也就为数组内建Array这个类来表示。
-
第一种数组创建方式:
var arrInit: (Int) -> Int = fun(i: Int): Int { return i } var arr1: Array<Int> = Array(3, arrInit)
可以看到创建一个数组需要2个参数,第一个参数为数组大小,第二个参数为用于初始化数组的函数,下图是Array类的构造函数:
image(注:Kotlin中函数是可以当参数的,并且也可以赋值给对应的变量,我们的第一行代码就是这样做的,详细关于函数的问题会在之后的函数篇章探讨,先了解该特性就好)
通过这种方式我们会得到数组:[0,1,2]
其实大家可以猜到,在创建Array对象时,其内部通过遍历次数调用我们提供的初始化函数将元素都为我们填充了进去。虽然Kotlin的Array类中构造函数并没有明确提供这段代码,但是我们通过反编译,代码一览无遗。以下是反编译后的代码:
image如果在座的各位对lambda比较熟悉,那么第一种方式就可以简化很多,不了解也没关系,之后的篇章会专门讲解lambda表达式:
//lambda表达式形式创建数组 var lambdaArr: Array<Int> = Array(3, { i -> i })
-
第二种数组创建方式:
var arr2: Array<Int> = arrayOf(1, 2, 3)
Kotlin官方也考虑到,开发者可能就是想要一个简单的数组,不想搞初始化函数什么乱七八糟的东西,所以为开发者内建了arrayOf()函数来快捷创建一些简单的数组。
除了arrayOf()函数外还提供以下内建函数用来快速创建对应的基本类型数组:
intArrayOf() longArrayOf() shortArrayOf() floatArrayOf() doubleArrayOf() byteArrayOf() booleanArrayOf() charArrayOf()
-
到此,Kotlin提供的基本数据类型总结完毕,如果有遗漏或错误的地方,欢迎评论。
网友评论