Java vs. C# - Part 0 - Primitive Types vs. Value Types

Java vs. C# - Part 0 - Primitive Types vs. Value Types
   As you may know I am a kind of programming language geek. Despite the fact that every software developer uses one or more programming languages most developers do not care much about them. Some are interested in software design patterns, some care more about development methodologies, some are algorithm guys, some like diving deep into databases, many are just interested in technologies and frameworks and there are even those who do not have a real passion but work as developers because this is how they pay the bills. Well my passion are programming languages and while I do not have the opportunity to work professionally on a compiler or even a parser I try to follow the development of popular programming languages and enjoy reading the motivation for language design decisions and compiler implementation decisions that language developers post online. I also like digging in programming language history.

   As part of my passion I regularly take part in IT flame wars on forums, blogs, IRC and in the physical world. One discussion that repeats often is Java vs. C#. I decided to summarize my arguments in this series of posts and just link them next time instead of writing the same thing again. What is more Java and C# share similar philosophy which makes comparison relatively easy. They are both statically typed, built on managed runtimes, object oriented, JIT compiled, etc. This eliminated many of the religious arguments and allows me to focus on more concrete things. When reading keep in mind that this article compares the programming languages. It does not deal with political issues like "Microsoft vs. Open Source" and only touches on things like tools and the underlying framework where it is directly related to the programming language or the compiler without taking into account the price, quality, portability, vendor support and availability of tools, libraries, web frameworks, desktop UI frameworks, mobile platforms support and many others that can make the platform better or worse for your particular case and are usually more important than the language itself. I am planning to only focus on features that both C# and Java have in some way. I will not comment on features that C# has and Java lacks and why they should be included in the language. It seems best to wait until Java 7 before comparing these features because many of them are proposed to be included in this future version. Probably these features will be discussed in future articles.

   I would also like to state that I do not consider Java language designers stupid or incompetent in any way. Many of the mistakes in Java were avoided in C# only because they were made in Java and the result was evident in the wild. Some of the decisions made sense when Java was made because it was created in a different time and targeted a different group of developers. In fact the Java language designers have done wonders introducing new features provided with the current legacy.

   It is also important to agree on what we consider good and bad and what is the main goal of languages like C# and Java. Performance is important but not of extreme importance because otherwise we would just use C/C++. It is good to have shorter code with less negotiations with the compiler but not of extreme importance otherwise we would use a dynamically typed language. It is good to have easily readable code but not of extreme importance otherwise we would use Python or Delphi. In my opinion the most important goal of C# and Java is producing the most maintainable code while staying as close to the aforementioned goals as possible.

   So here we go...

   Java's primitive types suck. Java books like to point out that in Java everything is an object and then quickly introduce the exception - the primitive types. The very fact that there is an exception increases the complexity of the language and creates problems for people using it. Even professional Java programmers have troubles with wrapping and unwrapping ints into Integers especially when they need to compare wrapped and unwrapped int. Pared with the lack of operator overloading it often requires thinking what the comparison operator does. I know that most Java developers will be able to predict the output of the following code but I doubt many of them will claim that this behavior improves readability and maintainability:

   Integer i1 = 1;
   int i2 = 1;        
   System.out.println(i1 == i2);
   Integer i3 = new Integer(1);
   Integer i4 = new Integer(1);
   System.out.println(i3 == i4);

Why does the first comparison choose to unbox the Integer instead of boxing the int? Why does the second comparison operator change the semantics if Integer and int are supposed to be the same?

   Even with autoboxing wrappers are all over the Java source code. You cannot declare a generic class or a generic interface of a primitive type which can hurt the performance in cases where extreme performance is required. When a type system needs two different types to represent a 32 bit integer then you know something is really wrong.

   C# solves these problems by introducing a special kind of objects - the value types. Value types do inherit from object but are passed around by value instead of reference and are stored on the stack instead of the heap (for local variables and method arguments but not for class members). Autoboxing occurs when these types are cast to object or object is cast to these types (autounboxing) but this is transparent to the user. Wrapper types are never seen and are not present in the type system despite the fact that the runtime wraps value types internally. Generics of value type are allowed and optimized by the JIT compiler to avoid boxing. In my opinion the power and beauty of C#'s type system approach is best demonstrated by this expression illegal in Java but legal in C#:


   The fact that you can call a method inherited from object on an int literal shows that in C# everything is really an object and this is transparent to the developer. There are user defined value types which are useful for many more things. For an example of elegant use you can read Jon Skeet's article on custom value types. What is even more interesting is that he used custom value types when porting a Java library.

Update: Part 1 has been published.
Tags:   english programming 
Last edited by:   Stilgar
on   01:07 21.06.2010
Posted by:   Stilgar
04:36 19.06.2010


First Previous 1 Next Last 

Posted by   JOKe (Unregistered)   on   12:43 24.06.2010

haha :)
The another strange thing :) is the caching of the boxed values. So what I mean:
if you type:
int a=5;
int b=5;
if( a==b) // it will be true
int a=200;
int b=200;
if(a==b) // true again
Integer a = 5; //or new Integer(5) same shit
Integer b = 5;
if(a==b) // true again and it will compare 5==5 really.!
Integer a= 129;
Integer b=129; // or new Integer - same shit.
if(a==b);// FALSE why because only integers from -128 to 127 are cached and are compared as unboxed variable the rest are compared as objects and are false... shit right ? :D but anyway Java rulz dont know what is C# I cannot even type it correctly in google ..... OMG.

Posted by   Stilgar   on   13:04 24.06.2010

except that you are not right that
Integer a = 5;
Integer a = new Integer(5);
is the same shit... talk about confusing

Posted by   ivelinka   on   13:13 24.06.2010

JOKe, your comment isn't exactly clear. let me give the examples:

Integer i1 = 5;
Integer i2 = 5;
System.out.println(i1==i2); //cached -> true

Integer i3 = Integer.valueOf(5);
Integer i4 = Integer.valueOf(5);
System.out.println(i3==i4); //cached -> true

Integer i5 = new Integer(5);
Integer i6 = new Integer(5);
System.out.println(i5==i6); //new objects, not cached -> false

Integer i7 = 129;
Integer i8 = 129;
System.out.println(i7==i8); // values > 127, not cached -> false

I admit it.. it's really confusing.

Posted by   JOKe (Unregistered)   on   13:20 24.06.2010

hahaha ok ok so //or new Integer(5) same shit, is not the same shit :D

anyway I like boxing/unboxing.
btw what is happening in C# if you have something like this :
* This should be closed method in a closed dll or obfuscated jar file with no doc or with a doc like that one:D
* @return
public static int someTotallyClosedMethodInDllOrJar() {
Integer nullOne = null;
return nullOne;

someTotallyClosedMethodInDllOrJar(); //dont have to asign it to anything or we dont care if we asign it to Integer or int same shit NullPointer always

Posted by   Stilgar   on   13:31 24.06.2010

You get a compile time error saying that Integer is not a known type:)

Posted by   ivelinka   on   13:33 24.06.2010

In my opinion this one is even worse:

Boolean test = null;
if (test) System.out.println("test");

the result: NPE

Posted by   JOKe (Unregistered)   on   15:16 24.06.2010

hahahaha ye :D

Posted by   JOke (Unregistered)   on   15:17 24.06.2010

Stilgar ok than Int32 or whatever... what I mean is can you write something like :

public static int someTotallyClosedMethodInDllOrJar() {
Int32 nullOne = null;
return nullOne;

or it is non nullable by default ?

Posted by   Stilgar   on   17:02 24.06.2010

You can't assing null to Int32. In case you still don't get it .NET HAS ONLY ONE TYPE FOR 32BIT SIGNED INTEGER. There is no difference between int and Int32 and there are no wrappers.

If you make the int nullable (which is by no means the same as Java's Integer) you will get compile time error saying that there is no implicit cast from int? to int. It is designed this way for the very same reason that motivates the lack of implicit cast between double and int. Actually the very same reason is behind the NPE in Java (instead of returning some default value).

Posted by   Nik (Unregistered)   on   15:47 29.06.2010

Value types ... are stored on the stack instead of the heap

This is not correct.  Value type members of classes are stored on the heap.  An array of value types goes on the heap as well.  Only local method value type variables are stored on the stack.

Posted by   Stilgar   on   16:57 29.06.2010

Explaination for value types added.

First Previous 1 Next Last 

Post as:

Post a comment: