I've read a comparison of C# and Java and the first thing on the list is "Single-root (unified) type system".
Can you describe what a single-root (unified) type system means?
C# has a unified type system. All C# types, including primitive types such as int and double, inherit from a single root object
type. Unlike class objects, these primitive types are value-types. They are not separately heap-allocated, and they are passed by value.
When a C# value type (such as a primitive int, or user-defined struct) is placed in a parametric collection, it is stored in a densely packed array with no pointers. This is possible because C# makes a custom parametric instantiation for each different parametric 'size' that is required. This means when you instantiate a C# List<int>
, the underlying array list stores densely packed arrays of int.
Source: http://www.pin5i.com/showtopic-24376.html
Java also has several primitive types (int, long, double, byte, etc) - however, they are special in that they are not object-oriented and they could not have been defined using the language itself. They are value types, not heap allocated, and passed by value.
Source: Comparison of C# and Java - Unified type system (Wikipedia)
At the same time, Java also has object-oriented primitive "wrapper" types (Integer, Long, Double, Byte, etc), often called boxed
types. These are heap allocated objects which are passed by reference, and exist in parallel to the primitive types mentioned above.
In more recent versions of Java, primitive types are automatically boxed into object types when necessary. This relieves most of the burden of managing them but it can also cause subtle bugs (see also auto-boxing).
In contrast to C#, in Java, the built-in JDK Collections framework always manages collections of object pointers. In order to make them parametric in a backward-compatible fashion, Java performs a technique called type-erasure, where (during runtime) everything is treated as an object inside the container (parameterised type checks are performed at compile time).
This means that you cannot make a Java List<int>
, you can only make List<Integer>
. And, the list above actually stores an array of pointers to boxed Integer
objects, which is double the size and substantially less performant than the C# version. For most use cases, this difference in size and performance is irrelevant.
In use cases where size and performance are relevant, there are two options available:
int[]
. Arrays of native types are packed in memory so they consume A LOT less memory and are more performant.