Project Coin was a subproject of OpenJDK aimed at determining the set of small language changes that had to be added to JDK7. Some of the proposals under Project Coin were incorporated in JDK7. A JDK Enhancement Proposal (jep – 213) was added to address and include amendments to these changes in Java 9.

There are basically five small amendments that are added to Java programming language as a part of this JEP.

@SafeVarargs For Private Methods

The annotation @SafeVarargs was introduced in Java 7. This was introduced to assert that the annotated method body do not perform potentially unsafe operations on their parameters. This annotation is used with methods that cannot be overridden as the overriding methods may contradict the usage of the annotation by performing an unsafe operation on the varargs parameter. In Java 7 release, the annotation was applicable only to static and final methods of a class. Java 9 has extended this feature for private methods also.

Consider the following example:

import java.util.*; public class PrivateSafeVarArgsDemo { public static void main(String[] args) { PrivateSafeVarArgsDemo demoObj = new PrivateSafeVarArgsDemo(); demoObj.testMethod(Arrays.asList("apple", "orange"), Arrays.asList("grape", "pineapple")); } @SafeVarargs public static void testMethod(List<String>...strList) { sampleVarArgsMethod(strList); } private static void sampleVarArgsMethod(List<String>...strList ) { System.out.println("number of string inputted: " + strList.length); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java . util . * ; public class PrivateSafeVarArgsDemo { public static void main ( String [ ] args ) { PrivateSafeVarArgsDemo demoObj = new PrivateSafeVarArgsDemo ( ) ; demoObj . testMethod ( Arrays . asList ( "apple" , "orange" ) , Arrays . asList ( "grape" , "pineapple" ) ) ; } @SafeVarargs public static void testMethod ( List <String> . . . strList ) { sampleVarArgsMethod ( strList ) ; } private static void sampleVarArgsMethod ( List <String> . . . strList ) { System . out . println ( "number of string inputted: " + strList . length ) ; } }

Let us run the above code in the command prompt using:

javac -Xlint:unchecked PrivateSafeVarArgsDemo.java 1 javac - Xlint : unchecked PrivateSafeVarArgsDemo . java

The following warning will be shown as the SafeVarargs annotation is not used in the private method:

PrivateSafeVarArgsDemo.java:15: warning: [unchecked] Possible heap pollution from parameterized vararg type List<String> private static void sampleVarArgsMethod(List<String>...strList ) { ^ 1 warning 1 2 3 4 PrivateSafeVarArgsDemo . java : 15 : warning : [ unchecked ] Possible heap pollution from parameterized vararg type List < String > private static void sampleVarArgsMethod ( List < String > . . . strList ) { ^ 1 warning

The heap pollution mentioned in the error message can be caused by generic methods including varargs if the variable of the parameterized type refers to an object which is not of that type.

Enhancements For Try With Resources

In Java 7, try with resources statement required a fresh variable to be declared for each resource that is managed by the statement.

A final variable is one that cannot be modified after initialization and has the keyword final explicitly added to it during declaration. An effectively final variable is a variable that does not have final keyword added to it but is not modified throughout the program after initialization.

In Java 9, if a resource is referenced by a final or effectively final variable, try with resources can handle it without having to declare a fresh variable.

package projectcoin; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryWithResourceEffectivelyFinal { private static final String PATH = System.getProperty("user.dir") + File.separator + "testFile.html"; public static void main(String[] args) throws FileNotFoundException { BufferedReader bufReader = new BufferedReader(new FileReader(PATH)); try (bufReader) { String input; while ((input = bufReader.readLine()) != null) { System.out.println(input); } } catch (IOException e) { e.printStackTrace(); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package projectcoin ; import java . io . BufferedReader ; import java . io . File ; import java . io . FileNotFoundException ; import java . io . FileReader ; import java . io . IOException ; public class TryWithResourceEffectivelyFinal { private static final String PATH = System . getProperty ( "user.dir" ) + File . separator + "testFile.html" ; public static void main ( String [ ] args ) throws FileNotFoundException { BufferedReader bufReader = new BufferedReader ( new FileReader ( PATH ) ) ; try ( bufReader ) { String input ; while ( ( input = bufReader . readLine ( ) ) ! = null ) { System . out . println ( input ) ; } } catch ( IOException e ) { e . printStackTrace ( ) ; } } }

The above program would have thrown an error in case of Java 7 and Java 8 but works fine with Java 9 because value of bufReader is never altered after initialization.

Diamond With Anonymous Classes

Java 7 introduced the concept of using Diamond <> operator in generics. With Java 7, we can create a list with the following statement:

List<String> listSample = new ArrayList<>(); 1 List <String> listSample = new ArrayList < > ( ) ;

Before JDK 7, it was mandatory to specify the type while creating the ArrayList. With diamond operator, the language knows inherently that the ArrayList is going to hold string objects as the object reference listSample is of type List<String>.

With Java 9, the diamond operator usage has been extended to anonymous inner classes also so that a cleaner code is written.

Let us learn more about this with an example:

package projectcoin; import java.util.Iterator; import java.util.NoSuchElementException; public class AnonymousDiamondExample { public static void main(String[] args) { Integer[] primes = { 2, 3, 5, 7, 11 }; Iterator<Integer> iter = new Iterator<>() { int i = 0; @Override public boolean hasNext() { return i < primes.length; } @Override public Integer next() { if (!hasNext()) throw new NoSuchElementException(); return primes[i++]; } }; while (iter.hasNext()) System.out.println(iter.next()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package projectcoin ; import java . util . Iterator ; import java . util . NoSuchElementException ; public class AnonymousDiamondExample { public static void main ( String [ ] args ) { Integer [ ] primes = { 2 , 3 , 5 , 7 , 11 } ; Iterator <Integer> iter = new Iterator < > ( ) { int i = 0 ; @Override public boolean hasNext ( ) { return i < primes . length ; } @Override public Integer next ( ) { if ( ! hasNext ( ) ) throw new NoSuchElementException ( ) ; return primes [ i ++ ] ; } } ; while ( iter . hasNext ( ) ) System . out . println ( iter . next ( ) ) ; } }

In the above example, we have a simple array of prime numbers for which we are creating a customized iterator. This iterator is created as an anonymous inner class. Note that the RHS of line 11 uses <> while defining the iterator body as anonymous inner class.

Output for the above program will be as follows:

2 3 5 7 11 1 2 3 4 5 2 3 5 7 11

Private Methods For Interfaces

Default methods were introduced in Java 8 mainly to support lambda expressions. With this feature, new methods could be added to interfaces without mandating all the implementing classes to implement the newly introduced code. A very good example of this would be the forEach method which was added as a default method to java.lang.Iterable interface which is inherited by java.util.Collection. In this way, there was no need to add implementation to this method in all the concrete classes like LinkedList, ArrayList, PriorityQueue, etc., and saved the developers of the language from changing code in multiple places for Java’s code base.

If there are two default methods that need to share code but should not expose too much of implementation details to the concrete classes which use the Interface, it would be a better idea to move that piece of code into a private method. This method can then be called by multiple default methods of the interface. But it will be still hidden from outside world and cannot be initiated from outside. Due to this reason, Java 9 has allowed usage of private methods in interfaces.

There are certain rules that should be followed while defining private interface methods:

No method can be declared private and abstract.

There should be a body for the private method.

No method should be declared as private and default.

Disallow Single Underscore To Be Used As A Legal Identifier

According to the rules for creating identifier name in Java, a variable’s identifier can start with a letter, dollar sign or underscore (but not with a number), followed by any number of alphanumeric characters, dollar symbols or underscores.

Before Java 8, it was possible to use a single underscore as a variable name. But single underscore is forbidden to be used as a lambda identifier for instance in Java 8. Java 9 has forbidden usage of single underscore for any type of identifier.

Consider the following example:

public class SingleUnderscore { public static void main(String[] args) { int _ = 10; System.out.println(_); } } 1 2 3 4 5 6 7 8 9 public class SingleUnderscore { public static void main ( String [ ] args ) { int _ = 10 ; System . out . println ( _ ) ; } }

On compiling the above code in command line, we get:

G:\learnings>javac SingleUnderscore.java SingleUnderscore.java:5: error: as of release 9, '_' is a keyword, and may not be used as an identifier int _ = 10; ^ SingleUnderscore.java:6: error: as of release 9, '_' is a keyword, and may not be used as an identifier System.out.println(_); ^ 2 errors 1 2 3 4 5 6 7 8 G : \ learnings > javac SingleUnderscore . java SingleUnderscore . java : 5 : error : as of release 9 , '_' is a keyword , and may not be used as an identifier int _ = 10 ; ^ SingleUnderscore . java : 6 : error : as of release 9 , '_' is a keyword , and may not be used as an identifier System . out . println ( _ ) ; ^ 2 errors

But usage of double underscores is still allowed in Java 9. For the same reason, the following code will compile and run successfully, giving the output as 11:

public class DoubleUnderscore { public static void main(String[] args) { int __ = 11; System.out.println(11); } } 1 2 3 4 5 6 7 8 9 public class DoubleUnderscore { public static void main ( String [ ] args ) { int __ = 11 ; System . out . println ( 11 ) ; } }

Although double underscores are supported by the language, it is better to stay away from usage of such identifiers as they make the code unreadable. The main reason why we use identifiers in any language is to address that location in memory to access/modify the value held there. If we use unreadable identifier names, that contradicts the need of identifiers. Another reason to use readable identifiers would be to prevent introduction of bugs in our code. If we use readable identifiers, that will help to maintain the code well.

Share this: Facebook

LinkedIn

Twitter

Tumblr

Pinterest



Like this: Like Loading...