data-type.md 14.2 KB
Newer Older
D
DCloud_LXH 已提交
1 2 3 4
## 数据类型@data-type

### 布尔值(Boolean)

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
5
布尔是简单的基础类型,只有2个值分别是:`true``false`。在全平台没有差异。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
6 7 8 9 10

```ts
let a:boolean = true
let b = false
```
D
DCloud_LXH 已提交
11 12 13

### 数字(Number)

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
14
在web中,数字不区分整型和浮点。但在kotlin和swift中,数字需要是一个确定类型,比如Int、Float、Double,没有泛数字。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
15

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
16
UTS 在iOS和Android平台上新增了 number 类型,拉齐了web端的实现,方便开发者写全端兼容代码。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
17

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
18
number是一个泛数字类型,包括整数或浮点数,包括正数负数。例如: 正整数 `42` 或者 浮点数 `3.14159` 或者 负数 `-1`
D
DCloud_LXH 已提交
19 20

```ts
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
21
// 以下都是number类型
D
DCloud_LXH 已提交
22
let a:number = 42
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
23 24 25
let b:number = 3.14159
let c = 42
let d = 3.14159
D
DCloud_LXH 已提交
26 27
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
28
注意:UTS中 number 是默认数字类型,书写的字面量如果没有特别指定类型会自动识别为 number。
杜庆泉's avatar
杜庆泉 已提交
29

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
30
除了 number,UTS 在Android和iOS设备上,也可以使用kotlin和swift的专用数字类型:
杜庆泉's avatar
杜庆泉 已提交
31

D
DCloud_LXH 已提交
32 33
#### Kotlin 特有的数字类型 @Kotlin

杜庆泉's avatar
杜庆泉 已提交
34 35 36 37
kotlin 本身支持下列数据类型 

|类型名称|长度  |最小值       |最大值          |描述|
|:--     |:---  |:---         |:---           |:-- |
杜庆泉's avatar
杜庆泉 已提交
38 39 40 41 42 43 44 45
|Byte    |8bit  |-128         |127            |整型|
|UByte   |8bit  |0            |255            |整型|
|Short   |16bit |-32768       |32767          |整型|
|UShort  |16bit |0            |65535          |整型|
|Int     |32bit |-2147483648  |2147483647     |整型|
|UInt    |32bit |0            |4294967295     |整型|
|Long    |64bit |-9223372036854775808 |9223372036854775807     |整型|
|ULong   |64bit |0            |9223372036854775807 * 2 + 1     |整型|
杜庆泉's avatar
杜庆泉 已提交
46 47
|Float   |32bit |1.4E-45F     |3.4028235E38F                   |[浮点型](https://kotlinlang.org/docs/numbers.html#floating-point-types)|
|Double  |64bit |4.9E-324     | 1.7976931348623157E308         |[浮点型](https://kotlinlang.org/docs/numbers.html#floating-point-types)|
杜庆泉's avatar
杜庆泉 已提交
48 49


杜庆泉's avatar
杜庆泉 已提交
50
**kotlin平台数字类型使用实践**
杜庆泉's avatar
杜庆泉 已提交
51

杜庆泉's avatar
杜庆泉 已提交
52
1. 在kotlin平台 `Number`是一个抽象类,编译时会自动选择合适的数据类型来填充,因此大多数场景下,开发者都应该使用 字面量(即Number类型),可以降低心智负担
杜庆泉's avatar
杜庆泉 已提交
53
2. 基本数据类型会有jvm编译魔法加持,在涉及大量科学运算的情况下,计算速度和内存占用会有优化。kotlin 会把  Int / Double 等来非空类型编译为 基本数据类型,Int? / Double? 等可为空的类型编译为 Integer等包装类型,享受不到编译优化加持  [详情](https://kotlinlang.org/docs/numbers.html#numbers-representation-on-the-jvm) 如果涉及大量运算,建议开发者不要使用 Number、Int? ,要明确使用 Int等类型
杜庆泉's avatar
杜庆泉 已提交
54

杜庆泉's avatar
杜庆泉 已提交
55
3. 在 kotlin 和 swift 中,有些系统API或三方SDK的入参或返回值的类型,强制约定了平台特有数字类型,此时无法使用number,需要使用下面列出方法进行转换
杜庆泉's avatar
杜庆泉 已提交
56

D
DCloud_LXH 已提交
57

杜庆泉's avatar
杜庆泉 已提交
58 59
所有的Number 都支持下列方法进行转换

杜庆泉's avatar
杜庆泉 已提交
60

杜庆泉's avatar
杜庆泉 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74
```
toByte(): Byte

toShort(): Short

toInt(): Int

toLong(): Long

toFloat(): Float

toDouble(): Double
```

杜庆泉's avatar
杜庆泉 已提交
75 76 77 78
部分类库API是使用java编写,要求的java类型与上述kotlin类型 完全一致,可以直接使用



D
DCloud_LXH 已提交
79 80 81 82 83 84
#### Swift 特有的数字类型 @Swift

- Int, UInt, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64
- Float, Float16, Float32, Float64
- Double

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
85 86 87
**特有数字类型的使用场景**

大多数场景下,开发者使用 字面量(即Number类型)就可以满足需要,但是也有需要特有数字类型的场景。
D
DCloud_LXH 已提交
88

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
89 90
1. 在 kotlin 和 swift 中,有些系统API或三方SDK的入参或返回值的类型,强制约定了平台特有数字类型,此时无法使用number。
2. number 作为泛数字,性能还是弱于Int。在普通计算中无法体现出差异,但在千万次运算后,累计会产生毫秒级速度差异。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
91 92 93 94

当需要特有数字类型时,UTS中可以直接定义<!--,也可以通过number类型转换为特有数字类型。-->

可以使用下面的方法,虽然可能会被编辑器报语法错误(后续HBuilderX会修复这类误报),但编译到 kotlin 和 swift 时是可用的。
D
DCloud_LXH 已提交
95 96

- 声明特定的平台数字类型
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
97
 > 目前这些特有数字类型,声明类型时,与 number 不同的是,均为首字母大写
D
DCloud_LXH 已提交
98 99 100 101 102 103 104 105

```ts

let a:Int = 3 //注意 Int 是首字母大写
let b:Int = 4
let c:Double  = a * 1.0 / b
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
106 107
* 注意这些特有数字类型不能在web端和小程序端使用,如工程需兼容非App端,要把这些代码放入条件编译中;
* iOS和Android都有的类型,比如Int,编译后可跨2个平台;但如果使用了某平台专有的数字类型,比如swift的Int8,则此代码不能编译到Android,工程如需支持Android,则把这些代码写在条件编译中。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
108

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
109
这些特有类型定义后,可以使用kotlin和swift为其提供的各种方法,具体参考kotlin和swift的文档。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
110

D
DCloud_LXH 已提交
111 112 113 114 115 116 117 118 119
- 在 kotlin(app-android) 下转换特定的平台数字类型
```ts
let a:Int = 3
a.toFloat() // 转换为 Float 类型,后续也将支持 new Float(a) 方式转换
a.toDouble() // 转换为 Double 类型,后续也将支持 new Double(a) 方式转换
```

- 在 swift(app-ios) 下转换特定的平台数字类型
```ts
lizhongyi_'s avatar
lizhongyi_ 已提交
120 121 122 123 124 125 126
// number转成特定类型
let num = 2
num.toInt() //将number 变量 num 转换为 Int 类型
num.toFloat() //将number 变量 num 转换为 float 类型
num.toInt64() // 将number 变量 num 转换为 Int64 类型

// 特定类型转成其他的特定类型
D
DCloud_LXH 已提交
127 128 129
let a:Int = 3
let b = new Double(a) // 将整型变量 a 转换为 Double 类型
```
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
130 131 132 133

<!-- #### number和特有数字类型互转 -->

#### 边界情况说明:
D
DCloud_LXH 已提交
134 135 136 137 138 139

- 在不同平台上,数值的范围限制不同,超出限制会导致相应的错误或异常
  * 编译至 JavaScript 平台时,最大值为 1.7976931348623157e+308,最小值为 -1.7976931348623157e+308,超出限制会返回 `Infinity``-Infinity`
  * 编译至 Kotlin 平台时,最大值为 9223372036854775807,最小值为 -9223372036854775808,超出限制会报错:`The value is out of range‌`
  * 编译至 Swift 平台时,最大值 9223372036854775807,最小值 -9223372036854775808,超出限制会报错:`integer literal overflows when stored into Int`

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
140 141 142
#### 更多API
number内置对象还有一些API,[详见](buildin-object-api/number.md)

D
DCloud_LXH 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155
### 字符串(String) @String

字符串是一串表示文本值的字符序列,例如:`"hello world"`

边界情况说明:

- 在不同平台上,字符串的长度限制不同,超出限制会导致相应的错误或异常
  * 编译至 JavaScript 平台时,最大长度取决于 JavaScript 引擎,例如在 V8 中,最大长度为 2^30 - 25,超出限制会报错:`Invalid string length`;在 JSCore 中,最大长度为 2^31 - 1,超出限制会报错:`Out of memory __ERROR`
  * 编译至 Kotlin 平台时,最大长度受系统内存的限制,超出限制会报错:`java.lang.OutOfMemoryError: char[] of length xxx would overflow`
  * 编译至 Swift 平台时,最大长度也受系统内存的限制,超出限制目前没有返回信息。

### 日期(Date)@date

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
156
日期对象表示日期,包括年月日时分秒等各种日期。[详见](buildin-object-api/date.md)
D
DCloud_LXH 已提交
157 158 159 160 161 162

### null

一个表明 null 值的特殊关键字。

有时需定义可为null的字符串,可以在类型描述中使用`|`操作符。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
163

D
DCloud_LXH 已提交
164 165 166 167
```ts
let user: string | null
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
168 169 170 171 172 173
> 注意:uts 编译为kotlin和swift时不支持 undefined。每个有类型的变量都需要初始化或赋值。

### 数组(Array)

Array,即数组,支持在单个变量名下存储多个元素,并具有执行常见数组操作的成员。

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
174
js和swift的array,是可变长的泛型array。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
175

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
176
而在kotlin中,其自带的array是不可变长的,length是固定的。只有arrayList是可变长的。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
177

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
178
为了拉齐实现,UTS补充了新的Array,替代kotlin的array。它继承自kotlin的ArrayList,所以可以变长。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
179

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
180
如果开发者需要使用原始的kotlin的不可变长的array,需使用 kotlin.array。
杜庆泉's avatar
杜庆泉 已提交
181

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
182 183 184
需要使用 kotlin.array 的场景和特有数字类型一样:
1. 某些系统API或三方原生SDK的入参或返回值强制指定了kotlin的array。
2. uts新增的可动态变长的array,在性能上不如固定length、不可变长的原始kotlin.array。但也只有在巨大量的运算中才能体现出毫秒级的差异。
杜庆泉's avatar
杜庆泉 已提交
185 186 187 188 189

#### 创建一个数组对象

`UTS`中数组的创建有两种方式:

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
190
1. 字面量创建
杜庆泉's avatar
杜庆泉 已提交
191

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
192
```ts
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
193 194
let a = [1,2,3];//支持
let a = [1,'2',3];//支持
杜庆泉's avatar
杜庆泉 已提交
195 196

// 需要注意的是,字面量创建的数组,不支持出现空的缺省元素
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
197
let a = [1,,2,3];//不支持
杜庆泉's avatar
杜庆泉 已提交
198 199
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
200 201
2. 创建数组对象
```ts
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
202 203 204 205
let a = new Array(1,2,3);//支持
let a = new Array(1,'2',3);//支持
let a = Array(1,2,3);//支持
let a = Array(1,'2','3');//支持
杜庆泉's avatar
杜庆泉 已提交
206 207 208 209 210 211
```

#### 遍历数组对象

在UTS语言中,推荐使用foreach来实现数组的遍历

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
212
```ts
杜庆泉's avatar
杜庆泉 已提交
213 214 215 216 217 218
const array1: string[] = ['a', 'b', 'c'];
array1.forEach((element:string, index:number) => {
    console.log(array1[index])
});
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
219
#### 更多API
杜庆泉's avatar
杜庆泉 已提交
220

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
221
更多Array的API,[详见](https://uniapp.dcloud.net.cn/uts/buildin-object-api/array.html)
杜庆泉's avatar
杜庆泉 已提交
222

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
223
#### kotlin平台的 Array 特性
杜庆泉's avatar
杜庆泉 已提交
224

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
225
<!-- 在kotlin平台上,Array 的具体实现类为: `io.dcloud.uts.UTSArray` -->
杜庆泉's avatar
杜庆泉 已提交
226

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
227
UTS 的 Array 拉齐了各个平台 Array 的功能和定义,可以满足大多数场景需要,但是在涉及与 系统API/三方sdk 交互部分,因为 系统API/三方sdk 是基于 java/kotlin 开发,因此调用时直接使用 UTS 的 Array 会产生类型不一致的错误。
杜庆泉's avatar
杜庆泉 已提交
228

杜庆泉's avatar
杜庆泉 已提交
229
举个例子:
杜庆泉's avatar
杜庆泉 已提交
230

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
231
```ts
杜庆泉's avatar
杜庆泉 已提交
232 233 234
let packageManager = UTSAndroid.getUniActivity()!.getPackageManager();
let intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
杜庆泉's avatar
杜庆泉 已提交
235
// 查询当前设备上安装了几个launcher
杜庆泉's avatar
杜庆泉 已提交
236 237 238
let resolveInfo = packageManager.queryIntentActivities(intent,0);
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
239
上面的代码向系统查询了有多少应用可以响应 `launcher`行为 ,返回的 resolveInfo 是一个 `List<ResolveInfo>`
杜庆泉's avatar
杜庆泉 已提交
240

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
241
这种情况下,我们建议的做法是将其先转换为UTS的Array对象再进行其他处理和操作
杜庆泉's avatar
杜庆泉 已提交
242

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
243
```ts
杜庆泉's avatar
杜庆泉 已提交
244 245 246
let launcherList = UTSArray.fromNative(resolveInfo) 
console.log(clothing.length);
```
杜庆泉's avatar
杜庆泉 已提交
247 248 249 250

下面汇总了常用的转换场景和代码:

##### 1 我有一个UTSArray 需要转换为其他类型
杜庆泉's avatar
杜庆泉 已提交
251

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
252
```ts
杜庆泉's avatar
杜庆泉 已提交
253
let utsArr= ["hello","world"]
杜庆泉's avatar
杜庆泉 已提交
254 255

// UTSArray 转换 kotlin.collections.List
杜庆泉's avatar
杜庆泉 已提交
256 257
let kotlinList = utsArr.toKotlinList()

杜庆泉's avatar
杜庆泉 已提交
258 259
// UTSArray 转换 kotlin.Array
let kotlinArray = utsArr.toTypedArray()
杜庆泉's avatar
杜庆泉 已提交
260 261 262

```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
263
##### 2 我有一个原生类数组类型 需要转成成UTS的Array
杜庆泉's avatar
杜庆泉 已提交
264

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
265
```ts
杜庆泉's avatar
杜庆泉 已提交
266
// kotlin.collections.List 转换 UTSArray
杜庆泉's avatar
杜庆泉 已提交
267
let utsArr= mutableListOf("hello","world")
杜庆泉's avatar
杜庆泉 已提交
268
let kotlinList = UTSArray.fromNative(utsArr) 
杜庆泉's avatar
杜庆泉 已提交
269 270
```

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
271
```ts
杜庆泉's avatar
杜庆泉 已提交
272
// kotlin.Array 转换 UTSArray
杜庆泉's avatar
杜庆泉 已提交
273
let utsArr= arrayOf("hello","world")
杜庆泉's avatar
杜庆泉 已提交
274
let kotlinList = UTSArray.fromNative(utsArr)
杜庆泉's avatar
杜庆泉 已提交
275 276
```

杜庆泉's avatar
杜庆泉 已提交
277

D
DCloud_LXH 已提交
278 279
### Object类型 @object

DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
280
对象(object)是指内存中的可以被标识符引用的一块区域,是一种引用类型。包括Array,Date,Map,Set,JSON等。
D
DCloud_LXH 已提交
281 282 283

### any类型 @any

fxy060608's avatar
fxy060608 已提交
284
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any 类型来标记这些变量:
D
DCloud_LXH 已提交
285 286

```ts
fxy060608's avatar
fxy060608 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
```

当你只知道一部分数据的类型时,any类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据:

```ts
let list: any[] = [1, true, "free"];
list[1] = 100;
```

### null类型 @null

uts 的类型系统可以消除来自代码空引用的危险。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
302

fxy060608's avatar
fxy060608 已提交
303
许多编程语言中最常见的陷阱之一,就是访问空引用的成员会导致空引用异常。在 Java 中,这等同于 NullPointerException 或简称 NPE。
DCloud_Heavensoft's avatar
DCloud_Heavensoft 已提交
304

fxy060608's avatar
fxy060608 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
在 uts 中,类型系统能够区分一个引用可以容纳 null (可空引用)还是不能容纳(非空引用)。 例如,String 类型的常规变量不能容纳 null:

```ts
let a: string = "abc" // 默认情况下,常规初始化意味着非空
a = null // 编译错误
```

如果要允许为空,可以声明一个变量为可空字符串(写作 string | null):

```ts
let b: string | null = "abc" // 可以设置为空
b = null // ok
```

现在,如果你调用 a 的方法或者访问它的属性,它保证不会导致 NPE,这样你就可以放心地使用:

```ts
const l = a.length
```

但是如果你想访问 b 的同一个属性,那么这是不安全的,并且编译器会报告一个错误:

```ts
const l = b.length // 错误:变量“b”可能为空
```

但是,还是需要访问该属性,对吧?有几种方式可以做到。


#### 在条件中检测 null

首先,你可以显式检测 b 是否为 null:

```ts
if (b != null) {
  console.log(b.length)
}
```

编译器会跟踪所执行检测的信息,并允许你在 if 内部调用 length。

#### 安全的调用

访问可空变量的属性的第二种选择是使用安全调用操作符 ?.:

```ts
const a = "uts"
const b: string | null = null
console.log(b?.length)
console.log(a?.length) // 无需安全调用
```

如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 number | null。

安全调用在链式调用中很有用。例如,一个员工 Bob 可能会(或者不会)分配给一个部门。 可能有另外一个员工是该部门的负责人。获取 Bob 所在部门负责人(如果有的话)的名字, 写作:

```ts
bob?.department?.head?.name
```

如果任意一个属性(环节)为 null,这个链式调用就会返回 null。

#### 空值合并

空值合并运算符(??)是一个逻辑运算符,当左侧的操作数为 null 时,返回其右侧操作数,否则返回左侧操作数。

```ts
const foo = null ?? 'default string';
console.log(foo);
// Expected output: "default string"

const baz = 0 ?? 42;
console.log(baz);
// Expected output: 0
```

#### 非空断言

非空断言运算符(!)将任何值转换为非空类型。可以写 b! ,这会返回一个非空的 b 值(例如:在我们示例中的 String)或者如果 b 为 null,就会抛出一个异常。

```ts
const l = b!.length
D
DCloud_LXH 已提交
387
```