- Java - Home
- Java - Overview
- Java - History
- Java - Features
- Java Vs. C++
- JVM - Java Virtual Machine
- Java - JDK vs JRE vs JVM
- Java - Environment Setup
- Java - Hello World Program
- Java - Comments
- Java - Basic Syntax
- Java - Variables
- Java - Data Types
- Java - Type Casting
- Java - Unicode System
- Java - User Input
- Java - Date & Time
Java Operators
- Java - Operators
- Java - Arithmetic Operators
- Java - Assignment Operators
- Java - Relational Operators
- Java - Logical Operators
- Java - Bitwise Operators
- Java Operator Precedence & Associativity
- Java - Unary Operators
Java Control Statements
- Java - Decision Making
- Java - If Else Statement
- Java - Switch Statement
- Java - Loop Control
- Java - For Loop
- Java - For-Each Loop
- Java - While Loop
- Java - Do While Loop
- Java - Break Statement
- Java - Continue Statement
Object Oriented Programming
- Java - OOPs Concepts
- Java - Object & Classes
- Java - Class Attributes
- Java - Class Methods
- Java - Methods
- Java - Variables Scope
- Java - Constructors
- Java - Access Modifiers
- Java - Inheritance
- Java - Aggregation
- Java - Polymorphism
- Java - Overriding
- Java - Method Overloading
- Java - Dynamic Binding
- Java - Static Binding
- Java - Instance Initializer Block
- Java - Abstraction
- Java - Encapsulation
- Java - Interfaces
- Java - Packages
- Java - Inner Classes
- Java - Static Class
- Java - Anonymous Class
- Java - Singleton Class
- Java - Wrapper Classes
- Java - Enums
- Java - Enum Constructor
- Java - Enum Strings
Java Built-in Classes
- Java - Number
- Java - Boolean
- Java - Characters
- Java - Arrays
- Java - Multi-Dimensional Arrays
- Java - Final Arrays
- Java - Math Class
Java File Handling
- Java - Files
- Java - Create a File
- Java - Write to File
- Java - Read Files
- Java - Delete Files
- Java - Directories
- Java - I/O Streams
Java Error & Exceptions
- Java - Exceptions
- Java - try-catch Block
- Java - try-with-resources
- Java - Multi-catch Block
- Java - Nested try Block
- Java - Finally Block
- Java - throw Exception
- Java - Exception Propagation
- Java - Built-in Exceptions
- Java - Custom Exception
- Java - Chained Exception
Java Multithreading
- Java - Multithreading
- Java - Thread Life Cycle
- Java - Creating a Thread
- Java - Starting a Thread
- Java - Joining Threads
- Java - Naming Thread
- Java - Thread Scheduler
- Java - Thread Pools
- Java - Main Thread
- Java - Thread Priority
- Java - Daemon Threads
- Java - Thread Group
- Java - Shutdown Hook
Java Synchronization
- Java - Synchronization
- Java - Block Synchronization
- Java - Static Synchronization
- Java - Inter-thread Communication
- Java - Thread Deadlock
- Java - Interrupting a Thread
- Java - Thread Control
- Java - Reentrant Monitor
Java Networking
- Java - Networking
- Java - Socket Programming
- Java - URL Processing
- Java - URL Class
- Java - URLConnection Class
- Java - HttpURLConnection Class
- Java - Socket Class
- Java - Generics
Java Collections
Java Interfaces
- Java - List Interface
- Java - Queue Interface
- Java - Map Interface
- Java - SortedMap Interface
- Java - Set Interface
- Java - SortedSet Interface
Java Data Structures
Java Collections Algorithms
Advanced Java
- Java - Command-Line Arguments
- Java - Lambda Expressions
- Java - Sending Email
- Java - Applet Basics
- Java - Javadoc Comments
- Java - Autoboxing and Unboxing
- Java - File Mismatch Method
- Java - REPL (JShell)
- Java - Multi-Release Jar Files
- Java - Private Interface Methods
- Java - Inner Class Diamond Operator
- Java - Multiresolution Image API
- Java - Collection Factory Methods
- Java - Module System
- Java - Nashorn JavaScript
- Java - Optional Class
- Java - Method References
- Java - Functional Interfaces
- Java - Default Methods
- Java - Base64 Encode Decode
- Java - Switch Expressions
- Java - Teeing Collectors
- Java - Microbenchmark
- Java - Text Blocks
- Java - Dynamic CDS archive
- Java - Z Garbage Collector (ZGC)
- Java - Null Pointer Exception
- Java - Packaging Tools
- Java - Sealed Classes
- Java - Record Classes
- Java - Hidden Classes
- Java - Pattern Matching
- Java - Compact Number Formatting
- Java - Garbage Collection
- Java - JIT Compiler
Java Miscellaneous
- Java - Recursion
- Java - Regular Expressions
- Java - Serialization
- Java - Strings
- Java - Process API Improvements
- Java - Stream API Improvements
- Java - Enhanced @Deprecated Annotation
- Java - CompletableFuture API Improvements
- Java - Marker Interface
- Java - Streams
- Java - Datetime Api
- Java 8 - New Features
- Java 9 - New Features
- Java 10 - New Features
- Java 11 - New Features
- Java 12 - New Features
- Java 13 - New Features
- Java 14 - New Features
- Java 15 - New Features
- Java 16 - New Features
Java APIs & Frameworks
Java Class References
- Java - Scanner
- Java - Arrays
- Java - Strings
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java Useful Resources
Java - Pattern Matching with instanceof Operator
Pattern matching means the act of checking if a particular data matches with another data in some property or feature, similar to a regular expression. Java 14 introduces the instanceof operator to have a type test pattern as a preview feature.
The type test pattern has a predicate to specify a type with a single binding variable. It is a standard feature of Java from Java 17 onwards.
The Traditional Approach
Previously, in the traditional approach, we had to perform two steps to safely access members of an object. First, we have to verify the object's type at runtime using the instanceof operator. Then, we have to explicitly castthe object to its type if the check was successful.
Syntax
In the syntax below, we're showing a regular approach of testing a person object with the Employee class, and then in an if block, we're typecasting the person to Employee e to perform operations on the Employee object.
if (person instanceof Employee) {
// Unnecessary casting
Employee e = (Employee)person;
return e.getEmployeeId();
}
Drawbacks of the Traditional Approach
The following are the drawbacks of using the traditional approach for the instanceof operator in Java −
- It repeats the code as it checks the type, then explicitly casts and assigns it to a newly created local variable. This leads to three references to the specific type(eg, "Employee" object as above).
- If the casting is not handled carefully, it can result in a ClassCastException error at runtime.
- It reduces the readability if multiple instanceof checks are used, making it complex to understand.
Enhanced instanceof Operator
Java 14 introduced an enhanced for the instanceof operator in the JEP 305, which tests both the parameter object and assigns it to a binding variable of the appropriate type. The main enhancement is the introduction of the type pattern, which consists of the following two things −
- Predicate − It is a Boolean function with one argument, which checks if the target object is an instance of the specified type.
- Pattern Variable − Also known as a binding variable, if the predicate is true, the pattern variable is automatically cast to the specified type.
Syntax
In the syntax below, we've used the instanceof operator to test person object is an Employee, as well as assign the person object to the Employee reference e, which is then used to perform operations on the Employee object.
if (person instanceof Employee e) {
return e.getEmployeeId();
}
Before this enhancement, developers had to typecast the object as shown in the traditional approach.
Scope of Pattern Variables
The scope of a pattern variable is the places where the program can reach only if the instanceof operator is true. The pattern variables store data from the target only if the predicate returns true.
In the syntax below, we're showing in a basicif statement, the pattern variable that is in scope within the if block −
if (person instanceof Employee e) {
// "e" is in scope here
return e.getEmployeeId();
//"e" is not in scope here
return false;
}
In the syntax below, we're showing that the scope of a pattern variable can be extended beyond the statement that introduced it, as we are negating the if instanceof check using the conditional operator(!) −
if (!(person instanceof Employee e)) {
// "e" is not in scope here as the predicate "e" instanceof Employee is false
return false;
//"e" is not in scope here
return e.getEmployeeId();
}
Example of Traditional Approach
In this example, we've defined classes Person, Employee, and Manager. Employee and Manager extend the Person class. In the APITester class, we've defined a method getId() which takes Person as input, and using the instanceof operator, we're testing the type of object as either Employee or Manager, and then based on the result of the if block, we're typecasting the object to either Employee or Manager and return the employeeId or managerId accordingly.
package com.tutorialspoint;
public class APITester {
public static void main(String[] args) {
// Create a Manager Instance
Person manager = new Manager(23, "Robert");
// Get and print Id of the manager
System.out.println(getId(manager));
}
// using instanceof operator
// to test type of Person to be Employee or Manager
public static int getId(Person person) {
// If person is Employee, assign it to e
// in next statement
if (person instanceof Employee) {
// Unnecessary typecasting
Employee e = (Employee)person;
return e.getEmployeeId();
}
// If person is Manager, assign it to m
// in same statement
else if (person instanceof Manager) {
// Unnecessary typecasting
Manager m = (Manager)person;
return m.getManagerId();
}
return -1;
}
}
abstract sealed class Person permits Employee, Manager {
String name;
String getName() {
return name;
}
}
final class Employee extends Person {
String name;
int id;
Employee(int id, String name){
this.id = id;
this.name = name;
}
int getEmployeeId() {
return id;
}
}
non-sealed class Manager extends Person {
int id;
Manager(int id, String name){
this.id = id;
this.name = name;
}
int getManagerId() {
return id;
}
}
Output
Let us compile and run the above program. This will produce the following result −
23
Example Enhanced instanceof Operator
In this example, we've defined classes Person, Employee, and Manager. Employee and Manager extend the Person class. In the APITester class, we've defined a method getId() which takes Person as input, and using the instanceof operator, we're testing the type of object as either Employee or Manager, and then within the same if block, we're assigning the object to either Employee or Manager without typecasting and return the employeeId or managerId accordingly.
package com.tutorialspoint;
public class APITester {
public static void main(String[] args) {
// Create a Manager Instance
Person manager = new Manager(23, "Robert");
// Get and print Id of the manager
System.out.println(getId(manager));
}
// using instanceof operator
// to test type of Person to be Employee or Manager
public static int getId(Person person) {
// If person is Employee, assign it to e
// in same statement
if (person instanceof Employee e) {
return e.getEmployeeId();
}
// If person is Manager, assign it to m
// in same statement
else if (person instanceof Manager m) {
return m.getManagerId();
}
return -1;
}
}
abstract sealed class Person permits Employee, Manager {
String name;
String getName() {
return name;
}
}
final class Employee extends Person {
String name;
int id;
Employee(int id, String name){
this.id = id;
this.name = name;
}
int getEmployeeId() {
return id;
}
}
non-sealed class Manager extends Person {
int id;
Manager(int id, String name){
this.id = id;
this.name = name;
}
int getManagerId() {
return id;
}
}
Output
Let us compile and run the above program. This will produce the following result −
23