Java 为什么原始类型的铸造方向是从大到小,而对象的铸造方向是从小到大?

Java 为什么原始类型的铸造方向是从大到小,而对象的铸造方向是从小到大?,java,oop,object,casting,primitive-types,Java,Oop,Object,Casting,Primitive Types,在爪哇 在将double(内存大小较大)转换为Integer(内存大小较小)时,我们需要强制转换 但在对象的情况下,如果父类是“哺乳动物”(内存大小较小),而其子类是“人类”(内存大小较大,因为得到的属性比哺乳动物多) 然后 但是从小到大的转换 Human h = (Human) m ; // needs casting 提前感谢。强制转换与对象的大小无关:它与变量的范围有关 “范围”是指变量可以包含的各种不同值。如果从一个变量赋值到另一个变量,其范围是第一个变量的超集,则不需要强制转换,因

在爪哇 在将double(内存大小较大)转换为Integer(内存大小较小)时,我们需要强制转换

但在对象的情况下,如果父类是“哺乳动物”(内存大小较小),而其子类是“人类”(内存大小较大,因为得到的属性比哺乳动物多)

然后

但是从小到大的转换

Human h = (Human) m ; // needs casting 

提前感谢。

强制转换与对象的大小无关:它与变量的范围有关

“范围”是指变量可以包含的各种不同值。如果从一个变量赋值到另一个变量,其范围是第一个变量的超集,则不需要强制转换,因为您知道赋值是可以的。但是,当您从一个变量分配到另一个变量(其范围是子集)时,确实需要强制转换,因为分配可能不可能

假设你有两个容器:一个塑料桶和一个同样大小的金属购物篮。显然,任何你能放在铁丝篮里的东西,你都可以放在浴缸里。但并不是所有能放在浴缸里的东西都能放在篮子里。你可以买一堆苹果。但是一堆葡萄干,你不能——它们会从篮子的洞里掉下来。因此,浴缸能容纳的东西的范围比篮子能容纳的东西的范围大,即使两者大小相同

在这个类比中,铸造就像检查你正在移动的东西是否适合新的容器。当你把东西从篮子里移到篮子里的时候,你不需要检查,但是当你把东西从篮子里移到篮子里的时候,你需要检查,否则你会把水果弄得满地都是


在你们的具体案例中,我们知道每个人都是哺乳动物,但不是每个哺乳动物都是人,所以哺乳动物类型变量的范围大于人类类型变量的范围。我们还知道,双精度(大约2^1024--(2^1024))的范围大于整数(2^31-1--2^31)的范围。因此,在这两种情况下,从前者分配到后者都需要强制转换,但从后者分配到前者则不需要。

当您使用基元类型时,您必须在可能丢失信息时显式强制转换。例如,
long
是64位,
int
是32位。在
int
中转换
long
会导致数据丢失(本例中为32位)

在处理对象时,这与多态性有关。编译器能够确保每个
人类
都是
哺乳动物
。没问题。但它无法确保每一种
哺乳动物
都是
人类
。要转换引用类型,必须显式强制转换

您可以将显式强制转换视为对编译器说“我知道您无法确保此数据转换是安全的,但我知道我在做什么”的一种方式

  • 在原语的情况下,内存起作用。如果您要像示例中那样将double存储到int中,则double比integer占用更多内存。因此,有可能会丢失数据。因此编译器抛出错误。如果您强制转换自己,则您知道自己在做什么,所以编译器可以这样做
  • 在对象的情况下,没有内存的情况。只有多变形开始发挥作用。所以你可以将一个子类对象转化为超类型

    希望你能得到它


  • 您真的不应该根据对象的内存大小来考虑对象,而应该根据它们所代表的内容来考虑对象。如果Java规则是基于数据丢失的,那么唯一的隐式整数到浮点转换将是
    int->double
    。我可以想出一些很好的理由来禁止有损转换,或者允许
    double->float
    ;我认为Java目前的规则在这两个方面都有相当糟糕的一面,因为类似于
    double d=1234567890-1f
    将自动将1234567890转换为不准确的1234567936.0f(产生1234567936.0的结果),而不是精确的1234567890.0(产生算术正确的1234567889.0)。
    Mammal m = new Human(); //works without casting
    
    Human h = (Human) m ; // needs casting