dcsimg
November 13, 2019
Hot Topics:

Using JShell in Java 9 in NetBeans 9.0, Part 4

  • December 28, 2018
  • By Deepak Vohra
  • Send Email »
  • More Articles »

JShell is a new feature in Java 9 to facilitate running code snippets. JShell code snippets are precisely the same as Java source code in a file for an application. As discussed in an earlier article, "Using JShell in Java 9 in NetBeans 9.0, Part 3," JShell does not allow several modifiers—including default, access, synchronized, public, private, and protected—that are supported in a source code file. JShell is designed mainly for testing and debugging Java code and not for running complete applications. In this continuation article, we shall running snippets for classes, interfaces, and arrays. We have used NetBeans 9 as in the earlier articles. We shall also discuss unchecked exceptions. This article has the following sections:

Using Classes

In this section, we shall discuss running code snippets for classes. Declare a simple class C as follows.

[1]-> class C {
}
|  created class C

Class C gets created. Unlike a method that may be invoked directly, a class must first be instantiated as follows.

[3]-> new C()
|  $1 ==> C@64485a47

A new instance of class C, $1 gets created. As with method declarations, class declarations are modifiable by re-declaring the class. A class may implement an interface using implements. As an example, declare an interface I.

[1]-> interface I{}
|  created interface I

Create class C to implement interface I.

[3]-> class C implements I{}
|  replaced class C
[4]->

Class C, created previously, gets replaced.

A class declaration in JShell does not have the concept of an application as a Java class declared in a file would have. A Java class in a file with the public static void main(String[] argv) method is a Java application. The public static void main(String[] argv) method may be added in JShell but is just another code snippet. Create a class Hello that includes the method public static void main(String[] argv).

[1]-> class Hello{
   public static void main(String[] argv){System.out.println
      (argv[0]+argv[1]);}
}
|  created class Hello
[2]->

The main(String[]) method is a static method and is defined for the class rather than an instance of a class. Create a String[] array to supply to the main(String[]) method.

String[] strArray={"Hello"," JShell"};

Invoke the main(String[]) method with the String[] as an arg.

Hello.main(strArray)

A Hello JShell message gets output, as shown in Figure 1.

Invoking static method in a class
Figure 1: Invoking static method in a class

Modifying a Class

A class may be modified as needed by modifying or deleting any of its method declarations or adding new methods. Re-declare class Hello without the main(String[]) method and the class gets replaced.

[4]-> class Hello{
}
|  replaced class Hello
[5]->

Re-add the main(String[]) method but with a slightly different System.out.println statement. Class Hello again gets replaced.

[5]-> class Hello{
   public static void main(String[] argv)
      {System.out.println(argv[0]);}
}
|  replaced class Hello
[5]->

Invoke the static method main(String[]) with Hello.main(strArray) for a different output, as shown in Figure 2.

Invoking a Variation of method main
Figure 2: Invoking a Variation of method main

The provision to replace a class is useful when developing a class. One method may be added at a time and class tested. As an example, add a second method hello(String). Again, class Hello gets replaced.

[9]-> class Hello{
   void  main(String[] argv){System.out.println(argv[0]);}
   String hello(String name){return name;}
}
|  replaced class Hello

The method hello(String) added, being an instance method, would need a class instance to invoke. Create a class instance.

[10]-> new Hello()
|  $2 ==> Hello@4516af24

Invoke method hello(String) using class instance $2.

[11]-> $2.hello("John")
|  $6 ==> "John"

Listing Classes

A Java class is a type. An interface is also a type. All types defined in the JShell session are listed with the /types command. Define a few classes and interfaces.

[4]-> [1]-> class C{}
|  created class C
[2]-> class D{}
|  created class D
[3]-> class B{}
|  created class B
[4]-> interface I{}
|  created interface I
[5]-> interface J{}
|  created interface J

Run the /types command and all the classes and interfaces get listed.

[6]-> /types
|    class C
|    class D
|    class B
|    interface I
|    interface J

Using Class Constructors

The no-arg class is implicitly defined in a class if it does not define any constructors with args. We had previously instantiated a class C that did not declare any constructors explicitly with new C(). The no-arg constructor may be defined explicitly.

Next, create a class Hello that declares a class constructor. The constructor has one parameter of type String. The constructor may be declared with the public modifier and is implicitly public if not set to public.

[6]->
class Hello{
   String name;
   public Hello(String name){this.name=name;}
   void hello(){System.out.println("Hello "+name);}
}

Create an instance of class Hello.

Hello hello=new Hello("John")

Invoke the instance method hello() to output a message, as shown in Figure 3.

Using a Class with a Constructor
Figure 3: Using a Class with a Constructor

Extending a Class

A class may be extended with extends just as in a Java source code file. As an example, create class D that declares a variable name of type tt>String, a  no-arg constructor and a method hello(String). The hello(String) method outputs a "Hello" message using the name arg supplied.

class D{
   String name="Michael";
   public D(){}
   void hello(String name){System.out.println("Hello "+name);}
}

Create a class C that extends class C and declares the hello() method, which does not override class D's hello(String) method and parameters are different. The hello() method invokes a field name, which is inherited from class D.

class C extends D{
   void hello(){System.out.println("Hello "+name);}
}

Instantiate class C and invoke the hello() method.

new C().hello()

A "Hello" message gets output, as shown in Figure 4. The name field value set in class D is used.

Extending a Class
Figure 4: Extending a Class

If we invoked the hello(String) method that class C inherits from class D, we would get a different output, as shown in Figure 5.

Invoking an Inherited Method from an Extended Class
Figure 5: Invoking an Inherited Method from an Extended Class

Overriding a Method

A class may override a method inherited from an extended class by providing its own method definition. Create a class D that declares a field name and a method hello().

class D{
   String name="Michael";
   void hello(){System.out.println("Hello "+name);}
}

Declare a class C that extends class D and overrides the hello() method. Class C also hides the field name.

class C extends D{
   String name="John";
   void hello(){System.out.println("Hello "+name);
}

Create an instance of class C and invoke method hello().

new C().hello()

The hello() method from class C gets invoked because it overrides the method from class D. The field name in class C hides the field name in class D. The message output is shown in Figure 6.

Overriding a Method
Figure 6: Overriding a Method

If class C does not hide field name from class D, the name field in class D is used, as shown in Figure 7.

Accessing Field from Extended Class
Figure 7: Accessing Field from Extended Class

A class C object is an instance of class D because it extends class D. Run the following statement to find if an instance of class C is also an instance of class D.

new C() instanceof D

A value of true verifies an instance of class C is also an instance of class D, as shown in Figure 8.

Verifying if an Instance of Class C is also an instance of class D
Figure 8: Verifying if an Instance of Class C is also an instance of class D

Because an instance of class C is also an instance of class D, it may be cast to D as follows:

D d=(D)(new C());

Subsequently, access field name for object d of type D.

d.name;

And, invoke method hello() for object d of type D.

d.hello();

The field value output is from class D because d is an object of type D, as shown in Figure 9. The method hello() invoked is from class C.

Casting an Object of type C to D
Figure 9: Casting an Object of type C to D

Using Interfaces

In this section, we shall run some snippets for interfaces in JShell. An existing class could be modified to implement an interface. Create class C.

[1]-> class C{}
|  created class C

Create an interface I that defines a method hello().

[2]-> interface I {
   String hello();
}
|  created interface I

Re-declare class C to implement interface I. Class C provides implementation for method hello().

[3]-> class C implements I{
   public String hello(){
      return "Hello JShell";
   }
}
|  replaced class C

Create an instance of class C.

[4]-> new C()
|  $1 ==> C@25bbf683

Using the class instance variable, invoke method hello() and the method output gets displayed.

[5]-> $1.hello()
|  $2 ==> "Hello JShell"
[6]->

Because methods in an interface are implicitly public while methods in a class are not a method, implementation in class C must be declared with the public access modifier. If not declared public, an error message is output because not specifying a public access modifier defaults to a weaker access modifier, which is not permitted when implementing an interface.

[3]-> class C implements I{
   String hello(){
      return "Hello JShell";
   }
}
|  Error:
|  hello() in C cannot implement hello() in I
|    attempting to assign weaker access privileges; was public
|      String hello(){
|      ^--------------...

Using a Default Implementation for a Method

As of Java 8, an interface method may provide a default implementation for a method by using keyword default. Declare an interface that provides a default implementation for method hello() using the default keyword.

[1]-> interface I {
   default  String hello(){
      return "Hello JShell";
   }
}
|  created interface I

Declare a class C that implements interface I.

[2]-> class C implements I{
}
|  created class C

Create an instance of class C and invoke method hello(). The method from the default implementation in interface I gets output.

[3]-> new C().hello();
|  $1 ==> "Hello JShell"

Declaring an Interface Method to be Static

Since Java 8, Interface methods may be declared static. Create an interface I that declares a static method.

[1]-> interface I {
   static String hello(){
      return "Hello JShell";
   }
}
|  created interface I

Invoke the static method by using interface I.

[2]-> I.hello()
|  $1 ==> "Hello JShell"

A class cannot be declared final and, if the final modifier is used, it is ignored.

[5]-> [1]-> final class C{}
|  Warning:
|  Modifier 'final' not permitted in top-level declarations,
|  ignored
|  final class C{}
|  ^---^
|  created class C

Using Arrays

In this section, we shall run some code snippets for arrays. Declaring, instantiating, and accessing arrays is no different than in a Java source code file-based application. As an example, declare an array of type String[]. Array is initialized to null.

[1]-> String[] strArray;
|  strArray ==> null

Allocate memory to the array. Array size, once set, cannot be modified. Array elements are initialized to null.

[2]-> strArray =new String[3];
|  strArray ==> String[3] { null, null, null }

Initialize the array elements using the array indices.

[3]-> strArray[0]="A";
strArray[1]="B";
strArray[2]="C";
|  $4 ==> "A"
|  $5 ==> "B"
|  $6 ==> "C"

Output the array length and the element at index 1.

[6]-> strArray.length;
strArray[1];
|  $9 ==> 3
|  $10 ==> "B"

The array length is output as 3. Element at index 1 is "B". An array may be initialized when declared as follows.

[1]-> String[] strArray={"A","B","C"};
|  strArray ==> String[3] { "A", "B", "C" }

Output the array length.

[2]-> strArray.length;
|  $1 ==> 3

Output the element at index 0.

[3]-> strArray[0];
|  $4 ==> "A"
[4]->

A multi-dimensional array may be declared just as in a Java application. Create a three-dimensional array of type String[][][] and initialize the array.

[1]-> String[][][] strArray={{{"A","B","C"},{"AA","AB","AC"}},
   {{"B","C","A"},{"BB","BC","BA"}},{{"C","A","B"},
   {"CC","CA","CB"}}};
|  strArray ==> String[3][][] { String[2][] { String[3]
|     { "A", "B", "C" }, String[3] { "AA", ...

Output the array length.

[2]-> strArray.length;
|  $1 ==> 3

Output the length of array at index 0.

[3]-> strArray[0].length;
|  $4 ==> 2

Output the length of array at index 1 within array at index 0.

[4]-> strArray[0][1].length;
|  $6 ==> 3

Output the array at index 0.

[5]-> strArray[0]
|  $10 ==> String[2][] { String[3] { "A", "B", "C" },
|     String[3] { "AA", "AB", "AC" } }

Output the array at index 1 within array at index 0.

strArray[0][1]
|  $11 ==> String[3] { "AA", "AB", "AC" }

Output the element at index 0 in array at index 1 within array at index 0.

strArray[0][1][0]
|  $12 ==> "AA"
[8]->

Using Unchecked Exceptions

JShell throws unchecked exceptions at runtime. As an example, if a variable of type String that has been initialized to its default value null is accessed. java.lang.NullPointerException is thrown.

[1]-> String str;
|  str ==> null
[2]-> str.length();
|  java.lang.NullPointerException thrown:
|     at (#2:1)
[3]->

As another example, if an array index outside an array's size is accessed, java.lang.ArrayIndexOutOfBoundsException is thrown.

[4]->
String[] str={"A","B","C"};
|  str ==> String[3] { "A", "B", "C" }
[5]-> str[3];
|  java.lang.ArrayIndexOutOfBoundsException thrown: 3
|     at (

If a method that defines division by zero is invoked, java.lang.ArithmeticException is thrown.

[1]-> int average(int i,int j){
   return (i+j)/0;
}
|  created method average(int,int)
[2]-> average(2,4)
|  java.lang.ArithmeticException thrown: / by zero
|     at average (#1:2)
|     at (#2:1)
[3]->

Conclusion

In these first four articles, we discussed running code snippets for variables, statements, methods, classes, interfaces, and arrays. JShell is designed to run only code snippets and as such some of the features are different than when running a complete Java application from a source code file. In two more articles, we shall explore some other features of JShell.







Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.


Thanks for your registration, follow us on our social networks to keep up-to-date