Sunday, 27 November 2005

Changing Java: Adding simpler primitive creation

So, when you're coding in Java sometimes you just have to use primitives. (We'd all love to use objects all the time, but that just isn't possible in Java). However creating primitives can be a pain on occasion, so what could we do?

Defining a variable/constant is easy and just works for short/byte (and all types):

// defining variables is easy:
double val1 = 2.1d;
float val1 = 2.1f;
long val1 = 2L;
int val1 = 2;
short val1 = 2;
byte val1 = 2;

However calling a method shows us the nasty difference between bytes and shorts compared to longs, floats and doubles:

someFloatMethod(2f);  // compiles OK
someShortMethod(2);   // doesn't compile
someByteMethod(2);    // doesn't compile
someShortMethod((short) 2);  // compiles OK
someByteMethod((byte) 2);    // compiles OK

public void someFloatMethod(float f) {
}
public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

So why do we not have a convenient shorthand for bytes and shorts like the 'f' for float or 'd' for double?

someShortMethod(2s);  // note the 's'
someByteMethod(2b);   // note the 'b'

public void someShortMethod(short s) {
}
public void someByteMethod(byte b) {
}

A related issue is creating a binary value (which I needed to do tonight - bonus points if you can guess the pattern I was storing!):

int binary =
    (1 << 2) + (1 << 5) + (1 << 7) + (1 << 10) +
    (1 << 13) + (1 << 16) + (1 << 18) + (1 << 21) +
    (1 << 24) + (1 << 26) + (1 << 29);

Yuck! Why could I not create it with a specialist syntax like this:

int binary = 0b00100101:00100101:00100100:10100100;

While not suitable for every case that you want to create a binary value, it definitely has value. The question is whether its too minor a use case to justify a language change?

Thursday, 24 November 2005

Adding for loop indexing to Java

When using the new for loop in JDK 1.5 do you ever need an index? What do you do, and could a language change help?

Collection coll = ...
int i = 0;
for (String str : coll) {
  System.out.println(str + ", line " + i);
  i++;
}

This isn't very friendly, and exposes the loop index outside the scope of the loop. Maybe we could have a small language change:

Collection coll = ...
for (String str : coll : int i) {
  System.out.println(str + ", line " + i);
}

Note that the extra : int i would be optional! If you don't want the index, just don't declare it.

This is really just a logical extension of the enhanced for loop change from JDK 1.5. Its main benefit is protecting against stupid errors with the scope of the index when an index is actually needed.

Something else that was lost with the new for loop was the ability to remove an item from the collection using the iterator. A variation on the index syntax would allow us to reinstate that:

Collection coll = ...
for (String str : coll : Iterator it) {
  if (str.startsWith("org.apache.")) {
    it.remove();
  }
}

There are more issues with this one however, as Iterator also exposes the hasNext and next methods which the for loop is using. This shouldn't cause a problem, but might require some more work in detailed design.

This blog is number 4 in a series on possible language enhancements to remove boilerplate code - see code blocks, nulls and casts. Opinions welcome as always :-)

Wednesday, 23 November 2005

Adding auto casts to Java

OK, so after auto null checks and code blocks what else would make Java that little bit clearer to read and write? What about casts?

Once again, here is an example use case:

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return ((Person) obj).getAge();
  }
  return -1;
}

Note, I've deliberately kept the use case 'stupid'. There are many good OO solutions to this kind of problem, but I believe that the vast majority of Java developers still end up writing nasty casts all the time.

So, what do I propose could be changed in Java 1.6?

public int getAge(Object obj) {
  if (obj instanceof Person) {
    return obj.getAge();
  }
  return -1;
}

The compiler can easily figure out that obj must be an instance of Person in the if statement. So why do we need the cast? The code without the cast is more readable and just as safe.

I still believe that casts have a useful role to play in Java, when you want to emphasise a point in conversion, or to cast without an instanceof. But when we've already checked with the instanceof, why are we have to repeat ourselves? Thats just boilerplate code.

Opinions welcome, as always.

Tuesday, 22 November 2005

Adding auto null checks to Java

So, after considering code blocks yesterday, what about another bane of Java life, nulls. How could they be simplified in a Java-friendly style?

Here's the use case I'm trying to solve:

public isFromBritain(Profile profile) {
  if (profile != null) {
    Person person = profile.getPerson();
    if (person != null) {
      Address address = person.getAddress();
      if (address != null) {
        return "GB".equals(getCountry());
      }
    }
  }
  return false;
}

And here is my proposed solution for JDK1.6:

public isFromBritain(Profile profile) {
  return profile#getPerson()#getAddress()#getCountry()#equals("GB");
}

A bit surprising at first glance, yet much much simpler to read and understand. I'm using # to indicate "ignore null for now and continue processing". I used # as javadoc already uses it instead of a dot. Implementation-wise, the compiler would expand it to the former use-case, so no big issues there.

By the way, this series of entries is inspired by Graham Hamilton's blog about boilerplate Java code. I'm just trying to show what gets in my way, and provide a Java-style (not Ruby/c#/python/... style) solution. As always, opinions welcome :-)

Monday, 21 November 2005

Adding closures to Java, or not...

There has been a lot of talk on Javalobby recently about adding closures to Java. But how can this be done without destroying the style of Java?

Groovy shows one way to add closures. But groovy has the ability to create syntax, change classes and do other strange stuff that is just too way out for Java itself. So I though I'd do an experiment to see if I could figure out a way to add closures to Java following a more java style.

I started with a use case I wanted to solve, the dreaded resource close:

InputStream in = null;
try {
  in = new FileInputStream(file);
  in.read();
  ...
} finally {
  if (in != null) {
    try (
      in.close();
    } catch (IOException ex) {
    }
  }
}

I then played around with some ideas.

My preferred solution was:

do.CloseAfter (InputStream in) {
  in = new FileInputStream(file);
  in.read();
  ...
}

I saw the main benefits as being more readable, shorter, removing the common close code, scoping the variable and reducing errors. Importantly, a current Java programmer would grok the new way of woring very quickly (no complex syntax).

The key was using the do keyword to identify the special code. I believe that this keyword-usage is much more Java-style than arbitrary symbols like ->.

CloseAfter would just be a regular Java class, just limited to have one method:

public class CloseAfter implements ClosureManager {
  public void execute(InputStream in) {
    try {
      call(in);
    } finally {
      if (in != null) {
        try (
          in.close();
        } catch (IOException ex) {
        }
      }
    }
  }
}

For this common case, it would be a JDK class.

Once I'd done all this and convinced myself that the compiler could implement it easily (by copying the CloseAfter code directly into the original method) I had a sudden realisation - this wasn't really closures, but surrounded code blocks.

Nevertheless, it could be very, very useful, for example to do commit and rollback...

do.DBTransaction (Connection con) {
  ...
}

Kind of like AOP-lite :-)

I just have this sense that a syntax like this would be easy to add to Java, and solve 80% of the issues that full-blown closures tackle (with 20% of the complexity). Opinions welcome :-)