© Vaskaran Sarcar 2020
V. SarcarInteractive Object-Oriented Programming in Javahttps://doi.org/10.1007/978-1-4842-5404-2_14

14. Important Features in Java’s Enhancement Path

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

Welcome to Chapter 14. In this book, my focus has been on the fundamental concepts of object-oriented programming in Java only. All programs were compiled in Java 8, which was the baseline in this book. Like other popular languages, Java is continuously growing, with new features added regularly. Though detailed coverage of these features was out of the scope of this book, in this chapter, you will examine some features or enhancements from various versions of Java. You get the most value out of a new enhancement if you are familiar with the existing features. So, for this chapter, I have picked only topics with which you are already familiar.

As a student, I first saw a Java book, which was based on Java 2, in my professor’s hand a long time ago. But at the time of this writing, Java 13 has been released, and in the upcoming days Java’s release train will be very fast. At present, Java is releasing new versions every six months. As a result, you can expect to see a lot more changes in the near future. But, as was said before, if you are familiar with the fundamental features and architecture, you can adapt to changes easily. All you have learned from this book can help you.

One final comment: for the latest features, I have compiled and executed the programs in the command-line environment. This is because my Eclipse environment was not ready to accept the latest features. So, if your preferred IDE is not ready to accommodate a latest feature, you can do the same thing I did. Now, let’s start.

Try-with-resource from Java 7

The try-with-resource statement is a try statement in which you can declare one or multiple resources. A resource is an object that should be closed when your program finishes execution. But to use this feature, you have to choose an object that implements the AutoCloseable interface in the java.lang package.

This is because the close() method of an AutoCloseable object is called automatically once the control exits a try-with-resource block.

Here, I present a simple demonstration for you. In this demonstration, Resource1 is a class that implements the AutoCloseable interface.

So, if you use this concept using the following block:
try(Resource1 resource1 = new Resource1())  {
           resource1.useResource();
        }

in the output you will notice that the close() method of Resource1 is called automatically.

Demonstration 1

Consider the following code:
package java2e.chapter14;
//Resource-1
class Resource1 implements AutoCloseable {
      public void useResource() {
            System.out.println("Using a Resource1 type.");
      }
      @Override
      public void close() throws Exception {
            System.out.println("Close Resource1 type now.");
      }
}
class TryWithResourceDemo {
      public static void main(String[] args) throws Exception {
         System.out.println("***Demonstration 1.Try with Resource demo.*** ");
         try(Resource1 resource1 = new Resource1())  {
         resource1.useResource();
        }
        catch(Exception e) {
            System.out.println(e);
        }
  }
}
Output
***Demonstration-1.Try with Resource demo.***
Using a Resource1 type.
Close Resource1 type now.

Q&A Session

14.1 What is a resource?

A resource is an object. Once your program uses a resource, you should close it before your program finishes execution.

14.2 Can I close multiple resources using this feature?

Yes. Here is a sample syntax for you, where two resources are used:
try(Resource1 resource1 = new Resource1();Resource2 resource2 = new Resource2())  {
  //Some code
}

Implementing Functional Interface Methods Using Lambda Expressions from Java 8

In Java, a functional interface is an interface that has only one method. You can use a lambda expression to provide an implementation for the interface method.

Note

In Chapter 12, prior to Demonstration 4, you got a quick overview of the lambda expression and its usage. If needed, you can review it there.

But the notable change is that in this case, you do not need to define the method again before you provide an implementation for it. So, you can save lots of typing.

Demonstration 2

To help you understand this concept, I have provided a usual implementation before using a lambda expression. Here, you will see how to use a lambda expression that can have a return statement. Refer to the supporting comment lines for a better understanding.
package java2e.chapter14;
@FunctionalInterface
interface MyFunctionalInterface {
      int addNumbers(int firstNumber, int secondNumber);
//error:You cannot declare multiple methods in a functional interface.
      //int addNumbers2(int firstNumber, int secondNumber);
}
//Usual implementation of an interface method
class Implementor implements MyFunctionalInterface{
      public int addNumbers(int firstNumber, int secondNumber) {
            System.out.println("Implementing the interface method 'addNumbers' inside the Implementor class.");
            System.out.println("Sum of "+ firstNumber + " and " +secondNumber + " is : ");
            return firstNumber+ secondNumber;
      }
}
class LambdaExpressionDemo {
      public static void main(String[] args) {
            System.out.println("***Demonstration 2. Lambda expression.*** ");
            //Common way to use an interface method.
            MyFunctionalInterface impl1= new Implementor();
            System.out.println(impl1.addNumbers(1, 2));
            // Using lambda expression with a return statement.
            System.out.println("Using Lambda expression with the return statement now.");
            MyFunctionalInterface impl3 = (int a, int b) -> {
                   return (a + b);
            };
            System.out.println("Sum of 50 and 100 is :");
            System.out.print(impl3.addNumbers(50,100));
      }
}
Output:
***Demonstration 2. Lambda expression.***
Implementing the interface method 'addNumbers' inside the Implementor class.
Sum of 1 and 2 is :
3
Using Lambda expression with the return statement now.
Sum of 50 and 100 is :
150

Q&A Session

14.3 Is @FunctionalInterface mandatory in this program to show that it is a functional interface?

No. But using the annotation in a case like this is a good practice that enhances readability. Also, if you use this annotation, in the future, if anyone tries to add another abstract method in the interface by mistake, the compiler can immediately raise an error.

Java Language Specification(11) says the following:
  • A functional interface is an interface that has just one abstract method (aside from the methods of Object) and thus represents a single function contract. This “single” method may take the form of multiple abstract methods, with override equivalent signatures inherited from superinterfaces; in this case, the inherited methods logically represent a single method.

  • It facilitates early detection of inappropriate method declarations appearing in or inherited by an interface that is meant to be functional.

  • “[I]nstances of functional interfaces can be created with method reference expressions and lambda expressions.”

Private Interface Method from Java 9

Private interface methods were a new addition in Java 9. Prior to Java 7, interface methods were straightforward—those were public abstract methods. Java 8 allows you to add public static methods and public default methods. In Java 9 onward you can use private static methods and private default methods in the interface.

Demonstration 3

Let’s consider the following demonstration. Here, you have an interface called MyInterface with four methods:
  • The first one is a common interface method; it does not have a body, and it is by default public and abstract.

  • Then you have two default methods.

  • Finally, you have the private non-static interface method, called privateInterfaceMethod(). Notice that since the method is private, you cannot call the method directly from main().

In this example, I am calling the private method through the default methods:
interface MyInterface{
      void commonInterfaceMethod();
      default void defaultInterfaceMethod1() {
            System.out.println("**Default non-static method1()**");
            //Doing the common task using the private interface method
            privateInterfaceMethod();
      }
      default void defaultInterfaceMethod2() {
            System.out.println("**Default non-static method2()**");
            //Doing the common task using the private interface method
            privateInterfaceMethod();
      }
      private void privateInterfaceMethod() {
            System.out.println("**Private non-static method in MyInterface**");
                System.out.println("**I can do the common tasks of multiple default methods.**");
      }
}
class MyInterfaceImplementor implements MyInterface{
      @Override
      public void commonInterfaceMethod() {
            System.out.println("**Implementing the commonInterfaceMethod().**");
      }
}
class PrivateInterfaceMethodFromJava9 {
      public static void main(String[] args) {
            System.out.println("***Demonstration 3.Private Interface Method From Java 9.*** ");
            MyInterface interOb=new MyInterfaceImplementor();
            interOb.commonInterfaceMethod();
            interOb.defaultInterfaceMethod1();
            interOb.defaultInterfaceMethod2();
      }
}
Output:
***Demonstration 3.Private Interface Method From Java 9.***
**Implementing the commonInterfaceMethod().**
**Default non-static method1()**
**Private non-static method in MyInterface**
**I can do the common tasks of multiple default methods.**
**Default non-static method2()**
**Private non-static method in MyInterface**
**I can do the common tasks of multiple default methods.**

Q&A Session

14.4 What is the use of a private interface method?

If you have multiple default methods in the interface and those interfaces are performing a common task, you can place the common code in the private helper method. Consider Demonstration 4 again. It shows how two default methods— defaultInterfaceMethod1() and defaultInterfaceMethod2()—can accomplish a common task using a private interface method.

14.5 If the sharing of code is the concern, I can make another default method and share the common code in that method. Is this understanding correct?

You can do that, but that approach cannot be considered a better design than this. It is better to use a private helper method than a public helper method. This approach can promote better encapsulation and security.

14.6 Can a default method be private?

No. You will get a compile-time error if you use the following line of code:
default private void defaultPrivateInterfaceMethod() {
 //some code
}
The error will be as follows:
PrivateInterfaceMethodFromJava9.java:14: error: illegal combination of modifiers: private and default
        default private void defaultPrivateInterfaceMethod() {//some code
                             ^
1 error

14.7 Can I make a private interface method static?

Yes. For example, if you add the following two methods in the interface MyInterface:
public static void publicStaticInterfaceMethod() {
            System.out.println("**Public static method in MyInterface**");
            System.out.println("**Invoking the private static method in MyInterface now.**");
      }
      private static void privateStaticInterfaceMethod() {
            System.out.println("**Private static method in MyInterface**");
      }
and then invoke the publicStaticInterfaceMethod() method from main() like the following:
MyInterface.publicStaticInterfaceMethod();
you will see the following lines in your output:
**Public static method in MyInterface**
**Invoking the private static method in MyInterface now.**

Points To Remember

  • Private methods cannot be abstract.

  • You cannot call a private non-static method from a private static method. If you do, you will receive a compile-time error for the following segment of code:

private static void privateStaticInterfaceMethod2() {
System.out.println("**Private static method2 in MyInterface**");
//Compile-time error
//privateInterfaceMethod();
}
But the reverse is allowed; i.e., you can call a private static method from a non-static private method in the interface. So, there is no compile-time error for this segment of code:
private void privateInterfaceMethod2() {
System.out.println("**Private Non-static method2 in MyInterface**");
//NO Compile-time error
publicStaticInterfaceMethod();
}

Local Variable Type Inference from Java 10

From Java 10 onward, you can declare a local variable without specifying its type.

Even if you do not declare the variable type, it can assume its type from what it is being set to. For example, from Java 10 onward, you can write something like the following:
var myInt=10;

Demonstration 4

The upcoming demonstration can show you a simple usage of var:
class LocalVariableTypeInterpretation {
 public static void main(String[] args) {
      System.out.println("***Demonstration 4.Local Variable Type Interpretation.*** ");
      int myInt1=1;//ok
      var myInt2=2;//Java10 onwards ok
      System.out.println("The value in myInt1 is :"+ myInt2);
      System.out.println("The myInt1 is of type:");
      //It will print java.lang.Integer
      System.out.println(((Object)myInt1).getClass().getName());
      System.out.println("The myInt2 is of type:");
      //It will also print java.lang.Integer
      System.out.println(((Object)myInt2).getClass().getName()); }
}
Output:
***Demonstration 4.Local Variable Type Interpretation.***
The value in myInt2 is :1
The myInt1 is of type:
java.lang.Integer
The myInt2 is of type:
java.lang.Integer

Restrictions

Here are some important restrictions when you use var:
  • You need to put both declaration and initialization together. For example:

var myInt=1;//ok
But the following line will raise a compile-time error:
var myInt;//Error
myInt=1;
  • You can use a variable name as var. The compiler will not complain about the following declaration; that is, it is not treated like reserved keywords in Java:

var var=12.5;//Till now , compiler allows it
  • You can use var in the context of initializing local variables and for loops, but you cannot use them in method parameters or return types. For example, in the following code segment, both methods in MyClass will raise compile-time errors:

//You can use 'var' in the context of initializing local variables //and for loops but you cannot use them in method parameters
//or return type.
class MyClass {
     void myMethod1(var i) { // Compile-time error
     // some code
     }
     var myMethod2(int i) { //Compile-time error
     }
}

New String Methods from Java 11

From Java 11 onward, you’ll get some new String class methods. In the following example, you will see three of them—isBlank(), repeat(), and strip(). Let’s see their definitions:
  • isBlank(): This method will return the Boolean value true if the string is empty or contains only white space codepoints; otherwise, false.

  • repeat(int n): Returns a string whose value is the concatenation of this string repeated n number of times.

  • strip(): This method returns a string with all leading and trailing white space removed.

Demonstration 5

Consider the following code:
class StringMethodsFromJava11 {
  public static void main(String[] args) {
      System.out.println("***Demonstration 5.Some new String methods from Java 11.*** ");
      String str1 = "A non-empty string.";
               System.out.println("The str1 is :"+ str1);
               System.out.println(" 'The str1 is a blank string'-This statement is "+ str1.isBlank());
               String str2 = "";
               System.out.println("The str2 is :"+ str2);
               System.out.println(" 'The str2 is a blank string'-This statement is "+  str2.isBlank());
               //Repeat the string
               System.out.println(" Repeating 'str1' 3 times now.");
               System.out.println(str1.repeat(3));
               //Using strip() removing beginning and trailing whitespaces
               String str3 = " Hi, Readers! How are you? ";
               System.out.println(" The str3 is :"+ str3);
               System.out.println("After strip() operation, str3 is :" + str3.strip());
      }
}
Output:
***Demonstration 5.Some new String methods from Java 11.***
The str1 is :A non-empty string.
 'The str1 is a blank string'-This statement is false
The str2 is :
 'The str2 is a blank string'-This statement is true
Repeating 'str1' 3 times now.
A non-empty string.A non-empty string.A non-empty string.
The str3 is : Hi, Readers! How are you?
After strip() operation, str3 is :Hi, Readers! How are you?

Q&A Session

14.8 How is isEmpty()different from isBlank()?

The definition of isEmpty() says that if and only if the string length is zero, it will return true. The following block of code can illustrate the difference between these two methods:
//isBlank vs isEmpty
String nonEmpty=" ";//a tab space
System.out.println("The nonEmpty.length()="+ nonEmpty.length());
System.out.println(nonEmpty.isBlank());//true
System.out.println(nonEmpty.isEmpty());//false
When you execute this block of code, you will get following output:
The nonEmpty.length()=1
true
false

Since the length of nonEmpty is not zero, isBlank() returns true, but isEmpty() returns false.

14.9 How is strip() different from trim()?

strip() can detect Unicode whitespace. But trim() can remove the space that is less than or equal to u0020. To see the difference, you can examine a string like the following:
//Medium Mathematical Space U+205F
String str1 = "u205F u205FThis is my test string with trailing whitespace-END.u205F u205F";
Now if you call the trim() method and the strip() method on this string object, you will notice the difference. For example, if you test with the following lines of code:
String trimmedString = str1.trim();
String strippedString = str1.strip();
System.out.printf("'%s'%n", trimmedString);
System.out.printf("'%s'%n", strippedString);

you will see that strip() can recognize the initial and trailing whitespaces of the string and complete its job properly.

New switch Expression in Java 12/13

The switch expression appeared in Java 12 and was further refined in Java 13. But it is a preview language feature. Using this expression, an entire switch block can receive an input value. You can use lambda-style syntax to implement this. Using this feature, you implement a straightforward control flow that is free of “fall-through.”

Note

If you are not aware of a preview feature, you can refer to Q&A 14.1. And you saw the use of a lambda expression in Demonstration 2 in this chapter.

Demonstration 6

The following demonstration shows a simple use of this feature. For case 1 to case 5, it will print a common message (Your version is between 1 and 5), for cases 6 to 12 it will print another common message (Your version is between 6 and 12). If the version is 13, the example will show a different message (which is shown in the output). The example also includes a default case to print about the default version. For simplicity, the myVersion variable is “hard-coded” here. But you can always modify it to accept a different version or consider the user’s input. My focus was on the main feature, so I’m ignoring the other fancy parts.
class SwitchExpressionTest {
 public static void main(String[] args) {
  System.out.println("***Testing Switch expression in Java 13.***");
    System.out.println("Considering versions between 1 to 13.");
    int myVersion=13;//Your version.You can change here.
    testNewSwitchExpressionInJava13(myVersion);
}
public static void testNewSwitchExpressionInJava13(int version){
 switch (version) {
   case  1,2,3,4,5-> System.out.println(" Your version is between 1 and 5.");
   case 6,7,8,9,10,11,12-> System.out.println("Your version is between 6 and 12");
   case 13-> System.out.println("At present, 13 is the latest version. You picked it.");
   default -> System.out.println("You didn't pick between 1 and 13. Default version is: 0");
            }
      }
}
Output:
***Testing Switch expression in Java 13.***
Considering versions between 1 and 13.
At present, 13 is the latest version. You picked it.

Running the Code

In a command-line environment, if the path is not set, to avoid a lot of typing (to mention the javac and java locations), you need to set the path. You can set it in your environment variable, or you can set the path like the following.

Normally, Java13 will be installed in this path. If you use a different path, mention that location only for the path variable. In Chapter 7, you saw how to troubleshoot some common errors in a command-line environment.
C:TestClasschapter14>set path=C:Program FilesJavajdk-13in;
To compile the code in this demonstration, you need to use the –enable-preview option. Here is a sample:
C:TestClasschapter14> javac --enable-preview -source 13 SwitchExpressionTest.java
Here is the immediate output:
Note: SwitchExpressionTest.java uses preview language features.
Note: Recompile with -Xlint:preview for details.
To run the program, you can try the following command, shown in bold:
C:TestClasschapter14>java --enable-preview SwitchExpressionTest

The output is already shown “” above.

Q&A Session

14.10 Why do I need to pass the additional parameters with javac or java when I compile or run this program?

This is still a preview feature. This simply means that, though the overall feature is complete, the final decision to include it in a mainline JDK has yet to be decided. To build confidence in a feature and to get maximum possible feedback, a feature can be tagged like this.

When you use a preview feature, you need to unlock it when you compile the program or run the program. This is why you used the -enable-preview option earlier to compile and run the program in this example (Demonstration6).

Summary

This chapter covered the following:
  • Switch expression from Java12/13

  • New String class methods from Java 11

  • Local variable type inference from Java 10

  • Private methods from Java 9

  • Implementing functional interfaces with lambda expressions from Java 8

  • Try-with resource-from Java 7

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.17.64