From 5116a45d1e05210176bac3c157d09c3d5351b17f Mon Sep 17 00:00:00 2001 From: Daniel Strmecki Date: Tue, 3 Nov 2020 20:37:30 +0100 Subject: [PATCH] Feature/bael 4662 sealed classes (#10224) * BAEL-4662: Initial commit of new module * BAEL-4662: Example with Records * BAEL-4662: Example with Interface * BAEL-4662: Add test classes * BAEL-4662: Update examples and tests * BAEL-4662: Rename test classes --- .../core-java-15/.mvn/jvm.config | 1 + core-java-modules/core-java-15/README.md | 7 ++ core-java-modules/core-java-15/pom.xml | 77 +++++++++++++++++++ .../baeldung/sealed/alternative/Vehicles.java | 49 ++++++++++++ .../java/com/baeldung/sealed/classes/Car.java | 21 +++++ .../com/baeldung/sealed/classes/Service.java | 11 +++ .../com/baeldung/sealed/classes/Truck.java | 21 +++++ .../com/baeldung/sealed/classes/Vehicle.java | 15 ++++ .../java/com/baeldung/sealed/records/Car.java | 14 ++++ .../com/baeldung/sealed/records/Truck.java | 14 ++++ .../com/baeldung/sealed/records/Vehicle.java | 7 ++ .../sealed/classes/VehicleUnitTest.java | 76 ++++++++++++++++++ .../sealed/records/VehicleUnitTest.java | 76 ++++++++++++++++++ 13 files changed, 389 insertions(+) create mode 100644 core-java-modules/core-java-15/.mvn/jvm.config create mode 100644 core-java-modules/core-java-15/README.md create mode 100644 core-java-modules/core-java-15/pom.xml create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java create mode 100644 core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java create mode 100644 core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java create mode 100644 core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java diff --git a/core-java-modules/core-java-15/.mvn/jvm.config b/core-java-modules/core-java-15/.mvn/jvm.config new file mode 100644 index 0000000000..50f549be0a --- /dev/null +++ b/core-java-modules/core-java-15/.mvn/jvm.config @@ -0,0 +1 @@ +--enable-preview \ No newline at end of file diff --git a/core-java-modules/core-java-15/README.md b/core-java-modules/core-java-15/README.md new file mode 100644 index 0000000000..53989f5cbb --- /dev/null +++ b/core-java-modules/core-java-15/README.md @@ -0,0 +1,7 @@ +## Core Java 15 + +This module contains articles about Java 15. + +### Relevant articles + +- TODO: add article links here diff --git a/core-java-modules/core-java-15/pom.xml b/core-java-modules/core-java-15/pom.xml new file mode 100644 index 0000000000..c6f1454078 --- /dev/null +++ b/core-java-modules/core-java-15/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + core-java-15 + core-java-15 + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../pom.xml + + + + + org.apache.commons + commons-lang3 + ${apache-commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.release} + --enable-preview + 15 + 15 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + --enable-preview + + + + + + + 15 + 3.11 + 3.17.2 + 3.8.1 + 3.0.0-M3 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java new file mode 100644 index 0000000000..091c5841bf --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java @@ -0,0 +1,49 @@ +package com.baeldung.sealed.alternative; + +public class Vehicles { + + abstract static class Vehicle { + + private final String registrationNumber; + + public Vehicle(String registrationNumber) { + this.registrationNumber = registrationNumber; + } + + public String getRegistrationNumber() { + return registrationNumber; + } + + } + + public static final class Car extends Vehicle { + + private final int numberOfSeats; + + public Car(int numberOfSeats, String registrationNumber) { + super(registrationNumber); + this.numberOfSeats = numberOfSeats; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + } + + public static final class Truck extends Vehicle { + + private final int loadCapacity; + + public Truck(int loadCapacity, String registrationNumber) { + super(registrationNumber); + this.loadCapacity = loadCapacity; + } + + public int getLoadCapacity() { + return loadCapacity; + } + + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java new file mode 100644 index 0000000000..7dce266da7 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java @@ -0,0 +1,21 @@ +package com.baeldung.sealed.classes; + +public non-sealed class Car extends Vehicle implements Service { + + private final int numberOfSeats; + + public Car(int numberOfSeats, String registrationNumber) { + super(registrationNumber); + this.numberOfSeats = numberOfSeats; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + @Override + public int getMaxServiceIntervalInMonths() { + return 12; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java new file mode 100644 index 0000000000..9486b302f1 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java @@ -0,0 +1,11 @@ +package com.baeldung.sealed.classes; + +public sealed interface Service permits Car, Truck { + + int getMaxServiceIntervalInMonths(); + + default int getMaxDistanceBetweenServicesInKilometers() { + return 100000; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java new file mode 100644 index 0000000000..8d5234342b --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java @@ -0,0 +1,21 @@ +package com.baeldung.sealed.classes; + +public final class Truck extends Vehicle implements Service { + + private final int loadCapacity; + + public Truck(int loadCapacity, String registrationNumber) { + super(registrationNumber); + this.loadCapacity = loadCapacity; + } + + public int getLoadCapacity() { + return loadCapacity; + } + + @Override + public int getMaxServiceIntervalInMonths() { + return 18; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java new file mode 100644 index 0000000000..79eda0c790 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java @@ -0,0 +1,15 @@ +package com.baeldung.sealed.classes; + +public abstract sealed class Vehicle permits Car, Truck { + + protected final String registrationNumber; + + public Vehicle(String registrationNumber) { + this.registrationNumber = registrationNumber; + } + + public String getRegistrationNumber() { + return registrationNumber; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java new file mode 100644 index 0000000000..74b6ed1405 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java @@ -0,0 +1,14 @@ +package com.baeldung.sealed.records; + +public record Car(int numberOfSeats, String registrationNumber) implements Vehicle { + + @Override + public String getRegistrationNumber() { + return registrationNumber; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java new file mode 100644 index 0000000000..1b887ae014 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java @@ -0,0 +1,14 @@ +package com.baeldung.sealed.records; + +public record Truck(int loadCapacity, String registrationNumber) implements Vehicle { + + @Override + public String getRegistrationNumber() { + return registrationNumber; + } + + public int getLoadCapacity() { + return loadCapacity; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java new file mode 100644 index 0000000000..c51f8e97c6 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java @@ -0,0 +1,7 @@ +package com.baeldung.sealed.records; + +public sealed interface Vehicle permits Car, Truck { + + String getRegistrationNumber(); + +} diff --git a/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java new file mode 100644 index 0000000000..b614981a43 --- /dev/null +++ b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.sealed.classes; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.lang.constant.ClassDesc; + +public class VehicleUnitTest { + + private static Vehicle car; + private static Vehicle truck; + + @BeforeAll + public static void createInstances() { + car = new Car(5, "VZ500DA"); + truck = new Truck(19000, "VZ600TA"); + } + + @Test + public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() { + Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(car.getClass().getSuperclass().isSealed()).isEqualTo(true); + Assertions.assertThat(car.getClass().getSuperclass().permittedSubclasses()) + .contains(ClassDesc.of(car.getClass().getCanonicalName())); + } + + @Test + public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() { + Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(truck.getClass().getSuperclass().isSealed()).isEqualTo(true); + Assertions.assertThat(truck.getClass().getSuperclass().permittedSubclasses()) + .contains(ClassDesc.of(truck.getClass().getCanonicalName())); + } + + @Test + public void givenCar_whenGettingPropertyTraditionalWay_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(car)).isEqualTo(5); + } + + @Test + public void givenCar_whenGettingPropertyViaPatternMatching_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(car)).isEqualTo(5); + } + + @Test + public void givenTruck_whenGettingPropertyTraditionalWay_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(truck)).isEqualTo(19000); + } + + @Test + public void givenTruck_whenGettingPropertyViaPatternMatching_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(truck)).isEqualTo(19000); + } + + private int getPropertyTraditionalWay(Vehicle vehicle) { + if (vehicle instanceof Car) { + return ((Car) vehicle).getNumberOfSeats(); + } else if (vehicle instanceof Truck) { + return ((Truck) vehicle).getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + + private int getPropertyViaPatternMatching(Vehicle vehicle) { + if (vehicle instanceof Car car) { + return car.getNumberOfSeats(); + } else if (vehicle instanceof Truck truck) { + return truck.getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + +} diff --git a/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java new file mode 100644 index 0000000000..ac8a8c953c --- /dev/null +++ b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.sealed.records; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.lang.constant.ClassDesc; + +public class VehicleUnitTest { + + private static Vehicle car; + private static Vehicle truck; + + @BeforeAll + public static void createInstances() { + car = new Car(4, "VZ500DA"); + truck = new Truck(16000, "VZ600TA"); + } + + @Test + public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() { + Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(car.getClass().getInterfaces()[0].isSealed()).isEqualTo(true); + Assertions.assertThat(car.getClass().getInterfaces()[0].permittedSubclasses()) + .contains(ClassDesc.of(car.getClass().getCanonicalName())); + } + + @Test + public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() { + Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(truck.getClass().getInterfaces()[0].isSealed()).isEqualTo(true); + Assertions.assertThat(truck.getClass().getInterfaces()[0].permittedSubclasses()) + .contains(ClassDesc.of(truck.getClass().getCanonicalName())); + } + + @Test + public void givenCar_whenGettingPropertyTraditionalWay_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(car)).isEqualTo(4); + } + + @Test + public void givenCar_whenGettingPropertyViaPatternMatching_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(car)).isEqualTo(4); + } + + @Test + public void givenTruck_whenGettingPropertyTraditionalWay_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(truck)).isEqualTo(16000); + } + + @Test + public void givenTruck_whenGettingPropertyViaPatternMatching_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(truck)).isEqualTo(16000); + } + + private int getPropertyTraditionalWay(Vehicle vehicle) { + if (vehicle instanceof Car) { + return ((Car) vehicle).getNumberOfSeats(); + } else if (vehicle instanceof Truck) { + return ((Truck) vehicle).getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + + private int getPropertyViaPatternMatching(Vehicle vehicle) { + if (vehicle instanceof Car car) { + return car.getNumberOfSeats(); + } else if (vehicle instanceof Truck truck) { + return truck.getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + +}