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