more on backward compability – this time with lang

I blogged an answer to Mark’s question about var in Java 10. He wrote back the following. I thought it was great and asked if I could use it as a guest blog post. He said yes.

So compliments of our guest blogger: Mark Yagnatinsky.

Thanks! You inspired me to try compiling my own little test program that I’d wondered about for a while:

It turns out that if you try to do this:

class java {
    class lang {
    }
}

Java won’t let you (it notices that there’s already a package with that name).
But first of all, this protection extends only to java.lang, and not, say, java.util.
And second of all, we can distract it by putting our code in a package:

package Scratches;
class java{
    interface lang{
        class String{}
        static void main( HELP[] args ) {
        }
    }
}

As far as I can tell, there is nothing we can type instead of HELP to make the above main method runnable on the command line.
In this case though, we’re only doing “local” damage: the rest of the code in our package (outside of “interface lang”) can still use Strings.

The way this is usually described is that there is an implicit “import java.lang.*” at the start of every file.
It turns out that java.lang is more special than this description implies.

If we try the same trick with java.util, we can knock access to the entire package (but not subpackages):

package Scratches;
// the line below has no effect whether you comment it out or not.
//import java.util.Hashtable;
class java {
    interface lang {
        class String{}
        static void main( String... args ) {
            // can't fix signature to run this method.
        }
    }
    interface util {
        class Hashtable{}
    }
}
class Main {
    public static void main( java.lang.String... args ) {
        // this method does not get called if you run from the command line
    }
    public static void main( String... args ) {
        // this method runs from the command line just fine
        new java.util.Hashtable(); // this is our hash table, not Java's
        // the line below won't compile (no such name)
        //new java.util.HashMap();
        new java.util.concurrent.ConcurrentHashMap(); // but this is fine
    }
}

It’s kind of amazing how much insanity the capitalized class name convention protects us from.
(Though to be fair, Java.Util is also a fairly unlikely class name…)

speaking at the NY Java Sig and including remote attendees

This week, I spoke at the NY Java Sig reprising my QCon Java 10/11 Release Train talk.It was fun.  Last time I spoke at the NY Java Sig, I was the unplanned “opening act” for the main talk. This time, there were two planned speakers and I was one of them. I went second.

The NY Java Sig was hosted by Credit Suisse. They had 12 remote attendees from their Raleigh, NC office. We were able to hear, but not see them. They were able to see me.

I work on a distributed team so dealing with remote people I can or can’t see is just a part of me. I didn’t realize how much so until this presentation though.

When I present, I try to involve the audience a bunch of times. They raise their hands, vote on stuff, etc. Almost every time I did that, I asked someone in Raleigh to comment on how the vote looked there.

I got feedback at from the NY Credit Suisse representative that this was the first time that a speaker included them. (To be fair, most speakers don’t involve the NY audience either.) The really cool part is that I didn’t even realize I was doing it. It was just part of me; they were attending so I asked.

For this particular presentation, I had offered a couple “free conference level training” available to any of our offices remotely. So I had practiced with people I couldn’t see as well.

var in java 10

In my Java 10/11 talk, I ask the audience if this code compiles:

var var = "var";

I usually get about a 50/50 response. The answer is that it does compile due to backward compatibility. You could have a local variable named var and it should still work. When I gave the talk at the NY Java Sig tonight, Mark asked “what if you have a class named lower case var”. After wincing a bit at the lower case class name, I said I didn’t know. But I definitely wanted to find out.

The answer is actually pretty interesting – it depends on what version of Java you compile with!

Compiling var.java

Fierst I created a class


public class var {

  public static final String STR = "a";

}

This class compiles in Java 9 and below. It does not compile in Java 10 or 11. Instead you get the message:

as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations

This means that you have to change the class name. However, you can still have a var.class file compiled in Java 9 or below.

Referencing that var.class file

Compiling OR running the code with Java 10/11 doesn’t let you refer to that var.class file either.

TripleVar.java:5: error: illegal reference to restricted type 'var'

Conclusion

If you followed bad practices and named your class var.class, you must change it. Even if you compiled in Java 9, it will not run in Java 10.