我非常了解.NET和Java中的面向对象编程。我知道Java和.NET中的所有内容都来自Object。
我的问题是关于原始类型。我知道原始类型不是从Object派生的,我也理解它们有多宽,例如一个字节是8位,一个整数是32位。我也明白拳击是对象的对象。
我的问题是:如果原始类型不是对象,它们是如何实际实现的?我对编译器理论有一点了解,但也许需要深入研究它。
在我的SCJP书中它说:“如果你排除原始类型,那么Java中的所有东西都是一个对象”。它在我的.NET书中也有同样的说法。他们没有详细说明。
我在这个问题上谈到了Java,因为我来自Java背景,Java是面向对象的(如.net)。但是,我正在寻找一个特定于.NET的答案。
答案 0 :(得分:2)
在Java中,原始类型不是从类型java.lang.Object
派生的。因此,包含基元类型的其他类(例如java.lang.Integer
基元类型的int
)可以存储在引用变量中。
CLR也知道原始类型,但它们被定义为结构。所有结构都来自System.ValueType
,而System.Object
继承自int
。 C#中的名称double
,System.Int32
等只是.NET框架中System.Double
,int
等结构类型的别名。 CLR中对这些类型有特殊处理,但与Java不同,它们是统一类型层次结构的一部分。
Java VM和CLR在这方面有很大不同。在Java中,类型java.lang.Integer
和System.Int32
是完全独立的,除了编译器知道如何在它们之间进行转换的事实。在CLR中,只有一种类型{{1}},它可以以盒装和非盒装形式出现。
答案 1 :(得分:2)
这取决于你戴的眼镜。如果你有“实现”眼镜,那么你会看到任何引用类型值都有一个对象头。这使得它们继承System.Object。对象头有两个字段,sync-block存储各种信息位,如哈希码和调用Monitor.Enter()的线程ID。重要的字段是第二个,方法表指针。其中标识了对象类型。方法表包含类的方法的地址,它总是以Equals,GetHashCode和ToString开始,即Object实现的方法。
使用相同的眼镜,不的值类型值具有此对象标题。它只占用存储值所需的空间量。 bool为1个字节,Char为2个字节,int为4个字节,等等。这使得价值类型非常有效。
你可以戴上的第二副眼镜是“型号系统”眼镜。值类型值始终可以转换为对象。然后回来。此转换称为装箱转换。回头称为拆箱。快速实现实现眼镜,你会发现你确实得到了这两个字段的对象,方法表指针标识了值类型。方法表有其他方法指针。与IConvertible类似,是由值类型实现的接口。超出这两个字段的对象的其余部分由值类型值位占用。它在拳击转换之前仍然是一个简单的值时所拥有的相同位。盒装对象存在于垃圾收集堆上,就像所有引用类型对象一样。
在绝大多数情况下,C#或VB.NET编译器会完全自动应用装箱转换。您不必自己在代码中编写强制转换。例如,你可以调用ToString或其中一个IConvertible方法,你将免费获得拳击转换。
这会产生一种值类型继承自System.Object的错觉。这是一个相当不错的错觉,任何戴着“类型系统”眼镜的人都会坚持认为值类型绝对是从Object继承的。如果你戴“实施”眼镜,那么你往往会担心拳击。它经过了大量优化,但肯定不是免费的。进行转换需要花费cpu周期,盒装值类型值会占用更多空间并产生垃圾。泛型集合类型已完全替换旧的System.Collection类的原因之一。
答案 2 :(得分:1)
这是非常错误的。在.NET中,“原始”类型(=值类型)做实际上来自System.Object
。但是,它们仅在类型系统方面这样做。他们的治疗方法仍然与参考类型不同。
这可以通过编译器和运行时中的特殊处理来处理。最直接的实现是,引用类型是通过指向堆分配存储的指针实现的,而值类型则不是。但请注意,这严格来说是Microsoft实现CLR(.NET)的实现细节。其他实现可能会以不同的方式处理它。
答案 3 :(得分:1)
简答:原始类型派生自System.Object,它的实现方式与.net中的任何其他类型一样。
答案很长: 但是,原始类型在.NET中是这样称呼的,因为支持它们的类被编译器识别为内置类型。此外,原始类型不是引用类型,它们是值类型(在.net中也称为轻量级类型),因此它们不在托管堆上分配,而是在线程堆栈上分配。
例如:
var a = new Int32(16);
var b = 16;
两个声明都将生成相同的IL指令。编译器会将 b = 16 解释为 b = new Int32(16)。 编译器将对涉及内置轻量级类型/原语的代码进行一些优化,例如:
int a = 1 + 2;
将编译为:
int a = 3;
当然还有另一个不太明显的优化,但我会对此给你一个很好的解释。
关键是类型和轻量级类型(基元所属的位置)之间的差异。这篇文章讨论了两种类型之间的差异,是一个很好的起点: http://msdn.microsoft.com/en-us/magazine/cc301569.aspx
答案 4 :(得分:0)
我理解原始类型不是从Object
派生的
他们继承自对象。例如,请参阅System.Int32
(这是VB.NET将Integer
翻译为的内容)。
就像Java一样,在.NET中,所有类型都继承自Object
,包括基本类型。
您认为语言原语类型在编译期间被翻译为从Object
继承的相应CLR类型。