Monday, April 30, 2012

Specifying Appropriate NetBeans JDK Source Release

NetBeans uses its projects' settings for javac.source (and javac.target) in more ways than simply enforcing javac's use of the -source and -target. In this post, I look at some of the numerous benefits of appropriately setting the Java release source level in NetBeans.

In a standard ("Java Application") NetBeans project, the JDK version is for the project is specified in the Project -> Properties -> Sources window. This is shown in the next screen snapshot with a really old version (1.2) of the SDK displayed.

Setting a project like that shown in the above screen snapshot leads to the setting of the properties javac.source and javac.target in the nbprojects/project.properties file. This is shown in the next screen snapshot.

There are several benefits to setting this JDK/Java version source level appropriately. According to the JDK 7 javac compiler documentation, it respects the following releases: 1.3, 1.4, 1.5 (5), 1.6 (6), and 1.7 (7). NetBeans 7.1 lists even more versions, ranging from JDK 1.2 through JDK 7.

Some benefits of setting the source level appropriately in NetBeans are obvious. For example, if the source JDK release is not set to at least 1.5 (or 5), then standard language constructs such as annotations, enums, and generics are shown are compilation errors in NetBeans. An example of this is shown in the next screen snapshot, which depicts the NetBeans error message when an enum is specified in a NetBeans project in which the JDK release is specified as 1.4.

The last example showed how using an "older" release can lead to errors regarding language features that did not exist for that release. An opposite benefit of this can be achieved by moving NetBeans's project's release to the new SDK release when appropriate because it can help developers identify ways in which they can improve their code base with the new version. I specifically discussed this approach using NetBeans 7 to "modernize" Java code bases to newer releases of Java in the blog post Seven NetBeans Hints for Modernizing Java Code. In that post, I demonstrated how NetBeans 7 (and even some older versions of NetBeans) can help flag areas of code where J2SE 5 and Java SE 7 new features apply and are not being used.

It's easy to think that there is no use in setting the source release in NetBeans to 1.6 (6) because Java SE 6 did not introduce any new language features. However, it turns out that there still are some differences and it's probably best to have 1.6 specified if that's the JDK the software is being written against. In the blog post Differences between source level 1.5 and 1.6 in NetBeans, Antonio Santiago wrote in early 2008 that NetBeans made use of Java SE 6's new Swing-related classes when JDK 1.6 was set as the release. This is preferable to using third-party libraries.

The use of new Java SE 6 SDK classes is not the only reason to have NetBeans projects configured to 1.6 if that's the version you're deploying against. Another difference between J2SE 5 and Java SE 6 treatment is the use of the @Override annotation on methods of classes that implement an interface. With NetBeans configured for J2SE 5, only methods extending a parent had a hint for @Override suggested, but in NetBeans configured to use Java SE 6 as the source release, methods implementing an interface also enjoy the hint to use that annotation. Note that if the source release is not set to at least 1.5, methods generated by NetBeans to implement an interface are generated without any @Override annotation in either case. The @Override annotation can be used on methods implementing an interface in NetBeans when JDK 1.5 is specified, but the issue is that there is no warning to add that annotation when not specified unless in at least JDK 1.6.

The difference in treatment of @Override has not been exclusive to NetBeans. The Javadoc for the Overrides annotation differs significantly between 1.5 and 1.7 (but interestingly not between 1.5 and 1.6):

1.5/1.6 Javadoc Description for Override
Indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.
1.7 Javadoc Description for Override
Indicates that a method declaration is intended to override a method declaration in a supertype. If a method is annotated with this annotation type compilers are required to generate an error message unless at least one of the following conditions hold:< br/>
  • The method does override or implement a method declared in a supertype.
  • The method has a signature that is override-equivalent to that of any public method declared in Object.

Section 9.6.3.4 of the Java SE 7 Java Language Specification states, "This behavior differs from that in Java SE 5.0, where @Override caused a compile-time error if applied to a method that implemented a method from a superinterface that was not also present in a superclass." More details regarding @Override in J2SE 5 versus Java SE 6 are available here.

Returning from the side note on @Override, one of my favorite additions to Java SE 7 is not even a language feature. The new Objects class is especially handy for writing more standard and safer implementations of the "common" methods equals(Object) and hashCode(). If a developer has his or her NetBeans project configured to use JDK 1.7 as the release, NetBeans takes advantage of the Objects class to implement these methods.

I have looked at some of the benefits NetBeans provides for recent versions of the JDK (1.5, 1.6, and 1.7), but I am sure there are more that I'm not aware of. The point of all this is that it is best to ensure that a particular project is configured to be using the correct source version even if it is believed that the version difference does not matter. It may not matter outside of NetBeans (such as to javac) in some cases, but it likely does matter to NetBeans.

No comments: