代码之家  ›  专栏  ›  技术社区  ›  peter.murray.rust

爪哇和C的原始类型不同吗?

  •  14
  • peter.murray.rust  · 技术社区  · 15 年前

    我手动将代码从Java转换为C语言,并与(我所称的)原始类型进行斗争(参见,例如)。 Do autoboxing and unboxing behave differently in Java and C# )从答案中我明白 double (C)和 Double (c)等同于 双重的 (c)也可用于容器中,例如用作字典中的键。然而, 双重的 (Java)不能在像HashMap这样的容器中使用,这就是为什么它被自动装箱的原因。 双重的 (爪哇)。

    1. 双重的 (c)原语还是物体?
    2. 如果它是原始的,它的行为与 双重的 (爪哇)?

    双重的 (c)不能设置为空,除非 nullable .

    1. double? (c)相当于 双重的 (爪哇)?它们都被称为对象吗?

    (在本次讨论中,“一流对象”一词的使用是否有用?)

    3 回复  |  直到 9 年前
        1
  •  17
  •   Community CDub    8 年前

    C和Java都有原始的(或“值”)类型:int、双、浮点等等。

    然而,在这之后,C和Java趋于分裂。

    Java具有包装类类型 所有原始类型 (这是Java中的一个小的有限集),允许它们被当作对象。 double/Double , int/Integer , bool/Boolean 等等。这些包装器类型是引用类型(读:类),因此, null 是分配给此类类型表达式/变量的有效值。Java(1.5/5 +)的最新版本将原语的隐式强制添加到相应的包装器中。

    // Java
    Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
    Boolean b = null; // okay, can assign null to a reference type
    boolean n = null; // WRONG - null is not a boolean!
    

    C不提供这种直接包装 -部分原因是C支持 无限值类型集 通过 structures 相反,C通过引入 Nullable<T> 包装类型。此外,类似于Java的C语言从值类型具有隐式转换。 T 可以为空<t> ,条件是t本身是“不可为空的类型”。

    // C#
    Nullable<bool> b = true; // implicit conversion bool -> bool?
    bool? b = true;          // short type syntax, implicit conversion
    bool? b = null;          // okay, can assign null as a Nullable-type
    bool b = null;           // WRONG - null is not a bool
    

    注意 可以为空<t> 也是一个值类型,因此遵循标准结构规则,用于确定值是否“在堆栈上”。

    回应评论:

    绝对正确,可以为空的值类型允许它有更紧凑的内存占用 在某些情况下 因为它可以避免引用类型的内存开销: What is the memory footprint of a Nullable<T> .但是,它仍然需要比不可为空的类型更多的内存,因为它必须记住该值是、好是、空还是不。根据对齐问题和VM实现的不同,这可能比“完整”对象小很多,也可能不是。此外,由于C/clr中的值已被重新确定,请考虑必须执行的任何提升操作:

    // C#
    object x = null;
    x = (bool?)true;
    (x as bool?).Value // true
    

    文章 Java Tip 130: Do you know your data size? 谈论引用类型内存消耗(在Java中)。需要注意的一点是,JVM内部有专门的数组版本,每个基元类型和对象都有一个(但是,请注意,本文包含一些 误导性陈述 )注意对象(与原语相比)如何引起额外的内存开销和字节对齐问题。但是,可以将优化后的数组大小写扩展到 可以为空<t> 类型与JVM所具有的有限特殊情况,因为 可以为空<t> 本身只是一种结构类型(或“原始”)。

    然而,一个对象只需要一个小的固定大小就可以在一个可变的槽中保持对它的“引用”。类型的可变槽 Nullable<LargeStruct> 另一方面,必须有空间 LargeStruct+Nullable (插槽本身可能在堆上)。见 C# Concepts: Value vs Reference Types . 注意在上面的“提升”示例中,变量的类型 object : 对象 是C中的“根类型”(引用类型和值类型的父级)和 专用值类型。


    C语言支持一组固定的 别名 对于允许访问“友好小写”类型名称的基元/通用类型。例如, double 是的别名 System.Double int 是一个别名 System.Int32 . 除非另有规定 Double 类型是在作用域中导入的, 双重的 双重的 将引用C中的同一类型。我建议使用别名,除非有其他原因。

        2
  •  10
  •   Daniel Pryden    15 年前

    Nullable<double> (阿卡 double? 在C是 一样 Double 在Java中。

    在Java进行自动装箱/解压之前,必须手动转换原语和一流对象之间的关系:

    Double dblObj = new Double(2.0);
    double dblPrim = dblObj.doubleValue();
    

    在Java 1.5中改变了,所以你可以这样做:

    Double dblObj = 2.0;
    double dblPrim = dblObj;
    

    Java将自动插入代码来镜像上面的示例。

    C是不同的,因为“基元”类型的数量是无限的(clr调用的类型 value types )这些行为大多类似于Java的原语,使用 值语义 . 可以使用创建新的值类型 struct 关键字。C具有自动氧化/拆箱功能 全部的 值类型,并使所有值类型派生自 Object .

    因此您可以使用值类型(例如 double )使用任何对象引用的位置(例如,作为 Dictionary )如有必要,它将被装箱,否则直接使用。(C的泛型实现非常好,可以在大多数情况下避免装箱。)

        3
  •  1
  •   Daniel A. White    15 年前

    在C中,分离对象的最佳方法是“值类型”,它有点像原语。- int S bool S等和“参考类型”-类等。