Default Methods of Java 8 and an impact on javac


I have an interesting experience with Java 8.

public class ZonedDateTimeToInstant {
    public static void main(final String[] args) throws NoSuchMethodException {
	assert ChronoZonedDateTime.class.isAssignableFrom(ZonedDateTime.class);
        final Method toInstant = ChronoZonedDateTime.class.getMethod("toInstant");
	final ZonedDateTime now = ZonedDateTime.now();
	final Instant instant = now.toInstant();
	System.out.println(instant);
    }
}

When I tried to compile it with -source 1.7, javac complained me that she doesn’t understand the method toInstant which is clearly defined in ChronoZonedDateTime class that ZonedDateTime class implemented.

$ javac ZonedDateTimeToInstant.java
$ java ZonedDateTimeToInstant
2014-04-01T12:01:13.934Z
$ 
$ javac -source 1.7 ZonedDateTimeToInstant.java
warning: [options] bootstrap class path not set in conjunction with -source 1.7
ZonedDateTimeToInstant.java:10: error: cannot find symbol
	final Instant instant = now.toInstant();
	                           ^
  symbol:   method toInstant()
  location: variable now of type ZonedDateTime
1 error
1 warning
$ javac -version
javac 1.8.0
$ 

javac is quickly suspected of having a bug.

$ cat Java8.java
public class Java8 {
    public void print(java.io.PrintStream out) {
        out.printf("hello world\n");
    }
}
$ javac Java8.java
$
$ cat Java7.java
public class Java7 {
    public static void main(final String[] args) {
        new Java8().print(System.out);
    }
}
$ javac -source 1.7 Java7.java
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
$ 
$ java Java7
hello world

No. Nothing’s wrong with javac. After spending some stackoverflowing, I answered that the javac is actually complaining about the source code, which is being compiled with -source 1.7, is using a Default Method defined in an interface.

$ cat Java8i.java
public interface Java8i {
    default void print(java.io.PrintStream out) {
        out.printf("hello world\n");
    }
}
$ javac Java8i.java
$ 
$ cat Java8c.java
public class Java8c implements Java8i {
}
$ javac Java8c.java
$ 
$ cat Java7i.java
public class Java7i {
    public static void main(final String[] args) {
        new Java8c().print(System.out);
    }
}
$ javac -source 1.7 Java7i.java
warning: [options] bootstrap class path not set in conjunction with -source 1.7
Java7i.java:3: error: cannot find symbol
	new Java8c().print(System.out);
	            ^
  symbol:   method print(PrintStream)
  location: class Java8c
1 error
1 warning
$ 

I think javac should’ve told me more helpfully.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s