My buddy Llewellyn showed me this a while back, but Java enums rock. It seems to me that in the Java/C# war whichever language gets the feature last does a better job because they see the other languages’ pain points. Enums were baked into .NET 1.0 (~2000), whereas Java got them in 2005. As a result Java did a better job.

The example they give in the tutorial is this one:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double getMass()   { return mass; }
    public double getRadius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }

    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }

    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage:  java Planet <earth_weight>");
            System.exit(-1);
        }
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/Planet.EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass));
    }
}

Pasted from here.

There was one syntax error in the code, and I changed a couple of other things shown in bold because I didn’t understand the point (perhaps if I was a better Java developer I might).

Let’s see what it would take to produce this in C#, shall we? I moved the main into a separate file (even in the Java world).
My first pass was this:

public class Planet
{
	public static readonly Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
	public static readonly Planet VENUS   = new Planet(4.869e+24, 6.0518e6);
	public static readonly Planet EARTH   = new Planet(5.976e+24, 6.37814e6);
	public static readonly Planet MARS    = new Planet(6.421e+23, 3.3972e6);
	public static readonly Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
	public static readonly Planet SATURN  = new Planet(5.688e+26, 6.0268e7);
	public static readonly Planet URANUS  = new Planet(8.686e+25, 2.5559e7);
	public static readonly Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);

	public static Planet[] values()
	{
		return new Planet[]
		{
			MERCURY,
			VENUS  ,
			EARTH  ,
			MARS   ,
			JUPITER,
			SATURN ,
			URANUS ,
			NEPTUNE,
		};
	}

	private readonly double mass;   // in kilograms
	private readonly double radius; // in meters
	private Planet(double mass, double radius)
	{
		this.mass = mass;
		this.radius = radius;
	}
	public double getMass() { return mass; }
	public double getRadius() { return radius; }

	// universal gravitational constant  (m3 kg-1 s-2)
	public static readonly double G = 6.67300E-11;

	public double surfaceGravity()
	{
		return G * mass / (radius * radius);
	}
	public double surfaceWeight(double otherMass)
	{
		return otherMass * surfaceGravity();
	}
}

Notice that I had to do explicit initialization, and I had to add the values function as well.
The only problem with this was that I didn’t get a proper ToString (or toString for the Java folks). I could just add it, but that would be tricky. Instead let me try another way, basically using the normal .NET enums to my advantage.

public enum PlanetEnum
{
	MERCURY,
	VENUS  ,
	EARTH  ,
	MARS   ,
	JUPITER,
	SATURN ,
	URANUS ,
	NEPTUNE,
}

public class Planet
{
	public static readonly Planet MERCURY = new Planet(PlanetEnum.MERCURY, 3.303e+23, 2.4397e6);
	public static readonly Planet VENUS = new Planet(PlanetEnum.VENUS, 4.869e+24, 6.0518e6);
	public static readonly Planet EARTH = new Planet(PlanetEnum.EARTH, 5.976e+24, 6.37814e6);
	public static readonly Planet MARS = new Planet(PlanetEnum.MARS, 6.421e+23, 3.3972e6);
	public static readonly Planet JUPITER = new Planet(PlanetEnum.JUPITER, 1.9e+27, 7.1492e7);
	public static readonly Planet SATURN = new Planet(PlanetEnum.SATURN, 5.688e+26, 6.0268e7);
	public static readonly Planet URANUS = new Planet(PlanetEnum.URANUS, 8.686e+25, 2.5559e7);
	public static readonly Planet NEPTUNE = new Planet(PlanetEnum.NEPTUNE, 1.024e+26, 2.4746e7);

	public static Planet[] values()
	{
		return new Planet[]
		{
			MERCURY,
			VENUS  ,
			EARTH  ,
			MARS   ,
			JUPITER,
			SATURN ,
			URANUS ,
			NEPTUNE,
		};
	}

	private readonly double mass;   // in kilograms
	private readonly double radius; // in meters
	private readonly PlanetEnum planetEnum;

	private Planet(PlanetEnum planetEnum, double mass, double radius)
	{
		this.planetEnum = planetEnum;
		this.mass = mass;
		this.radius = radius;
	}
	public double getMass() { return mass; }
	public double getRadius() { return radius; }

	// universal gravitational constant  (m3 kg-1 s-2)
	public static readonly double G = 6.67300E-11;

	public double surfaceGravity()
	{
		return G * mass / (radius * radius);
	}
	public double surfaceWeight(double otherMass)
	{
		return otherMass * surfaceGravity();
	}

	public override string ToString()
	{
		return planetEnum.ToString();
	}
}

That achieves parity, but it is ugly.

Score 1 for Java I guess…

This brought me to the end of the first three modules (OO Programming concepts, Language Basics, and Classes and Objects) in the “Learning the Java Language trail”. Next time I will continue with “Interfaces and Inheritance”.

I will admit it – the last time I did any serious Java programming Bill Clinton had just started his second term and Princess Diana was still alive. I kept up with the news here and there, for example I investigated (and quickly dismissed ) Java’s generic support back in 2005. Also my friend Llewellyn Falco had several Monday night code sessions that I attended which used Java. But on the whole my Java knowledge was … ahem… a bit stale. But all of that was about to change because I need to write a cloud course which covered a number of platforms, one of them being: Java.

As part of this little exercise, I am going to blog about some of the differences between the C# and Java languages. I am not just talking about how the C# readonly keyword is the same as the Java final keyword, I am talking about the major differences liked generics, checked exceptions, delegate support, properties, etc.

I jumped back in by flipping through the Java tutorial. The fact that a fully sponsored and standardized tutorial exists is already a point in Java’s favor. Not that there aren’t C# tutorials, there are in fact 3.6 quadrillion of them (rough guess). I even found one from Microsoft but it was for .NET 1.1 and a lot has changed since then.

After a while of quickly flipping through the tutorial I thought I had something that was notably different – namely explicit constructor initialization. I was thinking that the Java version could be more powerful that the C# version, until I read the line:”If present, the invocation of another constructor must be the first line in the constructor.” Crap. Never mind, with that limitation it is essentially the same as C#.

OK, a few more pages and I came across static and instance initializer blocks. However, once again after reading more closely it seemed like the recommended approach was to use private static methods and protected final methods to do the same thing (which is the approach C# has to take). So for those of you keeping score:

Boring 2, Interesting 0.

The next item I came to was on the subject of nested classes. I will confess I rarely use nested classes in C#, and I have a feeling that most developers in Java would say the same thing. When I do use them it is because I have classes that are tied to the state of the parent object. A great example of this is the state pattern, where you have an object that can transition between many states and the behavior of the object changes when the state is changed. In cases like that rather than allowing outsiders to change the state to whatever they want, you can make the states inner classes and only they can set the state.

This wikipedia article on the comparison of C# and Java is somewhat misleading in this regard. If you search for “Instance level inner classes”, you will see it states that Java supports both class level (static) and instance level nested classes, whereas C# only supports class level. However, C# *does* support both class and instance level classes but it does so in a way that is fundamentally different than Java. What Java has that C# doesn’t have is a concept of the outer this pointer within the inner class. That is what the wikipedia article is referring to. This means in C# you have to pass the outer object instance around just like you would with other classes, whereas in Java you get that for free.

A couple of pages later there was another interesting tidbit on local and anonymous inner classes. However, the tutorial writers were apparently just whetting my appetite, because they didn’t go into any detail at all. I am sure I will come back to that later.

Moving on. Finally the first significant difference between .NET and Java: enums. So major in fact that I had to move it to its own separate post.