xref: /aosp_15_r20/art/test/715-clinit-implicit-parameter-annotations/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.lang.annotation.Annotation;
18*795d594fSAndroid Build Coastguard Worker import java.lang.annotation.Retention;
19*795d594fSAndroid Build Coastguard Worker import java.lang.annotation.RetentionPolicy;
20*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Constructor;
21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Parameter;
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker public class Main {
24*795d594fSAndroid Build Coastguard Worker     // A simple parameter annotation
25*795d594fSAndroid Build Coastguard Worker     @Retention(RetentionPolicy.RUNTIME)
26*795d594fSAndroid Build Coastguard Worker     public @interface AnnotationA {}
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker     // A parameter annotation with additional state
29*795d594fSAndroid Build Coastguard Worker     @Retention(RetentionPolicy.RUNTIME)
30*795d594fSAndroid Build Coastguard Worker     public @interface AnnotationB {
value()31*795d594fSAndroid Build Coastguard Worker         String value() default "default-value";
32*795d594fSAndroid Build Coastguard Worker     }
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker     // An inner class whose constructors with have an implicit
35*795d594fSAndroid Build Coastguard Worker     // argument for the enclosing instance.
36*795d594fSAndroid Build Coastguard Worker     public class Inner {
37*795d594fSAndroid Build Coastguard Worker         private final int number;
38*795d594fSAndroid Build Coastguard Worker         private final String text;
39*795d594fSAndroid Build Coastguard Worker         boolean flag;
40*795d594fSAndroid Build Coastguard Worker 
Inner(@nnotationA int number, String text)41*795d594fSAndroid Build Coastguard Worker         Inner(@AnnotationA int number, String text) {
42*795d594fSAndroid Build Coastguard Worker             this.number = number;
43*795d594fSAndroid Build Coastguard Worker             this.text = text;
44*795d594fSAndroid Build Coastguard Worker             this.flag = false;
45*795d594fSAndroid Build Coastguard Worker         }
46*795d594fSAndroid Build Coastguard Worker 
Inner(@nnotationA int number, String text, @AnnotationB("x") boolean flag)47*795d594fSAndroid Build Coastguard Worker         Inner(@AnnotationA int number, String text, @AnnotationB("x") boolean flag) {
48*795d594fSAndroid Build Coastguard Worker             this.number = number;
49*795d594fSAndroid Build Coastguard Worker             this.text = text;
50*795d594fSAndroid Build Coastguard Worker             this.flag = flag;
51*795d594fSAndroid Build Coastguard Worker         }
52*795d594fSAndroid Build Coastguard Worker     }
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker     // An inner class whose constructors with have no implicit
55*795d594fSAndroid Build Coastguard Worker     // arguments for the enclosing instance.
56*795d594fSAndroid Build Coastguard Worker     public static class StaticInner {
57*795d594fSAndroid Build Coastguard Worker         private final int number;
58*795d594fSAndroid Build Coastguard Worker         private final String text;
59*795d594fSAndroid Build Coastguard Worker         boolean flag;
60*795d594fSAndroid Build Coastguard Worker 
StaticInner(@nnotationA int number, String text)61*795d594fSAndroid Build Coastguard Worker         StaticInner(@AnnotationA int number, String text) {
62*795d594fSAndroid Build Coastguard Worker             this.number = number;
63*795d594fSAndroid Build Coastguard Worker             this.text = text;
64*795d594fSAndroid Build Coastguard Worker             this.flag = false;
65*795d594fSAndroid Build Coastguard Worker         }
66*795d594fSAndroid Build Coastguard Worker 
StaticInner(@nnotationB"foo") int number, String text, @AnnotationA boolean flag)67*795d594fSAndroid Build Coastguard Worker         StaticInner(@AnnotationB("foo") int number, String text, @AnnotationA boolean flag) {
68*795d594fSAndroid Build Coastguard Worker             this.number = number;
69*795d594fSAndroid Build Coastguard Worker             this.text = text;
70*795d594fSAndroid Build Coastguard Worker             this.flag = flag;
71*795d594fSAndroid Build Coastguard Worker         }
72*795d594fSAndroid Build Coastguard Worker     }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker     public enum ImportantNumber {
75*795d594fSAndroid Build Coastguard Worker         ONE(1.0),
76*795d594fSAndroid Build Coastguard Worker         TWO(2.0),
77*795d594fSAndroid Build Coastguard Worker         MANY(3.0, true);
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker         private double doubleValue;
80*795d594fSAndroid Build Coastguard Worker         private boolean isLarge;
81*795d594fSAndroid Build Coastguard Worker 
ImportantNumber(@nnotationA double doubleValue)82*795d594fSAndroid Build Coastguard Worker         ImportantNumber(@AnnotationA double doubleValue) {
83*795d594fSAndroid Build Coastguard Worker             this.doubleValue = doubleValue;
84*795d594fSAndroid Build Coastguard Worker             this.isLarge = false;
85*795d594fSAndroid Build Coastguard Worker         }
86*795d594fSAndroid Build Coastguard Worker 
ImportantNumber(@nnotationB"x") double doubleValue, @AnnotationB("y") boolean isLarge)87*795d594fSAndroid Build Coastguard Worker         ImportantNumber(@AnnotationB("x") double doubleValue, @AnnotationB("y") boolean isLarge) {
88*795d594fSAndroid Build Coastguard Worker             this.doubleValue = doubleValue;
89*795d594fSAndroid Build Coastguard Worker             this.isLarge = isLarge;
90*795d594fSAndroid Build Coastguard Worker         }
91*795d594fSAndroid Build Coastguard Worker     }
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker     public enum BinaryNumber {
94*795d594fSAndroid Build Coastguard Worker         ZERO,
95*795d594fSAndroid Build Coastguard Worker         ONE;
96*795d594fSAndroid Build Coastguard Worker     }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker     private abstract static class AnonymousBase {
AnonymousBase(@nnotationA String s)99*795d594fSAndroid Build Coastguard Worker         public AnonymousBase(@AnnotationA String s) {}
100*795d594fSAndroid Build Coastguard Worker     }
101*795d594fSAndroid Build Coastguard Worker 
annotationToNormalizedString(Annotation annotation)102*795d594fSAndroid Build Coastguard Worker     private static String annotationToNormalizedString(Annotation annotation) {
103*795d594fSAndroid Build Coastguard Worker         // String.replace() to accomodate different representation across VMs.
104*795d594fSAndroid Build Coastguard Worker         return annotation.toString().replace("\"", "");
105*795d594fSAndroid Build Coastguard Worker     }
106*795d594fSAndroid Build Coastguard Worker 
DumpConstructorParameterAnnotations(Class<?> cls)107*795d594fSAndroid Build Coastguard Worker     private static void DumpConstructorParameterAnnotations(Class<?> cls) throws Throwable {
108*795d594fSAndroid Build Coastguard Worker         System.out.println(cls.getName());
109*795d594fSAndroid Build Coastguard Worker         for (Constructor c : cls.getDeclaredConstructors()) {
110*795d594fSAndroid Build Coastguard Worker             System.out.println(" " + c);
111*795d594fSAndroid Build Coastguard Worker             Annotation[][] annotations = c.getParameterAnnotations();
112*795d594fSAndroid Build Coastguard Worker             Parameter[] parameters = c.getParameters();
113*795d594fSAndroid Build Coastguard Worker             for (int i = 0; i < annotations.length; ++i) {
114*795d594fSAndroid Build Coastguard Worker                 // Exercise java.lang.reflect.Executable.getParameterAnnotationsNative()
115*795d594fSAndroid Build Coastguard Worker                 // which retrieves all annotations for the parameters.
116*795d594fSAndroid Build Coastguard Worker                 System.out.print("  Parameter [" + i + "]:");
117*795d594fSAndroid Build Coastguard Worker                 for (Annotation annotation : parameters[i].getAnnotations()) {
118*795d594fSAndroid Build Coastguard Worker                     System.out.println("    Indexed : " + annotationToNormalizedString(annotation));
119*795d594fSAndroid Build Coastguard Worker                 }
120*795d594fSAndroid Build Coastguard Worker                 for (Annotation annotation : annotations[i]) {
121*795d594fSAndroid Build Coastguard Worker                     System.out.println("    Array : " + annotationToNormalizedString(annotation));
122*795d594fSAndroid Build Coastguard Worker                 }
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker                 // Exercise Parameter.getAnnotationNative() with
125*795d594fSAndroid Build Coastguard Worker                 // retrieves a single parameter annotation according to type.
126*795d594fSAndroid Build Coastguard Worker                 Object[] opaqueClasses = new Object[] {AnnotationA.class, AnnotationB.class};
127*795d594fSAndroid Build Coastguard Worker                 for (Object opaqueClass : opaqueClasses) {
128*795d594fSAndroid Build Coastguard Worker                     @SuppressWarnings("unchecked")
129*795d594fSAndroid Build Coastguard Worker                     Class<? extends Annotation> annotationClass =
130*795d594fSAndroid Build Coastguard Worker                             (Class<? extends Annotation>) opaqueClass;
131*795d594fSAndroid Build Coastguard Worker                     Annotation annotation = parameters[i].getDeclaredAnnotation(annotationClass);
132*795d594fSAndroid Build Coastguard Worker                     String hasAnnotation = (annotation != null ? "Yes" : "No");
133*795d594fSAndroid Build Coastguard Worker                     System.out.println("    " + annotationClass.getName() + " " + hasAnnotation);
134*795d594fSAndroid Build Coastguard Worker 
135*795d594fSAndroid Build Coastguard Worker                     Annotation[] parameterAnnotations = parameters[i].getDeclaredAnnotationsByType(annotationClass);
136*795d594fSAndroid Build Coastguard Worker                     for (Annotation parameterAnnotation : parameterAnnotations) {
137*795d594fSAndroid Build Coastguard Worker                         System.out.println("    " + annotationToNormalizedString(parameterAnnotation));
138*795d594fSAndroid Build Coastguard Worker                     }
139*795d594fSAndroid Build Coastguard Worker                 }
140*795d594fSAndroid Build Coastguard Worker             }
141*795d594fSAndroid Build Coastguard Worker         }
142*795d594fSAndroid Build Coastguard Worker     }
143*795d594fSAndroid Build Coastguard Worker 
getLocalClassWithEnclosingInstanceCapture()144*795d594fSAndroid Build Coastguard Worker     private Class<?> getLocalClassWithEnclosingInstanceCapture() {
145*795d594fSAndroid Build Coastguard Worker         class LocalClass {
146*795d594fSAndroid Build Coastguard Worker             private final int integerValue;
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker             LocalClass(@AnnotationA int integerValue) {
149*795d594fSAndroid Build Coastguard Worker                 this.integerValue = integerValue;
150*795d594fSAndroid Build Coastguard Worker             }
151*795d594fSAndroid Build Coastguard Worker         }
152*795d594fSAndroid Build Coastguard Worker         return LocalClass.class;
153*795d594fSAndroid Build Coastguard Worker     }
154*795d594fSAndroid Build Coastguard Worker 
getLocalClassWithEnclosingInstanceAndLocalCapture()155*795d594fSAndroid Build Coastguard Worker     private Class<?> getLocalClassWithEnclosingInstanceAndLocalCapture() {
156*795d594fSAndroid Build Coastguard Worker         final long CAPTURED_VALUE = System.currentTimeMillis();
157*795d594fSAndroid Build Coastguard Worker         class LocalClassWithCapture {
158*795d594fSAndroid Build Coastguard Worker             private final String value;
159*795d594fSAndroid Build Coastguard Worker             private final long capturedValue;
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker             LocalClassWithCapture(@AnnotationA String p1) {
162*795d594fSAndroid Build Coastguard Worker                 this.value = p1;
163*795d594fSAndroid Build Coastguard Worker                 this.capturedValue = CAPTURED_VALUE;
164*795d594fSAndroid Build Coastguard Worker             }
165*795d594fSAndroid Build Coastguard Worker         }
166*795d594fSAndroid Build Coastguard Worker         return LocalClassWithCapture.class;
167*795d594fSAndroid Build Coastguard Worker     }
168*795d594fSAndroid Build Coastguard Worker 
main(String[] args)169*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Throwable {
170*795d594fSAndroid Build Coastguard Worker         // A local class declared in a static context (0 implicit parameters).
171*795d594fSAndroid Build Coastguard Worker         class LocalClassStaticContext {
172*795d594fSAndroid Build Coastguard Worker             private final int value;
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker             LocalClassStaticContext(@AnnotationA int p0) {
175*795d594fSAndroid Build Coastguard Worker                 this.value = p0;
176*795d594fSAndroid Build Coastguard Worker             }
177*795d594fSAndroid Build Coastguard Worker         }
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker         final long CAPTURED_VALUE = System.currentTimeMillis();
180*795d594fSAndroid Build Coastguard Worker         // A local class declared in a static context with a capture (1 implicit parameters).
181*795d594fSAndroid Build Coastguard Worker         class LocalClassStaticContextWithCapture {
182*795d594fSAndroid Build Coastguard Worker             private final long capturedValue;
183*795d594fSAndroid Build Coastguard Worker             private final String argumentValue;
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker             LocalClassStaticContextWithCapture(@AnnotationA String p1) {
186*795d594fSAndroid Build Coastguard Worker                 this.capturedValue = CAPTURED_VALUE;
187*795d594fSAndroid Build Coastguard Worker                 this.argumentValue = p1;
188*795d594fSAndroid Build Coastguard Worker             }
189*795d594fSAndroid Build Coastguard Worker         }
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker         // Another local class declared in a static context with a capture (1 implicit parameters).
192*795d594fSAndroid Build Coastguard Worker         class LocalClassStaticContextWithCaptureAlternateOrdering {
193*795d594fSAndroid Build Coastguard Worker             private final String argumentValue;
194*795d594fSAndroid Build Coastguard Worker             private final long capturedValue;
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker             LocalClassStaticContextWithCaptureAlternateOrdering(@AnnotationA String p1) {
197*795d594fSAndroid Build Coastguard Worker                 this.argumentValue = p1;
198*795d594fSAndroid Build Coastguard Worker                 this.capturedValue = CAPTURED_VALUE;
199*795d594fSAndroid Build Coastguard Worker             }
200*795d594fSAndroid Build Coastguard Worker         }
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(Main.class);
203*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(LocalClassStaticContext.class);
204*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(LocalClassStaticContextWithCapture.class);
205*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(LocalClassStaticContextWithCaptureAlternateOrdering.class);
206*795d594fSAndroid Build Coastguard Worker         Main m = new Main();
207*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(m.getLocalClassWithEnclosingInstanceCapture());
208*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(m.getLocalClassWithEnclosingInstanceAndLocalCapture());
209*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(Inner.class);
210*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(StaticInner.class);
211*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(ImportantNumber.class);
212*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(BinaryNumber.class);
213*795d594fSAndroid Build Coastguard Worker         DumpConstructorParameterAnnotations(new AnonymousBase("") {}.getClass());
214*795d594fSAndroid Build Coastguard Worker     }
215*795d594fSAndroid Build Coastguard Worker }
216