aboutsummaryrefslogtreecommitdiffstats
path: root/tests/features197
diff options
context:
space:
mode:
Diffstat (limited to 'tests/features197')
-rw-r--r--tests/features197/java15/Employee.java1
-rw-r--r--tests/features197/java15/HiddenClass.java6
-rw-r--r--tests/features197/java15/HiddenClassDemo.java39
-rw-r--r--tests/features197/java15/Manager.java1
-rw-r--r--tests/features197/java15/Person.java5
-rw-r--r--tests/features197/java15/PersonAspect.aj17
-rw-r--r--tests/features197/java15/PersonaNonGrata.java2
-rw-r--r--tests/features197/java15/TopManager.java10
8 files changed, 81 insertions, 0 deletions
diff --git a/tests/features197/java15/Employee.java b/tests/features197/java15/Employee.java
new file mode 100644
index 000000000..9b0b9da99
--- /dev/null
+++ b/tests/features197/java15/Employee.java
@@ -0,0 +1 @@
+public final class Employee extends Person {}
diff --git a/tests/features197/java15/HiddenClass.java b/tests/features197/java15/HiddenClass.java
new file mode 100644
index 000000000..f1ef61166
--- /dev/null
+++ b/tests/features197/java15/HiddenClass.java
@@ -0,0 +1,6 @@
+public class HiddenClass implements Test {
+ @Override
+ public void concat(String... words) {
+ System.out.println(String.join(" ", words));
+ }
+}
diff --git a/tests/features197/java15/HiddenClassDemo.java b/tests/features197/java15/HiddenClassDemo.java
new file mode 100644
index 000000000..0b7f0ab17
--- /dev/null
+++ b/tests/features197/java15/HiddenClassDemo.java
@@ -0,0 +1,39 @@
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+
+import java.io.FileInputStream;
+
+import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
+
+public class HiddenClassDemo {
+ public static void main(String[] args) throws Throwable {
+ // Step 1: Create lookup object
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+ // Step 2: Fetch or create the class bytes we want to define
+ byte[] bytes = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream("HiddenClass.class")
+ .readAllBytes();
+
+ // Step 3: Define hidden class
+ Class<?> clazz = lookup.defineHiddenClass(bytes, true, NESTMATE).lookupClass();
+ // Hidden classes have class names like my.package.MyClass/0x2a23f5, but no canonical name (null)
+ System.out.println("Hidden class name = " + clazz.getName());
+ System.out.println("Hidden class canonical name = " + clazz.getCanonicalName ());
+ // Hidden classes cannot be resolved by any class loader (ClassNotFoundException)
+ try {
+ Class.forName(clazz.getName());
+ }
+ catch (ClassNotFoundException e) {
+ System.out.println("Class.forName resolution error = " + e);
+ }
+
+ //Step 4: Create instance of hidden class object and call interface method
+ Test test = (Test) clazz.getConstructor(null).newInstance(null);
+ test.concat("Hello", "from", "dynamically", "defined", "hidden", "class");
+ }
+}
+
+interface Test {
+ void concat(String... words);
+}
diff --git a/tests/features197/java15/Manager.java b/tests/features197/java15/Manager.java
new file mode 100644
index 000000000..09b897d1e
--- /dev/null
+++ b/tests/features197/java15/Manager.java
@@ -0,0 +1 @@
+public non-sealed class Manager extends Person {}
diff --git a/tests/features197/java15/Person.java b/tests/features197/java15/Person.java
new file mode 100644
index 000000000..cdd87d7f3
--- /dev/null
+++ b/tests/features197/java15/Person.java
@@ -0,0 +1,5 @@
+public abstract sealed class Person permits Employee, Manager {
+ public void sayHello(String name) {
+ System.out.println("Hello " + name);
+ }
+}
diff --git a/tests/features197/java15/PersonAspect.aj b/tests/features197/java15/PersonAspect.aj
new file mode 100644
index 000000000..695a4de36
--- /dev/null
+++ b/tests/features197/java15/PersonAspect.aj
@@ -0,0 +1,17 @@
+public aspect PersonAspect {
+ // Weave into sealed class
+ void around(String name): execution(void sayHello(*)) && args(name) {
+ proceed("Sir " + name);
+ }
+
+ // ITD into non-sealed subclass of sealed class
+ private String Manager.jobTitle;
+
+ public void TopManager.setJobTitle(String jobTitle) {
+ this.jobTitle = jobTitle;
+ }
+
+ public String TopManager.getJobTitle() {
+ return jobTitle;
+ }
+}
diff --git a/tests/features197/java15/PersonaNonGrata.java b/tests/features197/java15/PersonaNonGrata.java
new file mode 100644
index 000000000..fc801536d
--- /dev/null
+++ b/tests/features197/java15/PersonaNonGrata.java
@@ -0,0 +1,2 @@
+// This should not compile because Person is sealed and does not allow PersonaNonGrata as a subclass
+public final class PersonaNonGrata extends Person {}
diff --git a/tests/features197/java15/TopManager.java b/tests/features197/java15/TopManager.java
new file mode 100644
index 000000000..e1dfdc367
--- /dev/null
+++ b/tests/features197/java15/TopManager.java
@@ -0,0 +1,10 @@
+public class TopManager extends Manager {
+ public static void main(String[] args) {
+ TopManager topManager = new TopManager();
+ topManager.sayHello("John");
+
+ // Call ITD methods
+ topManager.setJobTitle("CEO");
+ System.out.println(topManager.getJobTitle());
+ }
+}