Java 17 Features ==================================== 1. sealed classes : * sealed classes are created to define its child classes in a controlled way. * A sealed class can specify who can be its child class and who can't. * A sealed class can specify its subtypes with permits keyword. ex: public sealed ParentClass permits ChildClass1, ChildClass2 { // variables // methods } public final class ChildClass1 extends ParentClass { // valid // variables // methods } public final class ChildClass2 extends ParentClass { // valid // variables // methods } public final class ChildClass3 extends ParentClass { // error // variables // methods } * A child class of a sealed class must be declared as sealed or non-sealed or final * if you specify sealed for a child class then it can be further extended in a controlled way. It means, you have to use permits keyword to declare the child types. ex: public sealed class ChildClass1 extends ParentClass permits ChildClass11, ChildClass12 { } * If you specify non-sealed for a child class then it can be further extended in un-controlled way. It means, any class can extend this child class. ex: public non-sealed class ChildClass2 extends ParentClass { } * If you specify final for a child class then it can't be further extended. ex: public final class ChildClass2 extends ParentClass { } * We can also define a sealed interface to create implementation classes in a controlled way. ex: public sealed interface Shape permits Circle, Rectangle { } public final class Circle implements Shape { // valid } public final class Rectangle implements Shape { // valid } public final class Triangle implements Shape { // error } ========================================================================= Text block : * Before Java17, if you want to return a text block with more than one line of text then you have to use new line(\n) character and concatenation(+) symbol. ex: return " This is line1 \n" +" This is line2 \n" +" This is line3"; * From Java17+, if you want to return a text block with more than one line of text then you have to enclose the text block within three double quotes. ex: class Story { public static String getStory() { return """ Stream API is an important feature of Java8. It will simplify the processing of collections. """; } } ======================================================================================== enhanced switch statement: * It will allow to define multiple values in a single case. * It can return a value. * The symbol colon(:) and break statement for each case are replaced with -> symbol. ex: package pack1; import java.time.Month; import java.time.Year; public class Main { public static int getDays(Month month, int year) { return switch(month) { case APRIL, JUNE, SEPTEMBER, NOVEMBER -> 30; case FEBRUARY -> { yield Year.isLeap(year) ? 29 : 28; } default -> 31; }; } public static void main(String[] args) { int daysInFeb = Main.getDays(Month.FEBRUARY, 2028); System.out.println("No of days in Feb 2028 : " + daysInFeb); } } ============================================================== record class: --------------- * record classes are provided to create Data Transfer Objects(DTO's) in a concise way. * DTO's are used to carry the data from one service to another or from a server to a client. * From Java17, we can use record classes as DTO's to carry the data. * record class objects are immutable objects, by default. * when a record class is created with required fields, internally the below things will happen. 1. the fields are implicitly made as private and final. 2. All arguments constructor is generated. 3. accessor methods are created for the fields(like getters). 4. automatically toString(), equals() and hashCode() methods are generated. ex: public record Customer(int customerId, String customerName, long phone) { } public class Main { public static void main(String[] args) { Customer customer = new Customer(1011, "John", 9890080012L); System.out.println(customer.customerId()); System.out.println(customer.customerName()); System.out.println(customer.phone()); } } * We can also create static variables, static methods and instance methods in a record class, if needed. But we can't create instance variables. * Before Java17, to generate the boilerplate code like constructors, getters/setters, toString, equals and hashCode, a third-party api called Lombok annotations were used. * Every record class implicitly extends java.lang.Record class. * A record class can't extends any another record class or a normal java class. * A record class is implicitly final. * A record class can implement a normal interface or a sealed interface. ex: public sealed interface UserActivity permits CreateUser, DeleteUser { boolean confirm(); } public record CreateUser() implements UserActivity { @Override public boolean confirm() { // TODO Auto-generated method stub return false; } } public record DeleteUser() implements UserActivity { @Override public boolean confirm() { // TODO Auto-generated method stub return false; } } * We can able create a record class inside another record class. * The inner record class can be non-static or static. ex: public record MyRecord(int x, int y) { public record MySubRecord(int a, int b) { } } public class Main { public static void main(String[] args) { MyRecord myRecord = new MyRecord(10, 20); MyRecord.MySubRecord mySubRecord = new MyRecord.MySubRecord(40, 50); } } ====================================================================== pattern strategy in switch: --------------------------- * Before Java17, we can use switch for Strings, characters or integers. * From Java17+, we can use switch for object types. * The pattern matching and type casting will be automatically done by switch only. ex: public interface Payment { boolean confirm(); } public class CreditCardPayment implements Payment { @Override public boolean confirm() { // TODO Auto-generated method stub return true; } } public class UpiPayment implements Payment { @Override public boolean confirm() { // TODO Auto-generated method stub return true; } } public class PaymentProcessor { public void process(Payment payment) { switch(payment) { case CreditCardPayment credit -> { System.out.println("CredirCard payment processed"); System.out.println("status : " + credit.confirm()); } case UpiPayment upi -> { System.out.println("Upi payment processed"); System.out.println("status : "+ upi.confirm()); } default -> System.out.println("Unknown payment method"); } } } public class TestClass { public static void main(String[] args) { PaymentProcessor processor = new PaymentProcessor(); processor.process(new UpiPayment()); } } ===========================================================================================