Dart 为什么可以';我不能把一个数字转换成双精度的吗?
Dart 为什么可以';我不能把一个数字转换成双精度的吗?,dart,google-cloud-firestore,flutter,Dart,Google Cloud Firestore,Flutter,weight是一个字段(中的数字),设置为100 int weight = json['weight']; double weight = json['weight']; int-weight工作正常,按预期返回100,但double-weight崩溃(Object.noSuchMethod异常),而不是返回100.0,这是我预期的 然而,以下工作: num weight = json['weight']; num.toDouble(); 当从Firestore解析100时(Firestor
weight
是一个字段(中的数字),设置为100
int weight = json['weight'];
double weight = json['weight'];
int-weight
工作正常,按预期返回100
,但double-weight
崩溃(Object.noSuchMethod
异常),而不是返回100.0
,这是我预期的
然而,以下工作:
num weight = json['weight'];
num.toDouble();
当从Firestore解析
100
时(Firestore实际上不支持“数字类型”,但是),按照标准,它将被解析为int
Dart不会自动“巧妙地”投射这些类型。事实上,您不能将
int
转换为double
,这是您面临的问题。如果可能的话,您的代码就可以正常工作
解析
相反,您可以自己解析它:
double weight = json['weight'].toDouble();
铸造
同样有效的是,将JSON解析为num
,然后将其分配给double
,这将num
转换为double
double weight = json['weight'] as num;
起初这似乎有点奇怪,事实上(例如,内置于VS代码和IntelliJ的Dart插件中)会将其标记为“不必要的强制转换”,而事实并非如此
double a = 100; // this will not compile
double b = 100 as num; // this will compile, but is still marked as an "unnecessary cast"
double b=100 as num
编译,因为即使没有显式强制转换,Dart也会将超级强制转换为子类型。显式演员阵容将如下所示:
double a = 100 as double; // does not compile because int is not the super class of double
double b = (100 as num) as double; // compiles, you can also omit the double cast
关于“省道中的类型和铸造”
解释
发生在你身上的事情如下:
double weight;
weight = 100; // cannot compile because 100 is considered an int
// is the same as
weight = 100 as double; // which cannot work as I explained above
// Dart adds those casts automatically
在Dart中,
int
和double
是独立的类型,都是num
的子类型
数字类型之间没有自动转换。如果你写:
num n = 100;
double d = n;
您将得到一个运行时错误。Dart的静态类型系统允许不安全的向下转换,因此n
到d
的不安全分配(不安全,因为并非所有num
值都是double
值)被隐式视为:
num n = 100;
double d = n as double;
as double
检查该值是否实际为double
(或null
),如果不是,则抛出。如果该检查成功,则可以安全地将该值分配给d
,因为已知该值与变量的类型匹配
这就是这里发生的事情。json['weight']
(可能是静态类型的对象
或动态对象
)的实际值是值为100的int
对象。将其分配给int
有效。将其分配给num
有效。将其分配给double
将抛出
Dart JSON解析器将没有小数或指数部分的数字解析为整数(0.0
是双精度,0e0
是双精度,0
是整数)。这在大多数情况下都非常方便,但在像您这样需要double
但创建JSON的代码没有将其作为double编写的情况下,有时会让人恼火
在这种情况下,提取值时只需在值上写入.toDouble()
。这对真正的双打来说是不可能的
另外,编译为JavaScript的Dart将所有数字表示为JavaScript数字类型,这意味着所有数字都是双倍的。在JS编译的代码中,所有整数都可以赋值为double而无需转换。如果代码运行在非JS实现上(如Flatter、Dart VM/server或iOS的提前编译),则这将不起作用,因此不要依赖它,否则您的代码将无法移植。您可以解析如下所示的数据: 这里的文档是一张
地图
只需像这样将
int
转换为double
int a = 10;
double b = a + 0.0;
您可以在一行中完成:
double weight = (json['weight'] as num).toDouble();
double-weight=json['weight'].toDouble()
?您可以这样做:double-weight=json['weight']+0.0代码>这是飞镖,而不是飞镖本身。Dart对打字要求非常严格。最终,它使代码更清晰。但需要一点时间来适应它——Dart不仅仅是为您神奇地转换变量。这基本上是错误的。Dart从不将整数值转换为双精度,您必须调用.toDouble()
。对一个数字进行转换不会改变其类型。如果运行double x=42作为num在VM上,您将得到一个运行时错误,因为整数不是双精度的。它在编译为JavaScript时可以工作,但这只是因为JavaScript中的所有数字实例都是双倍的,即使是int
@lrn的实例也可以工作。我在发帖前测试了一下。。你也可以查看我链接的内容。我可能误读了你写的内容,如果是,我道歉。我对您所说的工作原理感到非常困惑(当在VM上运行时,.toDouble()
工作,其他一切都不工作,但从文本中看不清楚,这些示例不应该工作)。“解析”部分实际上是从int转换为double,“转换”部分所做的事情在运行时都失败了。所以,也许我只是说消息不清楚。不确定您指的是哪个链接,但我对Dart类型的系统和运行时行为非常熟悉。我是从Dart 2静态和运行时类型系统的角度讲的,但我在这里所说的也适用于--checked
more中的Dart 1(它检查类型,而不是忽略它们并允许任何操作)。您不会得到运行时错误。我不知道你是从哪里弄来的。也许曾经是这样,但是你可以在虚拟机上试试。没有编译或运行时错误。仅尝试:main(){num n=100;double d=n;}
在Dart 2虚拟机上运行会产生未处理的异常:类型“int”不是类型“double”的子类型
。将添加为double
没有任何区别。分配过去在未经检查的Dart 1代码中工作,但如果在运行Dart 1时使用--checked
,它将以完全相同的方式失败。An double weight = (json['weight'] as num).toDouble();