Java – Switch Expressions

Java – Switch Expressions ”; Previous Next Using switch expressions, we can return a value and we can use them within statements like other expressions. We can use case L -> label to return a value or using yield, we can return a value from a switch expression. Java 12 introduces expressions to Switch statements and releases them as a preview feature. Java 13 added a new yield construct to return a value from a switch statement. With Java 14, switch expression now is a standard feature. Each case block can return a value using yield statement. In case of enum, default case can be skipped. In other cases, default case is required. Switch Expression Using “case L ->” Labels Java provides a new way to return a value from a switch expression using case L – > notation. Syntax case label1, label2, …, labeln -> expression;|throw-statement;|block Where label1 to labeln are representing the various values to compare and we can use expression, a statement to return a value or throw an expression. Once Java runtime matches any label in the left block to the arrow, it moves to the right block of arrow and executes the expression(statement) and returns the result. Switch Expression Example: Using case L -> Labels In this example, we”ve compared switch expressions vs switch statement. getDayType() method takes a string input and returns the corresponding entry by evaluation switch expression and returning the value. Whereas getDayTypeOldStyle() method uses switch statement to compare each cases, uses break statement to end switch cases and to get a value, we”ve to set value in a variable. package com.tutorialspoint; public class SwitchTester { public static void main(String[] args) { System.out.println(“Old Switch”); System.out.println(getDayTypeOldStyle(“Monday”)); System.out.println(getDayTypeOldStyle(“Saturday”)); System.out.println(getDayTypeOldStyle(“”)); System.out.println(“New Switch”); System.out.println(getDayType(“Monday”)); System.out.println(getDayType(“Saturday”)); System.out.println(getDayType(“”)); } public static String getDayType(String day) { // evaluate switch expression and get a value return switch (day) { case “Monday”, “Tuesday”, “Wednesday”,”Thursday”, “Friday” -> “Weekday”; case “Saturday”, “Sunday” -> “Weekend”; default -> “Invalid day.”; }; } public static String getDayTypeOldStyle(String day) { String result = null; // evaluate relevant cases and get a value into result variable switch (day) { case “Monday”: case “Tuesday”: case “Wednesday”: case “Thursday”: case “Friday”: result = “Weekday”; break; case “Saturday”: case “Sunday”: result = “Weekend”; break; default: result = “Invalid day.”; } return result; } } Output Let us compile and run the above program, this will produce the following result − Old Switch Weekday Weekend Invalid day. New Switch Weekday Weekend Invalid day. Switch Expression Using “case L:” Statements and the yield Statement In java, we can get a value from switch expressio and switch statement using yield statement. yield statement returns the value and finishes the switch execution. Syntax case label1, label2, …, labeln -> expression; yield value; case label1: case labeln: expression; yield value; Switch Expression Example: Using “case L:” Statements and the yield Statement Where label1 to labeln are representing the various values to compare and we can use expression to perform an operation and return value using yield statement. In this example, we”ve compared switch expressions using yield statements. getDayType() method is using a switch expression with yield statement to get the result whereas getDayTypeStyle1() method is using switch cases with colon(:) notation with yield statement to the get the desired result. package com.tutorialspoint; public class SwitchTester { public static void main(String[] args) { System.out.println(“Old Way”); System.out.println(getDayTypeStyle2(“Monday”)); System.out.println(getDayTypeStyle2(“Saturday”)); // System.out.println(getDayTypeStyle2(“”)); System.out.println(“New Way”); System.out.println(getDayType(“Monday”)); System.out.println(getDayType(“Saturday”)); System.out.println(getDayType(“”)); } public static String getDayType(String day) { return switch (day) { // we can use block statements to return a value using yield after // executing other statements case “Monday”, “Tuesday”, “Wednesday”,”Thursday”, “Friday” -> { System.out.println(“In Weekdays”); yield “Weekday”; } case “Saturday”, “Sunday” -> { System.out.println(“In Weekends”); yield “Weekend”; } default -> throw new IllegalStateException(“Invalid day: ” + day); }; } public static String getDayTypeStyle2(String day) { return switch (day) { case “Monday”: case “Tuesday”: case “Wednesday”: case “Thursday”: case “Friday”: yield “Weekday”; case “Saturday”: case “Sunday”: yield “Weekend”; default: throw new IllegalStateException(“Invalid day: ” + day); }; } } Output Let us compile and run the above program, this will produce the following result − Old Way Weekday Weekend New Ways In Weekdays Weekday In Weekends Weekend Exception in thread “main” java.lang.IllegalStateException: Invalid day: at com.tutorialspoint.SwitchTester.getDayType(SwitchTester.java:26) at com.tutorialspoint.SwitchTester.main(SwitchTester.java:13) Print Page Previous Next Advertisements ”;

Java – Microbenchmark

Java – Micro Benchmark ”; Previous Next Java Benchmarking Benchmarking is a technique to check the performance of the application or of a section of application code in terms of throughput, average time taken, etc. In Java benchmarking, we check the performance of application code or of a library being used. This benchmarking helps in identifying any bottleneck in our code in case of heavy load or to identify the performance degradation of the application. Importance of Java Benchmarking Application performance is a very important attribute of any application. Poorly written code can lead to an unresponsive application, and high memory usage which can lead to poor user experience and even render the application unusable. In order to contain such issues, benchmarking an application is of utmost importance. A Java Developer should be able to find issues in an application and fix them using the benchmarking technique which can help identify the sluggish code. Java Benchmarking Techniques There are multiple techniques that developers deploy in order to benchmark the application code, system, library, or any component. Following are a few of the important techniques. Benchmarking Using Start/End Time This technique is easy and applicable on a small set of code, where we get the start time in nanoseconds before calling a code and then after executing the method, we again get the time. Now using the difference of end time and start time gives an idea of how much time the code is taking. This technique is simple but is not reliable as performance can vary based on many factors like garbage collectors in action, and any system process running during that time. // get the start time long startTime = System.nanoTime(); // execute the code to be benchmarked long result = operations.timeTakingProcess(); // get the end time long endTime = System.nanoTime(); // compute the time taken long timeElapsed = endTime – startTime; Example Following example shows a running example to demonstrate the above concept. package com.tutorialspoint; public class Operations { public static void main(String[] args) { Operations operations = new Operations(); // get the start time long startTime = System.nanoTime(); // execute the code to be benchmarked long result = operations.timeTakingProcess(); // get the end time long endTime = System.nanoTime(); // compute the time taken long timeElapsed = endTime – startTime; System.out.println(“Sum of 100,00 natural numbers: ” + result); System.out.println(“Elapsed time: ” + timeElapsed + ” nanoseconds”); } // get the sum of first 100,000 natural numbers public long timeTakingProcess() { long sum = 0; for(int i = 0; i < 100000; i++ ) { sum += i; } return sum; } } Let us compile and run the above program, this will produce the following result − Sum of 100,00 natural numbers: 4999950000 Elapsed time: 1111300 nanoseconds Benchmarking Using Java MicroBenchmark Harness (JMH) Java Microbenchmark Harness (JMH) is a powerful benchmarking API developed by the OpenJDK community to check the performance of a code. It provides a simple annotation-based approach to get benchmark data of a method/class with minimal coding required from the developer”s end. Step 1 − Annotate the class/method to be benchmarked. @Benchmark public long timeTakingProcess() { } Step 2 − Prepare the Benchmark options and run using Benchmark Runner. // prepare the options Options options = new OptionsBuilder() .include(Operations.class.getSimpleName()) // use the class whose method is to be benchmarked .forks(1) // create the fork(s) which will be used to run the iterations .build(); // run the benchmark runner new Runner(options).run(); In order to use benchmarking library, we need to add following dependencies in pom.xml in case of maven project. <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>1.35</version> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>1.35</version> </dependency> Following is the complete code of the pom.xml which is used to run the above benchmarking example. <project xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”> <modelVersion>4.0.0</modelVersion> <groupId>com.tutorialspoint</groupId> <artifactId>test</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>test</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <jmh.version>1.35</jmh.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>${jmh.version}</version> </dependency> <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>${jmh.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> <annotationProcessorPaths> <path> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-generator-annprocess</artifactId> <version>${jmh.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <finalName>benchmarks</finalName> <transformers> <transformer implementation=”org.apache.maven.plugins.shade.resource.ManifestResourceTransformer”> <mainClass>org.openjdk.jmh.Main</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> Example Following is the complete code of the class which is used to run the above benchmarking example. package com.tutorialspoint.test; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; public class Operations { public static void main(String[] args) throws RunnerException { Options options = new OptionsBuilder() .include(Operations.class.getSimpleName()) .forks(1) .build(); new Runner(options).run(); } // get the sum of first 100,000 natural numbers @Benchmark public long timeTakingProcess() { long sum = 0; for(int i = 0; i < 100000; i++ ) { sum += i; } return sum; } } Let us compile and run the above program, this will produce the following result − # JMH version: 1.35 # VM version: JDK 21.0.2, Java HotSpot(TM) 64-Bit Server VM, 21.0.2+13-LTS-58 # VM invoker: C:Program FilesJavajdk-21binjava.exe # VM options: -Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ShowCodeDetailsInExceptionMessages # Blackhole mode: compiler (auto-detected, use -Djmh.blackhole.autoDetect=false to disable) # Warmup: 5 iterations, 10 s each # Measurement: 5 iterations, 10 s each # Timeout: 10 min per iteration # Threads: 1 thread, will synchronize iterations # Benchmark mode: Throughput, ops/time # Benchmark: com.tutorialspoint.test.Operations.timeTakingProcess # Run progress: 0.00% complete, ETA 00:01:40 # Fork: 1 of 1 # Warmup Iteration 1: 33922.775 ops/s # Warmup Iteration 2: 34104.930 ops/s # Warmup Iteration 3: 34519.419 ops/s # Warmup Iteration 4: 34535.636 ops/s # Warmup Iteration 5: 34508.781 ops/s Iteration 1: 34497.252 ops/s Iteration 2: 34338.847 ops/s Iteration 3: 34355.355 ops/s Iteration 4: 34105.801 ops/s Iteration 5: 34104.127 ops/s Result “com.tutorialspoint.test.Operations.timeTakingProcess”: 34280.276 ±(99.9%) 660.293 ops/s [Average] (min, avg, max) = (34104.127, 34280.276, 34497.252), stdev = 171.476 CI (99.9%): [33619.984, 34940.569] (assumes normal distribution) # Run complete. Total time: 00:01:40 REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on why the numbers are the way they are. Use profilers (see -prof, -lprof), design

Java – Comparators

Java – How to Use Comparator? ”; Previous Next Both TreeSet and TreeMap store elements in sorted order. However, it is the comparator that defines precisely what sorted order means. Java Comparator Interface In Java, the Comparator interface is a part of java.util package and it defines the order of the objects of user-defined classes. Methods of Comparator Interface The Comparator interface defines two methods: compare() and equals(). The compare() method, shown here, compares two elements for order − The compare() Method int compare(Object obj1, Object obj2) obj1 and obj2 are the objects to be compared. This method returns zero if the objects are equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned. By overriding compare(), you can alter the way that objects are ordered. For example, to sort in a reverse order, you can create a comparator that reverses the outcome of a comparison. The equals() Method The equals() method, shown here, tests whether an object equals the invoking comparator − boolean equals(Object obj) obj is the object to be tested for equality. The method returns true if obj and the invoking object are both Comparator objects and use the same ordering. Otherwise, it returns false. Overriding equals() is unnecessary, and most simple comparators will not do so. Comparator Interface to Sort a Custom Object In this example, we”re using Comparator interface to sort a custom object Dog based on comparison criterias. Example import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class Dog implements Comparator<Dog>, Comparable<Dog> { private String name; private int age; Dog() { } Dog(String n, int a) { name = n; age = a; } public String getDogName() { return name; } public int getDogAge() { return age; } // Overriding the compareTo method public int compareTo(Dog d) { return (this.name).compareTo(d.name); } // Overriding the compare method to sort the age public int compare(Dog d, Dog d1) { return d.age – d1.age; } @Override public String toString() { return this.name + “,” + this.age; } } public class ComparatorDemo { public static void main(String args[]) { // Takes a list o Dog objects List<Dog> list = new ArrayList<>(); list.add(new Dog(“Shaggy”, 3)); list.add(new Dog(“Lacy”, 2)); list.add(new Dog(“Roger”, 10)); list.add(new Dog(“Tommy”, 4)); list.add(new Dog(“Tammy”, 1)); Collections.sort(list); // Sorts the array list System.out.println(“Sorted by name:”); // printing the sorted list of names System.out.print(list); // Sorts the array list using comparator Collections.sort(list, new Dog()); System.out.println(” “); System.out.println(“Sorted by age:”); // printing the sorted list of ages System.out.print(list); } } Output Sorted by name: [Lacy,2, Roger,10, Shaggy,3, Tammy,1, Tommy,4] Sorted by age: [Tammy,1, Lacy,2, Shaggy,3, Tommy,4, Roger,10] Note − Sorting of the Arrays class is as the same as the Collections. Comparator Interface to Reverse Sort In this example, we”re using Comparator interface to reverse sort the Dog objects. Example 2 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class Dog implements Comparator<Dog>, Comparable<Dog> { private String name; private int age; Dog() { } Dog(String n, int a) { name = n; age = a; } public String getDogName() { return name; } public int getDogAge() { return age; } // Overriding the compareTo method public int compareTo(Dog d) { return (this.name).compareTo(d.name); } // Overriding the compare method to sort the age public int compare(Dog d, Dog d1) { return d.age – d1.age; } @Override public String toString() { return this.name + “,” + this.age; } } public class ComparatorDemo { public static void main(String args[]) { // Takes a list o Dog objects List<Dog> list = new ArrayList<>(); list.add(new Dog(“Shaggy”, 3)); list.add(new Dog(“Lacy”, 2)); list.add(new Dog(“Roger”, 10)); list.add(new Dog(“Tommy”, 4)); list.add(new Dog(“Tammy”, 1)); Collections.sort(list, Collections.reverseOrder()); // Sorts the array list System.out.println(“Sorted by name in reverse order:”); // printing the sorted list of names System.out.print(list); } } Output Sorted by name in reverse order: [Tommy,4, Tammy,1, Shaggy,3, Roger,10, Lacy,2] In this example, we”re using Comparator interface to sort String values in reverse order. Example 3 import java.util.ArrayList; import java.util.Collections; import java.util.List; public class ComparatorDemo { public static void main(String args[]) { // Takes a list o Dog objects List<String> list = new ArrayList<>(); list.add(“Shaggy”); list.add(“Lacy”); list.add(“Roger”); list.add(“Tommy”); list.add(“Tammy”); Collections.sort(list, Collections.reverseOrder()); // Sorts the array list System.out.println(“Sorted by name in reverse order:”); // printing the sorted list of names System.out.print(list); } } Output Sorted by name in reverse order: [Tommy, Tammy, Shaggy, Roger, Lacy] Print Page Previous Next Advertisements ”;

Java – Synchronization

Java – Thread Synchronization ”; Previous Next Need of Thread Synchronization? When we start two or more threads within a program, there may be a situation when multiple threads try to access the same resource and finally they can produce unforeseen result due to concurrency issues. For example, if multiple threads try to write within a same file then they may corrupt the data because one of the threads can override data or while one thread is opening the same file at the same time another thread might be closing the same file. So there is a need to synchronize the action of multiple threads and make sure that only one thread can access the resource at a given point in time. This is implemented using a concept called monitors. Each object in Java is associated with a monitor, which a thread can lock or unlock. Only one thread at a time may hold a lock on a monitor. Thread Synchronization in Java Java programming language provides a very handy way of creating threads and synchronizing their task by using synchronized blocks. You keep shared resources within this block. Following is the general form of the synchronized statement − Syntax synchronized(objectidentifier) { // Access shared variables and other shared resources } Here, the objectidentifier is a reference to an object whose lock associates with the monitor that the synchronized statement represents. Now we are going to see two examples, where we will print a counter using two different threads. When threads are not synchronized, they print counter value which is not in sequence, but when we print counter by putting inside synchronized() block, then it prints counter very much in sequence for both the threads. Multithreading Example without Thread Synchronization Here is a simple example which may or may not print counter value in sequence and every time we run it, it produces a different result based on CPU availability to a thread. Example class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i–) { System.out.println(“Counter — ” + i ); } } catch (Exception e) { System.out.println(“Thread interrupted.”); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { PD.printCount(); System.out.println(“Thread ” + threadName + ” exiting.”); } public void start () { System.out.println(“Starting ” + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo( “Thread – 1 “, PD ); ThreadDemo T2 = new ThreadDemo( “Thread – 2 “, PD ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); } catch ( Exception e) { System.out.println(“Interrupted”); } } } This produces a different result every time you run this program − Output Starting Thread – 1 Starting Thread – 2 Counter — 5 Counter — 4 Counter — 3 Counter — 5 Counter — 2 Counter — 1 Counter — 4 Thread Thread – 1 exiting. Counter — 3 Counter — 2 Counter — 1 Thread Thread – 2 exiting. Multithreading Example with Thread Synchronization Here is the same example which prints counter value in sequence and every time we run it, it produces the same result. Example class PrintDemo { public void printCount() { try { for(int i = 5; i > 0; i–) { System.out.println(“Counter — ” + i ); } } catch (Exception e) { System.out.println(“Thread interrupted.”); } } } class ThreadDemo extends Thread { private Thread t; private String threadName; PrintDemo PD; ThreadDemo( String name, PrintDemo pd) { threadName = name; PD = pd; } public void run() { synchronized(PD) { PD.printCount(); } System.out.println(“Thread ” + threadName + ” exiting.”); } public void start () { System.out.println(“Starting ” + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { PrintDemo PD = new PrintDemo(); ThreadDemo T1 = new ThreadDemo( “Thread – 1 “, PD ); ThreadDemo T2 = new ThreadDemo( “Thread – 2 “, PD ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); } catch ( Exception e) { System.out.println(“Interrupted”); } } } This produces the same result every time you run this program − Output Starting Thread – 1 Starting Thread – 2 Counter — 5 Counter — 4 Counter — 3 Counter — 2 Counter — 1 Thread Thread – 1 exiting. Counter — 5 Counter — 4 Counter — 3 Counter — 2 Counter — 1 Thread Thread – 2 exiting. java_multithreading.htm Print Page Previous Next Advertisements ”;

Java – Null Pointer Exception

Java – Null Pointer Exception ”; Previous Next In Java 14, a new feature was introduced as helpful NullPointerException. It was a preview feature then and later became the standard part of the JDK. The motivation behind this enhancement was to enrich the NullPointerException with more details as a traditional NullPointerException only gave details of filename, method, and the line number where a NullPointerException occurred. Traditional Null Pointer Exception in Java Before Java 14 NullPointerException enhancement, following code will show a NullPointerException message as shown below: // Create an employee without department Employee emp = new Employee(1,”Robert”,null); // get the name of the dept // as name is null, this code will throw a null pointer exception String dept = emp.getDept().getName(); If this code snippet is used to run, this will produce similar result − Exception in thread “main” java.lang.NullPointerException at com.tutorialspoint.Tester.main(Tester.java:10) New Informative Null Pointer Exception in Java During debugging, such a error message is not useful. And with multiple nesting level, it becomes more difficult to check which field being null is causing the issue. Java 14 catered to this need. It provided an option to return a more helpful message like below in such case: Exception in thread “main” java.lang.NullPointerException: Cannot invoke “com.tutorialspoint.Department.getName()” because the return value of “com.tutorialspoint.Employee.getDept()” is null at com.tutorialspoint.Tester.main(Tester.java:10) Here we can see, that a more information message is getting printed to assist in debugging the issue that getDept() is null. In order to enable this feature in Java 14, we”ve to run the java code using following flag. -XX:+ShowCodeDetailsInExceptionMessages Now with Java 20, this flag is not needed anymore. Helpful NullPointerException for Null Objects In this example, we”re showcasing the above learnt concept. It is a very useful feature to debug the issues caused due to null references. Here we”ve created two classes Employee and Department. In main method, we”ve created the object of Employee class but department is passed as null. Then we”ve tried to get the department name of the employee which results in a NullPointerException. In output we can see the informative null pointer exception raised by the JVM. Example package com.tutorialspoint; import java.util.List; public class Tester { public static void main(String[] args) { // declare an employee without department Employee emp = new Employee(1,”Robert”,null); // get department name of null department will // throw a NullPointerException String dept = emp.getDept().getName(); System.out.println(dept); } } class Employee { int id; String name; Department dept; Employee (int id, String name, Department dept){ this.id = id; this.name = name; this.dept = dept; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } } class Department { int id; String name; List<Employee> employees; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } } Output Let us compile and run the above program, this will produce the following result − Exception in thread “main” java.lang.NullPointerException: Cannot invoke “com.tutorialspoint.Department.getName()” because the return value of “com.tutorialspoint.Employee.getDept()” is null at com.tutorialspoint.Tester.main(Tester.java:10) Informative NullPointerException – Local Null Variable Similar to object reference, local variable can be null. In Java 14, if a null local variable is used, then JVM prints the name of variable as <local> as shown below: String name = null; System.out.println(“Length: ” + name.length() ); If this code snippet is used to run, this will produce similar result − Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.length()” because “<local1>” is null at com.tutorialspoint.Tester.main(Tester.java:8) In order to print the name of the local variable, we had to use following flag while running the program. -g Using this flag results in following output. Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.length()” because “name” is null at com.tutorialspoint.Tester.main(Tester.java:8) In Java 20 onwards, this flag is not needed anymore. See the complete example below: Helpful NullPointerException for Null Local Variable In this example, we”re showcasing the above learnt concept to debug null local references. Here we”ve created a local variable name and we”re trying to the get the length of null string variable which will cause the NullPointerException. In output we can see the informative null pointer exception raised by the JVM with the actual name of the null variable. Example package com.tutorialspoint; public class Tester { public static void main(String[] args) { String name = null; // accessing property of null local variable // will cause a NullPointerException System.out.println(“Length: ” + name.length() ); } } Output Let us compile and run the above program, this will produce the following result − Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.length()” because “name” is null at com.tutorialspoint.Tester.main(Tester.java:8) Print Page Previous Next Advertisements ”;

Java – Multi-Release Jar Files

Java – Multi-Release Jar Files ”; Previous Next Multi-release JAR feature was introduced in Java 9. It allows to use of multiple versions of a class pertaining to multiple versions of Java. For example, many third-party libraries or frameworks use Java. As Java as a language is continuously evolving and with every major release, many new features are getting added to the language. As third-party libraries/frameworks have to rewrite their code base in order to accommodate new features, teams are highly reluctant to use the new features. It acts as a hindrance to them to move to the new versions of Java. In order to counter this problem of maintenance of multiple source codes of the same file or platform-specific version of a file, the Multirelease JAR feature was introduced. Consider the following example: A typical jar file has all the classes at the root level. jar root – Calculator.class – Util.class – Math.class – Service.class If we”ve Java 9 feature specific Util class then that jar cannot be used in JRE 8 or lower. In multi-release Jar, the format has been enhanced to have different versions of Java classes or resources that can be maintained and used as per the platform. In JAR, a file MANIFEST.MF file has an entry Multi-Release: true in its main section. META-INF directory also contains a versions subdirectory whose subdirectories (starting with 9 for Java 9 ) store version-specific classes and resource files. Using MANIFEST.MF, we can specific Java 9 or higher version-specific classes in separate locations as shown below: Java Multi-Release Jar Files Directory Structure jar root – Calculator.class – Util.class – Math.class – Service.class META-INF – versions – 9 – Util.class – Math.class – 10 – Util.class – Math.class Now if JRE is not support Multi-release jar, then it will choose the root level classes to load and execute otherwise, version specific classes will be loaded. For example, if above jar is used in Java 8, then root level Util.class will be used. If same jar is executed by Java 9, then java 9 version specific class will be picked and so on. This way, third party libraries/frameworks can support new features without changing their source codes which was written targeting the lower versions. Creating and Using Multi-Release Jar Files in Java In this example, we”ll be creating and using a multi-release jar to have two versions of Tester.java file, one for jdk 7 and one for jdk 9 and run it on different jdk versions. The following are the steps for creating and using multi-release jar files in Java – Step 1: Create Java 7 Specific Java Class Let”s create a Java class that may have Java 7 specific code and features which is not available prior to Java 9. In this example, we”re simply printing a message just to showcase the usage of this feature. Create a folder c:/test/java7/com/tutorialspoint. Create Tester.java with following content − Tester.java This is a simple code where we”re printing a Java 7 specific message when program is executed. package com.tutorialspoint; public class Tester { public static void main(String[] args) { System.out.println(“Inside java 7″); } } Step 2: Create Java 9 Specific Java Class Let”s create a Java class that may have code specific to Java 9 enhancements and features which is not available prior to Java 9. In this example, we”re simply printing a message just to showcase the usage of this feature. Create a folder c:/test/java9/com/tutorialspoint. Create Tester.java with following content − Tester.java This is also similar code as above where we”re printing a Java 9 specific message when program is executed. package com.tutorialspoint; public class Tester { public static void main(String[] args) { System.out.println(“Inside java 9″); } } In order to use multi-release jar feature, we must ensure that signature of both class should be same. Public interface like method signatures should be same in both the classes. Step 3: Compile with Target Versions C:test > javac –release 9 java9/com/tutorialspoint/Tester.java C:JAVA > javac –release 7 java7/com/tutorialspoint/Tester.java Step 4: Create a Multi-Release JAR C:JAVA > jar -c -f test.jar -C java7 . –release 9 -C java9. Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java, multiple resources with same name Step 5: Run the JAR with JDK 7 C:JAVA > java -cp test.jar com.tutorialspoint.Tester Inside Java 7 Step 6: Run the JAR JDK 9 C:JAVA > java -cp test.jar com.tutorialspoint.Tester Inside Java 9 Conclusion We can see, that with multi-release Jar feature, we can create multiple version of a class without having backwards compatibility issues. We”ve showcased that same command can be used to execute a class. Based on the JRE version listed in META-INF file, the corresponding class is picked. In case of lower JRE version which is not supporting Multi-Release jar, the root level classes are picked instead of version specific classes. And lastly, the signature of public methods of the versioned classes should be same so this functionality can work perfectly. Print Page Previous Next Advertisements ”;

Java – Record Classes

Java – Record ”; Previous Next In Java 14, an exciting feature record was introduced as a preview feature. The record feature helps in creating immutable data objects. In the Java 15 version, record types were enhanced further. In Java 14 and 15, in order to use a record, a flag –enable-preview has to be passed. From Java 16 onwards, this flag is not required as the record is a standard part of JDK. Purpose of a Java Record The prime purpose of a record is to create a data object or a POJO which is used to carry data in application program flow. In a multi-tier program, Domain/Model objects store the data captured from the data source and then these model objects are passed further to the application/UI layer to process the data and vice versa where UI/Application stores data in data objects and then pass these objects to Data layer to populate data sources. As these data objects contain a lot of fields, developers are required to write a lot of setter/getter methods, parameterized constructors, overridden equals methods, and hashcode methods. In such a scenario, the record comes to the rescue as it provides most of the boilerplate code and the developer can focus on required functionalities only. Features of Java Record Following are the features of the record which makes the record an exciting feature: Record objects have an implicit constructor with all the parameters as field variables. Record objects have implicit field-getter methods for each field variable. Record objects have implicit field setter methods for each field variable. Record objects have an implicit sensible implementation of hashCode(), equals(), and toString() methods. With Java 15, native methods cannot be declared in records. With Java 15, implicit fields of record are not final and modification using reflection will throw IllegalAccessException. Example Without Using Java Record Let”s create a simple program without using record where we”re creating a Student object and printing its details. The Student has three properties, id, name and className. In order to create a student, we”ve create a parameterized constructor, setter, getter methods, equals and hashcode methods. Thus our Student class is completed with nearly 60+ lines. package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student1 = new Student(1, “Mahesh”, “XII”); Student student2 = new Student(2, “Sudhir”, “XII”); // print the students System.out.println(student1); System.out.println(student2); // check if students are same boolean result = student1.equals(student2); System.out.println(result); // check if students are same result = student1.equals(student1); System.out.println(result); // get the hashcode System.out.println(student1.hashCode()); System.out.println(student2.hashCode()); } } class Student{ private int id; private String name; private String className; Student(int id, String name, String className){ this.id = id; this.name = name; this.className = className; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } @Override public String toString() { return “Student[id: ” + id + “, name: ” + name + “, class: ” + className + “]”; } @Override public boolean equals(Object obj) { if(obj == null || !(obj instanceof Student) ) { return false; } Student s = (Student)obj; return this.name.equals(s.name) && this.id == s.id && this.className.equals(s.className); } @Override public int hashCode() { int prime = 19; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((className == null) ? 0 : className.hashCode()); result = prime * result + id; return result; } } Let us compile and run the above program, this will produce the following result − Student[id: 1, name: Mahesh, class: XII] Student[id: 2, name: Sudhir, class: XII] false true 371251946 288252156 Example Using Java Record Let”s recreate above program using record where we”re creating a Student object as record and printing its details. The Student has three properties, id, name and className. Here you can see the difference, the complete Student class is replaced with one line of code as Student record. package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student1 = new Student(1, “Mahesh”, “XII”); Student student2 = new Student(2, “Sudhir”, “XII”); // print the students System.out.println(student1); System.out.println(student2); // check if students are same boolean result = student1.equals(student2); System.out.println(result); // check if students are same result = student1.equals(student1); System.out.println(result); // get the hashcode System.out.println(student1.hashCode()); System.out.println(student2.hashCode()); } } record Student(int id, String name, String className) {} Let us compile and run the above program, this will produce the following result − Student[id: 1, name: Mahesh, class: XII] Student[id: 2, name: Sudhir, class: XII] false true 371251946 288252156 We can add custom methods in records as well. But generally it is not required. Java Record for Sealed Interfaces As records are final by default and can extend interfaces. We can define sealed interfaces and let records implement them for better code management. Example: Use of Java Record for Sealed Interfaces Consider the following example − package com.tutorialspoint; public class Tester { public static void main(String[] args) { Person employee = new Employee(23, “Robert”); System.out.println(employee.id()); System.out.println(employee.name()); } } sealed interface Person permits Employee, Manager { int id(); String name(); } record Employee(int id, String name) implements Person {} record Manager(int id, String name) implements Person {} Let us compile and run the above program, this will produce the following result − 23 Robert Overriding Methods of Java Records We can override a record method implementation easily and provide our own implementation. Example: Override Java Record Methods Consider the following example − package com.tutorialspoint; public class Tester { public static void main(String args[]) { // create student objects Student student = new Student(1, “Mahesh”, “XII”); System.out.println(student); } } record Student(int id, String name, String className) { public String toString() { return “Id: ” + id + “, Name: ” + name +

Java – Enum Constructor

Java – Enum Constructor ”; Previous Next Java enum is a special kind of class that represents a group of pre-defined constant values and can be used in switch expressions for comparison, to be used as constants in application code. By default, an enum does not require any constructor and its default value is the same as its declaration. Consider the following example: enum WEEKDAY { MONDAY, TUESDAY, WEDNESDAY, THRUSDAY, FRIDAY, SATURDAY, SUNDAY } If we print the any of the value of above enum, it will print the same string as declared. System.out.println(WEEKDAY.MONDAY); It will print the result as shown below: MONDAY Use of Enum Constructor Now in case, we want to assign a default value to enum, we can create a enum constructor as shown below: enum WEEKDAY { MONDAY(“Day 1″); private final String description; WEEKDAY(String description) { this.description = description; } } In this case, we”re assigning a default description to the enum using the constructor. Scope of Enum Constructor As enum is a special class, an enum constructor can only have private or package-private modifier. Setting a public idenifier to enum constructor will attract a compile time error. enum WEEKDAY { MONDAY(“Day 1”); private final String description; // compiler error: illegal modifier, only private is permitted. public WEEKDAY(String description) { this.description = description; } } Following are valid declarations of enum constructor Enum with Private Constructor We can create a private constructor for an enum as shown below. enum WEEKDAY { MONDAY(“Day 1″); private final String description; // valid declaration private WEEKDAY(String description) { this.description = description; } } Example In this example, we”ve created an enum WEEKDAY with a private constructor. Using private constructor, we”re setting the value of enum description using its constructor. package com.tutorialspoint; // create the enum enum WEEKDAY { // create values of enum MONDAY(“Day 1”), TUESDAY(“Day 2”), WEDNESDAY(“Day 3”), THRUSDAY(“Day 4”), FRIDAY(“Day 5”), SATURDAY(“Day 6”), SUNDAY(“Day 7”); private final String description; // private construtor to set default value private WEEKDAY(String description) { this.description = description; } // getter method to get the description public String getDescription () { return this.description; } } public class Tester { public static void main(String[] args) { System.out.println(WEEKDAY.MONDAY.getDescription()); System.out.println(WEEKDAY.MONDAY); } } Let us compile and run the above program, this will produce the following result − Day 1 MONDAY Enum with Package-private Constructor We can create a package private constructor for an enum as shown below. enum WEEKDAY { MONDAY(“Day 1″); private final String description; // valid declaration WEEKDAY(String description) { this.description = description; } } Example In this example, we”ve created an enum WEEKDAY with a package-private constructor as no modifier is passed. Using this constructor, we”re setting the value of enum description using its constructor. package com.tutorialspoint; // create the enum enum WEEKDAY { // create values of enum MONDAY(“Day 1”), TUESDAY(“Day 2”), WEDNESDAY(“Day 3”), THRUSDAY(“Day 4”), FRIDAY(“Day 5”), SATURDAY(“Day 6”), SUNDAY(“Day 7″); private final String description; // private construtor to set default value WEEKDAY(String description) { this.description = description; } // getter method to get the description public String getDescription () { return this.description; } } public class Tester { public static void main(String[] args) { System.out.println(WEEKDAY.MONDAY.getDescription()); System.out.println(WEEKDAY.MONDAY); } } Let us compile and run the above program, this will produce the following result − Day 1 MONDAY Print Page Previous Next Advertisements ”;

Java – Collection Factory Methods

Java – Collection Factory Methods ”; Previous Next Factory Methods for Collection In Java 9, collections were enhanced to have few new methods to create immutable list in an easy and concise way. These new factory methods were added to List, Set, and Map interfaces to create immutable instances. These factory methods are mainly convenience factory methods in order to create a collection in less verbose and in concise way. Syntax Before Java 9, following syntax was used to create a immutable list. List unmodifiableList = Collections.unmodifiableList(arrayList); Where arrayList is a mutable list instance. So we are required to create a list and then using unmodifiableList() we get an immutable instance from which we cannot add/remove an element. Factory Methods of List Interface Now from Java 9, following methods can be used to create a immutable list. static <E> List<E> of(); static <E> List<E> of(E e1); static <E> List<E> of(E… elements) static <E> List<E> of(E e1, E e2); static <E> List<E> of(E e1, E e2, E e3); static <E> List<E> of(E e1, E e2, E e3, E e4); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8,E e9); static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8,E e9, E e10); Syntax So from Java 9 onwards, following syntax can be used to create a immutable list. of(E… elements) method can be used to have more than 10 elements in an immutable list. List<String> unmodifiableList = List.of(“A”, “B”, “C”); Example of List Interface Factory Methods Before Java 9 Here, we are creating unmodifiable list before Java 9. package com.tutorialspoint; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Tester { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add(“A”); list.add(“B”); list.add(“C”); list = Collections.unmodifiableList(list); System.out.println(list); } } Let us compile and run the above program, this will produce the following result − [A, B, C] Example of List Interface Factory Methods in Java 9 Here, we are creating unmodifiable list in Java 9. package com.tutorialspoint; import java.util.List; public class Tester { public static void main(String[] args){ List<String> list = List.of(“A”,”B”,”C”); System.out.println(list); } } Let us compile and run the above program, this will produce the following result − [A, B, C] Factory Methods of Set Interface On similar pattern, Set interface is having these new methods to create a unmodifiable Set to get an instance of a set from which we cannot add/remove an element. static <E> Set<E> of(); static <E> Set<E> of(E e1); static <E> Set<E> of(E… elements) static <E> Set<E> of(E e1, E e2); static <E> Set<E> of(E e1, E e2, E e3); static <E> Set<E> of(E e1, E e2, E e3, E e4); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8,E e9); static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8,E e9, E e10); Syntax So from Java 9 onwards, following syntax can be used to create a immutable set. of(E… elements) method can be used to have more than 10 elements in an immutable set. Set<String> unmodifiableSet = Set.of(“A”, “B”, “C”); Example of Set Interface Factory Methods Before Java 9 Here, we are creating unmodifiable set before Java 9. package com.tutorialspoint; import java.util.Collections; import java.util.HashSet; import java.util.Set; public class Tester { public static void main(String[] args){ Set<String> set = new HashSet<>(); set.add(“A”); set.add(“B”); set.add(“C”); set = Collections.unmodifiableSet(set); System.out.println(set); } } Let us compile and run the above program, this will produce the following result − [A, B, C] Example of Set Interface Factory Methods in Java 9 Here, we are creating unmodifiable set in Java 9. package com.tutorialspoint; import java.util.Set; public class Tester { public static void main(String[] args){ Set<String> set = Set.of(“A”,”B”,”C”); System.out.println(set); } } Let us compile and run the above program, this will produce the following result − [A, B, C] Factory Methods of Map Interface In case of Map interface, we”ve ofEntries(…) can be used to accept var args parameter other than of() methods as shown below. static <K,V> Map<K,V> of(); static <K,V> Map<K,V> of(K k1, V v1); static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>… entries) static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7); static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8);

Java – Autoboxing and Unboxing

Java – Autoboxing and Unboxing ”; Previous Next Java Autoboxing Autoboxing is a technique used by Java compiler to automatically convert a primitive value to its wrapper counterpart. For example, when an int value is assigned to an Integer wrapper object, compiler automatically converts the int value to the object without any need to explicitly cast the int value or by calling any method to convert int to Integer object. Autoboxing is also known as boxing. // Autoboxing Integer obj = 10; // Explicit casting Integer obj2 = Integer.valueOf(10) In both cases, the wrapper objects are initialized with an int value. In first case, autoboxing is playing role and second case, we”re explicitly casting int value to Integer wrapper object. Compiler uses autoboxing in following scenarios − If a primitive value is passed as an argument to a function which is expecting a wrapper class object. If a primitive value is assigned to a variable of the type of wrapper class. Example of Autoboxing in Java In this example, we”ve created a list of Integer as List can contain only objects. Now while adding the item to this list, we”re not creating any Integer object but we”re just passing the primitive int values. Java compiler automatically handles the conversion and program compiles successfully. We”ve used another case of assigning a char primitive value to Character object which works as well. package com.tutorialspoint; import java.util.ArrayList; import java.util.List; public class Tester { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for(int i = 0; i< 10; i++){ // autoboxing by passing as an argument // int value is converted to Integer // by compiler during compilation list.add(i); } System.out.println(list); char c = ”a”; //autoboxing by assigning a char to Character object Character ch = c; System.out.println(ch); } } Output Let us compile and run the above program without any command line argument, this will produce the following result − [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] a Java Unboxing Unboxing is reverse of autoboxing. Unboxing is used by Java compiler to convert a wrapper object to its primitive counterpart. For example when an Integer object is passed to a method as argument but the method called is expecting an int variable, then compiler automatically converts the Integer object to int value and then pass it to the mathod called. Similarly Java compilier unboxes the wrapper value if it is assigned to a primitive variable. Thus we are not required to explicitly get the int value from the wrapper object. Integer obj = Integer.valueOf(10); // Unboxing int i = obj; // Explicit value deduction i = obj.intValue(); In both cases, the primitive values are initialized with an int value. In first case, unboxing is playing role and second case, we”re explicitly getting int value from an Integer wrapper object. Compiler uses unboxing in following scenarios − If a wrapper class object is passed as an argument to a function which is expecting a primitive value. If a wrapper class object is assigned to a variable of primitive type. Example of Unboxing in Java In this example, we”ve created an Integer object and initilized it with a value of 10. This object is passed to abs() method which is expecting an int, a primitive variable. Java compiler automatically handles the conversion and program compiles successfully. We”ve used another case of assigning a Integer object to int variable which works as well. package com.tutorialspoint; public class Tester { public static void main(String[] args) { Integer integer = Integer.valueOf(-10); // unboxing by passing as an argument // Integer object is converted to int // by compiler during compilation int i = abs(integer); System.out.println(i); //unboxing by assigning an Integer object to int variable int j = integer; System.out.println(j); } private static int abs(int i){ return (i < 0)? -i: i; } } Output Let us compile and run the above program without any command line argument, this will produce the following result − 10 -10 Mapping of Primitive and Wrapper Objects Sr. No. Primitive Wrapper method to get value 1 byte Byte byteValue() 2 short Short shortValue() 3 int Integer intValue() 4 long Long longValue() 5 float Float floatValue() 6 double Double doubleValue() 7 char Character charValue() 8 boolean Boolean booleanValue() Print Page Previous Next Advertisements ”;