11/*
2- * Copyright (c) 2013, 2016 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2013, 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323
2424/*
2525 * @test
26- * @bug 6298888 6992705 8161500 6304578
26+ * @bug 6298888 6992705 8161500 6304578 8322878
2727 * @summary Check Class.toGenericString()
28- * @author Joseph D. Darcy
2928 */
3029
3130import java .lang .reflect .*;
@@ -37,25 +36,41 @@ public class GenericStringTest {
3736 public Map <String , Integer >[] mixed = null ;
3837 public Map <String , Integer >[][] mixed2 = null ;
3938
39+ private static record PlatformTestCase (Class <?> clazz , String expected ) {}
40+
4041 public static void main (String ... args ) throws ReflectiveOperationException {
4142 int failures = 0 ;
4243
4344 String [][] nested = {{"" }};
4445 int [][] intArray = {{1 }};
4546
46- Map <Class <?>, String > testCases =
47- Map .of (int .class , "int" ,
48- void .class , "void" ,
49- args .getClass (), "java.lang.String[]" ,
50- nested .getClass (), "java.lang.String[][]" ,
51- intArray .getClass (), "int[][]" ,
52- java .lang .Enum .class , "public abstract class java.lang.Enum<E extends java.lang.Enum<E>>" ,
53- java .util .Map .class , "public abstract interface java.util.Map<K,V>" ,
54- java .util .EnumMap .class , "public class java.util.EnumMap<K extends java.lang.Enum<K>,V>" ,
55- java .util .EventListenerProxy .class , "public abstract class java.util.EventListenerProxy<T extends java.util.EventListener>" );
56-
57- for (Map .Entry <Class <?>, String > testCase : testCases .entrySet ()) {
58- failures += checkToGenericString (testCase .getKey (), testCase .getValue ());
47+ List <PlatformTestCase > platformTestCases =
48+ List .of (new PlatformTestCase (int .class , "int" ),
49+ new PlatformTestCase (void .class , "void" ),
50+ new PlatformTestCase (args .getClass (), "java.lang.String[]" ),
51+ new PlatformTestCase (nested .getClass (), "java.lang.String[][]" ),
52+ new PlatformTestCase (intArray .getClass (), "int[][]" ),
53+
54+ new PlatformTestCase (java .lang .Enum .class ,
55+ "public abstract class java.lang.Enum<E extends java.lang.Enum<E>>" ),
56+ new PlatformTestCase (java .util .Map .class ,
57+ "public abstract interface java.util.Map<K,V>" ),
58+ new PlatformTestCase (java .util .EnumMap .class ,
59+ "public class java.util.EnumMap<K extends java.lang.Enum<K>,V>" ),
60+ new PlatformTestCase (java .util .EventListenerProxy .class ,
61+ "public abstract class java.util.EventListenerProxy<T extends java.util.EventListener>" ),
62+
63+ // Sealed class
64+ new PlatformTestCase (java .lang .ref .Reference .class ,
65+ "public abstract sealed class java.lang.ref.Reference<T>" ),
66+ // non-sealed class
67+ new PlatformTestCase (java .lang .ref .WeakReference .class ,
68+ "public non-sealed class java.lang.ref.WeakReference<T>" )
69+ );
70+
71+ for (PlatformTestCase platformTestCase : platformTestCases ) {
72+ failures += checkToGenericString (platformTestCase .clazz ,
73+ platformTestCase .expected );
5974 }
6075
6176 Field f = GenericStringTest .class .getDeclaredField ("mixed" );
@@ -70,7 +85,33 @@ public static void main(String... args) throws ReflectiveOperationException {
7085 AnInterface .class ,
7186 LocalMap .class ,
7287 AnEnum .class ,
73- AnotherEnum .class )) {
88+ AnotherEnum .class ,
89+
90+ SealedRootClass .class ,
91+ SealedRootClass .ChildA .class ,
92+ SealedRootClass .ChildB .class ,
93+ SealedRootClass .ChildB .GrandChildAB .class ,
94+ SealedRootClass .ChildC .class ,
95+ SealedRootClass .ChildC .GrandChildACA .class ,
96+ SealedRootClass .ChildC .GrandChildACB .class ,
97+ SealedRootClass .ChildC .GrandChildACC .class ,
98+ SealedRootClass .ChildC .GrandChildACC .GreatGrandChildACCA .class ,
99+ SealedRootClass .ChildC .GrandChildACC .GreatGrandChildACCB .class ,
100+
101+ SealedRootIntf .class ,
102+ SealedRootIntf .ChildA .class ,
103+ SealedRootIntf .ChildB .class ,
104+ SealedRootIntf .ChildB .GrandChildAB .class ,
105+ SealedRootIntf .ChildC .class ,
106+ SealedRootIntf .ChildC .GrandChildACA .class ,
107+ SealedRootIntf .ChildC .GrandChildACB .class ,
108+ SealedRootIntf .ChildC .GrandChildACC .class ,
109+ SealedRootIntf .ChildC .GrandChildACC .GreatGrandChildACCA .class ,
110+ SealedRootIntf .ChildC .GrandChildACC .GreatGrandChildACCB .class ,
111+ SealedRootIntf .IntfA .class ,
112+ SealedRootIntf .IntfA .IntfAImpl .class ,
113+ SealedRootIntf .IntfB .class ,
114+ SealedRootIntf .IntfB .IntfAImpl .class )) {
74115 failures += checkToGenericString (clazz , clazz .getAnnotation (ExpectedGenericString .class ).value ());
75116 }
76117
@@ -107,7 +148,102 @@ enum AnEnum {
107148 FOO ;
108149}
109150
110- @ ExpectedGenericString ("enum AnotherEnum" )
151+ // If an enum class has a specialized enum constant, that is compiled
152+ // by having the enum class as being sealed rather than final. See JLS
153+ // 8.9 Enum Classes.
154+ @ ExpectedGenericString ("sealed enum AnotherEnum" )
111155enum AnotherEnum {
112156 BAR {};
113157}
158+
159+ // Test cases for sealed/non-sealed _class_ hierarchy.
160+ @ ExpectedGenericString ("sealed class SealedRootClass" )
161+ sealed class SealedRootClass
162+ permits
163+ SealedRootClass .ChildA ,
164+ SealedRootClass .ChildB ,
165+ SealedRootClass .ChildC {
166+
167+ @ ExpectedGenericString ("final class SealedRootClass$ChildA" )
168+ final class ChildA extends SealedRootClass {}
169+
170+ @ ExpectedGenericString ("sealed class SealedRootClass$ChildB" )
171+ sealed class ChildB extends SealedRootClass permits SealedRootClass .ChildB .GrandChildAB {
172+ @ ExpectedGenericString ("final class SealedRootClass$ChildB$GrandChildAB" )
173+ final class GrandChildAB extends ChildB {}
174+ }
175+
176+ @ ExpectedGenericString ("non-sealed class SealedRootClass$ChildC" )
177+ non-sealed class ChildC extends SealedRootClass {
178+ // The subclasses of ChildC do not themselves have to be
179+ // sealed, non-sealed, or final.
180+ @ ExpectedGenericString ("class SealedRootClass$ChildC$GrandChildACA" )
181+ class GrandChildACA extends ChildC {}
182+
183+ @ ExpectedGenericString ("final class SealedRootClass$ChildC$GrandChildACB" )
184+ final class GrandChildACB extends ChildC {}
185+
186+ @ ExpectedGenericString ("sealed class SealedRootClass$ChildC$GrandChildACC" )
187+ sealed class GrandChildACC extends ChildC {
188+ @ ExpectedGenericString ("final class SealedRootClass$ChildC$GrandChildACC$GreatGrandChildACCA" )
189+ final class GreatGrandChildACCA extends GrandChildACC {}
190+
191+ @ ExpectedGenericString ("non-sealed class SealedRootClass$ChildC$GrandChildACC$GreatGrandChildACCB" )
192+ non-sealed class GreatGrandChildACCB extends GrandChildACC {}
193+ }
194+ }
195+ }
196+
197+ // Test cases for sealed/non-sealed _interface_ hierarchy.
198+ @ ExpectedGenericString ("abstract sealed interface SealedRootIntf" )
199+ sealed interface SealedRootIntf
200+ permits
201+ SealedRootIntf .ChildA ,
202+ SealedRootIntf .ChildB ,
203+ SealedRootIntf .ChildC ,
204+
205+ SealedRootIntf .IntfA ,
206+ SealedRootIntf .IntfB {
207+
208+ @ ExpectedGenericString ("public static final class SealedRootIntf$ChildA" )
209+ final class ChildA implements SealedRootIntf {}
210+
211+ @ ExpectedGenericString ("public static sealed class SealedRootIntf$ChildB" )
212+ sealed class ChildB implements SealedRootIntf permits SealedRootIntf .ChildB .GrandChildAB {
213+ @ ExpectedGenericString ("final class SealedRootIntf$ChildB$GrandChildAB" )
214+ final class GrandChildAB extends ChildB {}
215+ }
216+
217+ @ ExpectedGenericString ("public static non-sealed class SealedRootIntf$ChildC" )
218+ non-sealed class ChildC implements SealedRootIntf {
219+ // The subclasses of ChildC do not themselves have to be
220+ // sealed, non-sealed, or final.
221+ @ ExpectedGenericString ("class SealedRootIntf$ChildC$GrandChildACA" )
222+ class GrandChildACA extends ChildC {}
223+
224+ @ ExpectedGenericString ("final class SealedRootIntf$ChildC$GrandChildACB" )
225+ final class GrandChildACB extends ChildC {}
226+
227+ @ ExpectedGenericString ("sealed class SealedRootIntf$ChildC$GrandChildACC" )
228+ sealed class GrandChildACC extends ChildC {
229+ @ ExpectedGenericString ("final class SealedRootIntf$ChildC$GrandChildACC$GreatGrandChildACCA" )
230+ final class GreatGrandChildACCA extends GrandChildACC {}
231+
232+ @ ExpectedGenericString ("non-sealed class SealedRootIntf$ChildC$GrandChildACC$GreatGrandChildACCB" )
233+ non-sealed class GreatGrandChildACCB extends GrandChildACC {}
234+ }
235+ }
236+
237+ @ ExpectedGenericString ("public abstract static sealed interface SealedRootIntf$IntfA" )
238+ sealed interface IntfA extends SealedRootIntf {
239+ @ ExpectedGenericString ("public static non-sealed class SealedRootIntf$IntfA$IntfAImpl" )
240+ non-sealed class IntfAImpl implements IntfA {}
241+ }
242+
243+ @ ExpectedGenericString ("public abstract static non-sealed interface SealedRootIntf$IntfB" )
244+ non-sealed interface IntfB extends SealedRootIntf {
245+ // Check that non-sealing can be allowed with a second superinterface being sealed.
246+ @ ExpectedGenericString ("public static non-sealed class SealedRootIntf$IntfB$IntfAImpl" )
247+ non-sealed class IntfAImpl implements IntfB , IntfA {}
248+ }
249+ }
0 commit comments