diff options
19 files changed, 947 insertions, 746 deletions
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java index 95dad9a217..170c901569 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java @@ -565,6 +565,26 @@ public class ClassTest extends junit.framework.TestCase { "class [Ljava.lang.Object;", clazz.toString()); } + /** + * java.lang.Class#getTypeName() + */ + public void test_getTypeName() throws ClassNotFoundException { + assertEquals("Class toString printed wrong value", + "int", int.class.getTypeName()); + + Class<?> clazz = null; + clazz = Class.forName("[I"); + assertEquals("Class toString printed wrong value", + "int[]", clazz.getTypeName()); + + clazz = Class.forName("java.lang.Object"); + assertEquals("Class toString printed wrong value", + "java.lang.Object", clazz.getTypeName()); + + clazz = Class.forName("[Ljava.lang.Object;"); + assertEquals("Class toString printed wrong value", + "java.lang.Object[]", clazz.getTypeName()); + } // Regression Test for JIRA-2047 public void test_getResourceAsStream_withSharpChar() throws Exception { diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericArrayTypeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericArrayTypeTest.java index 4888fd21f0..58b15e0e0d 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericArrayTypeTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericArrayTypeTest.java @@ -36,6 +36,9 @@ public class GenericArrayTypeTest extends GenericReflectionTestsBase { Field field = clazz.getDeclaredField("array"); Type genericType = field.getGenericType(); assertInstanceOf(GenericArrayType.class, genericType); + assertEquals("T[]", genericType.toString()); + assertEquals("T[]", genericType.getTypeName()); + Type componentType = ((GenericArrayType) genericType).getGenericComponentType(); assertEquals(getTypeParameter(clazz), componentType); assertInstanceOf(TypeVariable.class, componentType); @@ -52,13 +55,17 @@ public class GenericArrayTypeTest extends GenericReflectionTestsBase { Class<? extends B> clazz = GenericArrayTypeTest.B.class; Field field = clazz.getDeclaredField("array"); Type genericType = field.getGenericType(); - assertInstanceOf(GenericArrayType.class, genericType); + + String bName = B.class.getName(); + assertEquals(bName + "<T>[]", genericType.toString()); + assertEquals(bName + "<T>[]", genericType.getTypeName()); + GenericArrayType arrayType = (GenericArrayType) genericType; Type componentType = arrayType.getGenericComponentType(); assertInstanceOf(ParameterizedType.class, componentType); - ParameterizedType parameteriezdType = (ParameterizedType) componentType; - assertEquals(clazz, parameteriezdType.getRawType()); - assertEquals(clazz.getTypeParameters()[0], parameteriezdType.getActualTypeArguments()[0]); + ParameterizedType parameterizedType = (ParameterizedType) componentType; + assertEquals(clazz, parameterizedType.getRawType()); + assertEquals(clazz.getTypeParameters()[0], parameterizedType.getActualTypeArguments()[0]); } } diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/ParameterizedTypeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/ParameterizedTypeTest.java index 3b2614eaea..6004863b4f 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/ParameterizedTypeTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/ParameterizedTypeTest.java @@ -32,6 +32,11 @@ public class ParameterizedTypeTest extends GenericReflectionTestsBase { Class<? extends B> clazz = B.class; Type genericSuperclass = clazz.getGenericSuperclass(); assertInstanceOf(ParameterizedType.class, genericSuperclass); + + String aName = A.class.getName(); + assertEquals(aName + "<java.lang.String>", genericSuperclass.toString()); + assertEquals(aName + "<java.lang.String>", genericSuperclass.getTypeName()); + ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; assertEquals(ParameterizedTypeTest.class, parameterizedType.getOwnerType()); assertEquals(A.class, parameterizedType.getRawType()); @@ -48,6 +53,11 @@ public class ParameterizedTypeTest extends GenericReflectionTestsBase { Class<? extends D> clazz = D.class; Type genericSuperclass = clazz.getGenericSuperclass(); assertInstanceOf(ParameterizedType.class, genericSuperclass); + + String cName = C.class.getName(); + assertEquals(cName + "<T>", genericSuperclass.toString()); + assertEquals(cName + "<T>", genericSuperclass.getTypeName()); + ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; assertEquals(ParameterizedTypeTest.class, parameterizedType.getOwnerType()); assertEquals(C.class, parameterizedType.getRawType()); @@ -70,6 +80,10 @@ public class ParameterizedTypeTest extends GenericReflectionTestsBase { assertEquals(ParameterizedTypeTest.class, parameterizedType.getOwnerType()); assertEquals(E.class, parameterizedType.getRawType()); + String eName = E.class.getName(); + assertEquals(eName + "<T>", parameterizedType.toString()); + assertEquals(eName + "<T>", parameterizedType.getTypeName()); + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); assertLenghtOne(actualTypeArguments); assertEquals(getTypeParameter(clazz), actualTypeArguments[0]); diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/TypeVariableTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/TypeVariableTest.java index d1c7ea9954..8f93da4841 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/TypeVariableTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/TypeVariableTest.java @@ -35,6 +35,8 @@ public class TypeVariableTest extends GenericReflectionTestsBase { TypeVariable<Class> typeVariable = typeParameters[0]; assertEquals(clazz, typeVariable.getGenericDeclaration()); assertEquals("T", typeVariable.getName()); + assertEquals("T", typeVariable.toString()); + assertEquals("T", typeVariable.getTypeName()); Type[] bounds = typeVariable.getBounds(); assertLenghtOne(bounds); assertEquals(Object.class, bounds[0]); @@ -51,6 +53,8 @@ public class TypeVariableTest extends GenericReflectionTestsBase { TypeVariable<Method> typeVariable = typeParameters[0]; assertEquals(method, typeVariable.getGenericDeclaration()); assertEquals("T", typeVariable.getName()); + assertEquals("T", typeVariable.toString()); + assertEquals("T", typeVariable.getTypeName()); Type[] bounds = typeVariable.getBounds(); assertLenghtOne(bounds); assertEquals(Object.class, bounds[0]); @@ -67,6 +71,8 @@ public class TypeVariableTest extends GenericReflectionTestsBase { TypeVariable<?> typeVariable = typeParameters[0]; assertEquals(constructor, typeVariable.getGenericDeclaration()); assertEquals("T", typeVariable.getName()); + assertEquals("T", typeVariable.toString()); + assertEquals("T", typeVariable.getTypeName()); Type[] bounds = typeVariable.getBounds(); assertLenghtOne(bounds); assertEquals(Object.class, bounds[0]); @@ -79,13 +85,18 @@ public class TypeVariableTest extends GenericReflectionTestsBase { assertEquals(3, typeParameters.length); assertEquals("Q", typeParameters[0].getName()); assertEquals(clazz, typeParameters[0].getGenericDeclaration()); + assertEquals("Q", typeParameters[0].toString()); + assertEquals("Q", typeParameters[0].getTypeName()); assertEquals("R", typeParameters[1].getName()); assertEquals(clazz, typeParameters[1].getGenericDeclaration()); + assertEquals("R", typeParameters[1].toString()); + assertEquals("R", typeParameters[1].getTypeName()); assertEquals("S", typeParameters[2].getName()); assertEquals(clazz, typeParameters[2].getGenericDeclaration()); - + assertEquals("S", typeParameters[2].toString()); + assertEquals("S", typeParameters[2].getTypeName()); } static class E { @@ -99,12 +110,18 @@ public class TypeVariableTest extends GenericReflectionTestsBase { assertEquals(3, typeParameters.length); assertEquals("Q", typeParameters[0].getName()); assertEquals(method, typeParameters[0].getGenericDeclaration()); + assertEquals("Q", typeParameters[0].toString()); + assertEquals("Q", typeParameters[0].getTypeName()); assertEquals("R", typeParameters[1].getName()); assertEquals(method, typeParameters[1].getGenericDeclaration()); + assertEquals("R", typeParameters[1].toString()); + assertEquals("R", typeParameters[1].getTypeName()); assertEquals("S", typeParameters[2].getName()); assertEquals(method, typeParameters[2].getGenericDeclaration()); + assertEquals("S", typeParameters[2].toString()); + assertEquals("S", typeParameters[2].getTypeName()); } static class F { @@ -118,12 +135,18 @@ public class TypeVariableTest extends GenericReflectionTestsBase { assertEquals(3, typeParameters.length); assertEquals("Q", typeParameters[0].getName()); assertEquals(constructor, typeParameters[0].getGenericDeclaration()); + assertEquals("Q", typeParameters[0].toString()); + assertEquals("Q", typeParameters[0].getTypeName()); assertEquals("R", typeParameters[1].getName()); assertEquals(constructor, typeParameters[1].getGenericDeclaration()); + assertEquals("R", typeParameters[1].toString()); + assertEquals("R", typeParameters[1].getTypeName()); assertEquals("S", typeParameters[2].getName()); assertEquals(constructor, typeParameters[2].getGenericDeclaration()); + assertEquals("S", typeParameters[2].toString()); + assertEquals("S", typeParameters[2].getTypeName()); } static class G <T extends Number>{} @@ -135,6 +158,8 @@ public class TypeVariableTest extends GenericReflectionTestsBase { Type[] bounds = typeVariable.getBounds(); assertLenghtOne(bounds); assertEquals(Number.class, bounds[0]); + assertEquals("T", typeVariable.toString()); + assertEquals("T", typeVariable.getTypeName()); } static class H <T extends Number & Serializable >{} @@ -146,5 +171,7 @@ public class TypeVariableTest extends GenericReflectionTestsBase { assertEquals(2, bounds.length); assertEquals(Number.class, bounds[0]); assertEquals(Serializable.class, bounds[1]); + assertEquals("T", typeVariable.toString()); + assertEquals("T", typeVariable.getTypeName()); } } diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/WildcardTypeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/WildcardTypeTest.java index e29fd474ca..9d3a8b0dbd 100644 --- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/WildcardTypeTest.java +++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/WildcardTypeTest.java @@ -76,6 +76,8 @@ public class WildcardTypeTest extends GenericReflectionTestsBase { assertInstanceOf(WildcardType.class, actualTypeArguments[0]); WildcardType wildcardType = (WildcardType) actualTypeArguments[0]; + assertEquals("? super T", wildcardType.toString()); + assertEquals("? super T", wildcardType.getTypeName()); Type[] lowerBounds = wildcardType.getLowerBounds(); assertLenghtOne(lowerBounds); @@ -97,6 +99,8 @@ public class WildcardTypeTest extends GenericReflectionTestsBase { assertInstanceOf(WildcardType.class, actualTypeArguments[0]); WildcardType wildcardType = (WildcardType) actualTypeArguments[0]; + assertEquals("? extends T", wildcardType.toString()); + assertEquals("? extends T", wildcardType.getTypeName()); assertLenghtZero(wildcardType.getLowerBounds()); Type[] upperBounds = wildcardType.getUpperBounds(); diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java index 01267655a2..cd2666f605 100644 --- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java +++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java @@ -33,8 +33,8 @@ package java.lang.reflect; import com.android.dex.Dex; + import java.lang.annotation.Annotation; -import java.util.List; import libcore.reflect.GenericSignatureParser; import libcore.reflect.ListOfTypes; import libcore.reflect.Types; @@ -44,27 +44,33 @@ import libcore.util.EmptyArray; * This class represents an abstract method. Abstract methods are either methods or constructors. * @hide */ -public abstract class AbstractMethod extends AccessibleObject { +public abstract class AbstractMethod extends Executable { /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */ - protected int accessFlags; + @SuppressWarnings("unused") // set by runtime + private int accessFlags; /** - * The ArtMethod associated with this Method, requried for dispatching due to entrypoints + * The ArtMethod associated with this Method, required for dispatching due to entrypoints * Classloader is held live by the declaring class. * Hidden to workaround b/16828157. * @hide */ - protected long artMethod; + @SuppressWarnings("unused") // set by runtime + private long artMethod; /** Method's declaring class */ - protected Class<?> declaringClass; + @SuppressWarnings("unused") // set by runtime + private Class<?> declaringClass; /** Overriden method's declaring class (same as declaringClass unless declaringClass - * is a proxy class) */ - protected Class<?> declaringClassOfOverriddenMethod; + * is a proxy class) + */ + @SuppressWarnings("unused") // set by runtime + private Class<?> declaringClassOfOverriddenMethod; /** The method index of this method within its defining dex file */ - protected int dexMethodIndex; + @SuppressWarnings("unused") // set by runtime + private int dexMethodIndex; /** * Hidden to workaround b/16828157. @@ -73,10 +79,6 @@ public abstract class AbstractMethod extends AccessibleObject { protected AbstractMethod() { } - public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { - return super.getAnnotation(annotationClass); - } - /** * We insert native method stubs for abstract methods so we don't have to * check the access flags at the time of the method call. This results in @@ -99,65 +101,38 @@ public abstract class AbstractMethod extends AccessibleObject { return flags & 0xffff; // mask out bits not used by Java } - int getModifiers() { + // Overrides {@link Executable#getModifiers()} - for ART behavior see fixMethodFlags(). + @Override + public int getModifiers() { return fixMethodFlags(accessFlags); } - boolean isVarArgs() { - return (accessFlags & Modifier.VARARGS) != 0; - } - - boolean isBridge() { - return (accessFlags & Modifier.BRIDGE) != 0; - } - - boolean isSynthetic() { + // Overrides {@link Executable#isSynthetic()} - we can do it cheaply here. + @Override + public boolean isSynthetic() { return (accessFlags & Modifier.SYNTHETIC) != 0; } - boolean isDefault() { - return (accessFlags & Modifier.DEFAULT) != 0; - } - - /** - * @hide - */ - public final int getAccessFlags() { - return accessFlags; + // Overrides {@link Executable#isVarArgs()} - we can do it cheaply here. + @Override + public boolean isVarArgs() { + return (accessFlags & Modifier.VARARGS) != 0; } - /** - * Returns the class that declares this constructor or method. - */ - Class<?> getDeclaringClass() { + @Override + public Class<?> getDeclaringClass() { return declaringClass; } /** - * Returns the index of this method's ID in its dex file. - * - * @hide - */ - public final int getDexMethodIndex() { - return dexMethodIndex; - } - - /** - * Returns the name of the method or constructor represented by this - * instance. - * - * @return the name of this method - */ - abstract public String getName(); - - /** * Returns an array of {@code Class} objects associated with the parameter types of this * abstract method. If the method was declared with no parameters, an * empty array will be returned. * * @return the parameter types */ - Class<?>[] getParameterTypes() { + @Override + public Class<?>[] getParameterTypes() { Dex dex = declaringClassOfOverriddenMethod.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); if (types.length == 0) { @@ -171,30 +146,23 @@ public abstract class AbstractMethod extends AccessibleObject { return parametersArray; } - /** - * Returns true if {@code other} has the same declaring class, name, - * parameters and return type as this method. - */ - @Override public boolean equals(Object other) { - if (!(other instanceof AbstractMethod)) { - return false; - } - // Exactly one instance of each member in this runtime, todo, does this work for proxies? - AbstractMethod otherMethod = (AbstractMethod) other; - return this.declaringClass == otherMethod.declaringClass && - this.dexMethodIndex == otherMethod.dexMethodIndex; - } - - String toGenericString() { - return toGenericStringHelper(); + @Override + public int getParameterCount() { + Dex dex = declaringClassOfOverriddenMethod.getDex(); + short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); + return types.length; } - Type[] getGenericParameterTypes() { - return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false); + @Override + public Type[] getGenericParameterTypes() { + return Types.getTypeArray( + getMethodOrConstructorGenericInfoInternal().genericParameterTypes, false); } - Type[] getGenericExceptionTypes() { - return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false); + @Override + public Type[] getGenericExceptionTypes() { + return Types.getTypeArray( + getMethodOrConstructorGenericInfoInternal().genericExceptionTypes, false); } @Override public native Annotation[] getDeclaredAnnotations(); @@ -205,22 +173,33 @@ public abstract class AbstractMethod extends AccessibleObject { } return isAnnotationPresentNative(annotationType); } - private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType); - public Annotation[] getAnnotations() { - return super.getAnnotations(); + @Override + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + if (annotationClass == null) { + throw new NullPointerException("annotationClass == null"); + } + return getAnnotationNative(annotationClass); } + private native <T extends Annotation> T getAnnotationNative(Class<T> annotationClass); + + @Override + public Annotation[][] getParameterAnnotations() { + Annotation[][] parameterAnnotations = getParameterAnnotationsNative(); + if (parameterAnnotations == null) { + parameterAnnotations = new Annotation[getParameterTypes().length][0]; + } + return parameterAnnotations; + } + private native Annotation[][] getParameterAnnotationsNative(); /** - * Returns an array of arrays that represent the annotations of the formal - * parameters of this method. If there are no parameters on this method, - * then an empty array is returned. If there are no annotations set, then - * and array of empty arrays is returned. - * - * @return an array of arrays of {@code Annotation} instances + * @hide */ - public abstract Annotation[][] getParameterAnnotations(); + public final int getAccessFlags() { + return accessFlags; + } /** * Returns the constructor's signature in non-printable form. This is called @@ -250,28 +229,15 @@ public abstract class AbstractMethod extends AccessibleObject { /** * Returns generic information associated with this method/constructor member. */ - final GenericInfo getMethodOrConstructorGenericInfo() { + final GenericInfo getMethodOrConstructorGenericInfoInternal() { String signatureAttribute = getSignatureAttribute(); - Member member; - Class<?>[] exceptionTypes; - boolean method = this instanceof Method; - if (method) { - Method m = (Method) this; - member = m; - exceptionTypes = m.getExceptionTypes(); - } else { - Constructor<?> c = (Constructor<?>) this; - member = c; - exceptionTypes = c.getExceptionTypes(); - } + Class<?>[] exceptionTypes = this.getExceptionTypes(); GenericSignatureParser parser = - new GenericSignatureParser(member.getDeclaringClass().getClassLoader()); - if (method) { - parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes); + new GenericSignatureParser(this.getDeclaringClass().getClassLoader()); + if (this instanceof Method) { + parser.parseForMethod(this, signatureAttribute, exceptionTypes); } else { - parser.parseForConstructor((GenericDeclaration) this, - signatureAttribute, - exceptionTypes); + parser.parseForConstructor(this, signatureAttribute, exceptionTypes); } return new GenericInfo(parser.exceptionTypes, parser.parameterTypes, parser.returnType, parser.formalTypeParameters); @@ -288,10 +254,13 @@ public abstract class AbstractMethod extends AccessibleObject { } return result.toString(); } - private native String[] getSignatureAnnotation(); - protected boolean equalMethodParameters(Class<?>[] params) { + final boolean equalNameAndParametersInternal(Method m) { + return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes()); + } + + private boolean equalMethodParameters(Class<?>[] params) { Dex dex = declaringClassOfOverriddenMethod.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); if (types.length != params.length) { @@ -305,7 +274,7 @@ public abstract class AbstractMethod extends AccessibleObject { return true; } - protected int compareParameters(Class<?>[] params) { + final int compareMethodParametersInternal(Class<?>[] params) { Dex dex = declaringClassOfOverriddenMethod.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); int length = Math.min(types.length, params.length); @@ -322,51 +291,26 @@ public abstract class AbstractMethod extends AccessibleObject { return types.length - params.length; } - /** - * Helper for Method and Constructor for toGenericString - */ - final String toGenericStringHelper() { - StringBuilder sb = new StringBuilder(80); - GenericInfo info = getMethodOrConstructorGenericInfo(); - int modifiers = ((Member)this).getModifiers(); - // append modifiers if any - if (modifiers != 0) { - sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' '); - } - // append type parameters - if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) { - sb.append('<'); - for (int i = 0; i < info.formalTypeParameters.length; i++) { - Types.appendGenericType(sb, info.formalTypeParameters[i]); - if (i < info.formalTypeParameters.length - 1) { - sb.append(","); - } - } - sb.append("> "); - } - Class<?> declaringClass = ((Member) this).getDeclaringClass(); - if (this instanceof Constructor) { - // append constructor name - Types.appendTypeName(sb, declaringClass); - } else { - // append return type - Types.appendGenericType(sb, Types.getType(info.genericReturnType)); - sb.append(' '); - // append method name - Types.appendTypeName(sb, declaringClass); - sb.append(".").append(((Method) this).getName()); - } - // append parameters - sb.append('('); - Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes()); - sb.append(')'); - // append exceptions if any - Type[] genericExceptionTypeArray = - Types.getTypeArray(info.genericExceptionTypes, false); - if (genericExceptionTypeArray.length > 0) { - sb.append(" throws "); - Types.appendArrayGenericType(sb, genericExceptionTypeArray); - } - return sb.toString(); + final String getMethodNameInternal() { + Dex dex = declaringClassOfOverriddenMethod.getDex(); + int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex); + return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex); + } + + final Class<?> getMethodReturnTypeInternal() { + Dex dex = declaringClassOfOverriddenMethod.getDex(); + int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); + // Note, in the case of a Proxy the dex cache types are equal. + return declaringClassOfOverriddenMethod.getDexCacheType(dex, returnTypeIndex); + } + + /** A cheap implementation for {@link Method#isDefault()}. */ + final boolean isDefaultMethodInternal() { + return (accessFlags & Modifier.DEFAULT) != 0; + } + + /** A cheap implementation for {@link Method#isBridge()}. */ + final boolean isBridgeMethodInternal() { + return (accessFlags & Modifier.BRIDGE) != 0; } } diff --git a/luni/src/main/java/libcore/reflect/AnnotatedElements.java b/luni/src/main/java/libcore/reflect/AnnotatedElements.java index 2fe2d2b25c..2b4fb5ea28 100644 --- a/luni/src/main/java/libcore/reflect/AnnotatedElements.java +++ b/luni/src/main/java/libcore/reflect/AnnotatedElements.java @@ -32,45 +32,15 @@ import java.util.ArrayList; */ public final class AnnotatedElements { /** - * Default implementation for {@link AnnotatedElement#getDeclaredAnnotation}. - * - * @return Directly present annotation of type {@code annotationClass} for {@code element}, - * or {@code null} if none was found. - */ - public static <T extends Annotation> T getDeclaredAnnotation(AnnotatedElement element, - Class<T> annotationClass) { - if (annotationClass == null) { - throw new NullPointerException("annotationClass"); - } - - Annotation[] annotations = element.getDeclaredAnnotations(); - - // Safeguard: getDeclaredAnnotations should never return null. - if (annotations == null) { - return null; - } - - // The annotation might be directly present: - // Return the first (and only) annotation whose class matches annotationClass. - for (int i = 0; i < annotations.length; ++i) { - if (annotationClass.isInstance(annotations[i])) { - return (T)annotations[i]; // Safe because of above guard. - } - } - - // The annotation was *not* directly present: - // If the array was empty, or we found no matches, return null. - return null; - } - - /** - * Default implementation for {@link AnnotatedElement#getDeclaredAnnotationsByType}. + * Default implementation of {@link AnnotatedElement#getDeclaredAnnotationsByType}, and + * {@link AnnotatedElement#getAnnotationsByType} for elements that do not support annotation + * inheritance. * * @return Directly/indirectly present list of annotations of type {@code annotationClass} for * {@code element}, or an empty array if none were found. */ - public static <T extends Annotation> T[] getDeclaredAnnotationsByType(AnnotatedElement element, - Class<T> annotationClass) { + public static <T extends Annotation> T[] getDirectOrIndirectAnnotationsByType( + AnnotatedElement element, Class<T> annotationClass) { if (annotationClass == null) { throw new NullPointerException("annotationClass"); } @@ -182,37 +152,7 @@ public final class AnnotatedElements { return (repeatableAnnotation == null) ? null : repeatableAnnotation.value(); } - /** - * Default implementation of {@link AnnotatedElement#getAnnotationsByType}. - * - * <p> - * This method does not handle inherited annotations and is - * intended for use for {@code Method}, {@code Field}, {@code Package}. - * The {@link Class#getAnnotationsByType} is implemented explicitly. - * </p> - * - * @return Associated annotations of type {@code annotationClass} for {@code element}. - */ - public static <T extends Annotation> T[] getAnnotationsByType(AnnotatedElement element, - Class<T> annotationClass) { - if (annotationClass == null) { - throw new NullPointerException("annotationClass"); - } - - // Find any associated annotations [directly or repeatably (indirectly) present on this class]. - T[] annotations = element.getDeclaredAnnotationsByType(annotationClass); - if (annotations == null) { - throw new AssertionError("annotations must not be null"); // Internal error. - } - - // If nothing was found, we would look for associated annotations recursively up to the root - // class. However this can only happen if AnnotatedElement is a Class, which is handled - // in the Class override of this method. - return annotations; - } - private AnnotatedElements() { - throw new AssertionError("Instances of AnnotatedElements not allowed"); } } diff --git a/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java b/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java index 3ae44c69fc..3093bbdec9 100644 --- a/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java +++ b/luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java @@ -45,6 +45,13 @@ public final class ConstructorTest extends TestCase { assertEquals(expectedParameters[0], parameters[0]); } + public void test_getParameterCount() throws Exception { + Class[] expectedParameters = new Class[] { Object.class }; + Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters); + int count = constructor.getParameterCount(); + assertEquals(1, count); + } + public void testGetConstructorWithNullArgumentsArray() throws Exception { Constructor<?> constructor = ConstructorTestHelper.class.getConstructor((Class[]) null); assertEquals(0, constructor.getParameterTypes().length); diff --git a/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java b/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java index a8764c2e98..5cb88d6cf1 100644 --- a/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java +++ b/luni/src/test/java/libcore/java/lang/reflect/MethodTest.java @@ -53,6 +53,13 @@ public final class MethodTest extends TestCase { assertEquals(expectedParameters[0], parameters[0]); } + public void test_getParameterCount() throws Exception { + Class[] expectedParameters = new Class[] { Object.class }; + Method method = MethodTestHelper.class.getMethod("m2", expectedParameters); + int count = method.getParameterCount(); + assertEquals(1, count); + } + public void testGetMethodWithPrivateMethodAndInterfaceMethod() throws Exception { assertEquals(InterfaceA.class, Sub.class.getMethod("a").getDeclaringClass()); } @@ -222,11 +229,9 @@ public final class MethodTest extends TestCase { Collections.class, "sort", List.class, Comparator.class); // Java 8 language addition: default interface method. - // Commented until http://b/28666126 is complete: toString() for default methods not - // implemented yet. - // checkToString( - // "public default java.util.function.Function java.util.function.Function.compose(java.util.function.Function)", - // Function.class, "compose", Function.class); + checkToString( + "public default java.util.function.Function java.util.function.Function.compose(java.util.function.Function)", + Function.class, "compose", Function.class); // Java 8 language addition: static interface method. checkToString( "public static java.util.function.Function java.util.function.Function.identity()", @@ -262,11 +267,9 @@ public final class MethodTest extends TestCase { // Java 8 language addition: default interface method. - // Commented until http://b/28666126 is complete: toGenericString() for default methods not - // implemented yet. - // checkToGenericString( - // "public default <V> java.util.function.Function<V, R> java.util.function.Function.compose(java.util.function.Function<? super V, ? extends T>)", - // Function.class, "compose", Function.class); + checkToGenericString( + "public default <V> java.util.function.Function<V, R> java.util.function.Function.compose(java.util.function.Function<? super V, ? extends T>)", + Function.class, "compose", Function.class); // Java 8 language addition: static interface method. checkToGenericString( "public static <T> java.util.function.Function<T, T> java.util.function.Function.identity()", diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java index 44eadce141..7573fc39f1 100644 --- a/ojluni/src/main/java/java/lang/Class.java +++ b/ojluni/src/main/java/java/lang/Class.java @@ -26,35 +26,36 @@ package java.lang; +import com.android.dex.Dex; + +import java.io.InputStream; +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; -import java.lang.reflect.Member; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Member; import java.lang.reflect.Method; -import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.List; +import java.util.Collections; import java.util.HashMap; -import sun.reflect.CallerSensitive; -import java.lang.annotation.Inherited; -import java.lang.annotation.Annotation; - -import java.io.Serializable; -import com.android.dex.Dex; -import dalvik.system.VMStack; -import libcore.reflect.InternalNames; +import java.util.List; import libcore.reflect.GenericSignatureParser; +import libcore.reflect.InternalNames; import libcore.reflect.Types; import libcore.util.BasicLruCache; import libcore.util.CollectionUtils; import libcore.util.EmptyArray; -import java.util.Collections; + +import dalvik.system.VMStack; +import sun.reflect.CallerSensitive; /** * Instances of the class {@code Class} represent classes and @@ -1157,6 +1158,33 @@ public final return simpleName; } + + /** + * Return an informative string for the name of this type. + * + * @return an informative string for the name of this type + * @since 1.8 + */ + public String getTypeName() { + if (isArray()) { + try { + Class<?> cl = this; + int dimensions = 0; + while (cl.isArray()) { + dimensions++; + cl = cl.getComponentType(); + } + StringBuilder sb = new StringBuilder(); + sb.append(cl.getName()); + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + return sb.toString(); + } catch (Throwable e) { /*FALLTHRU*/ } + } + return getName(); + } + /** * Returns the canonical name of the underlying class as * defined by the Java Language Specification. Returns null if diff --git a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java index 1fbf178cf0..22ecfb7489 100644 --- a/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java +++ b/ojluni/src/main/java/java/lang/reflect/AccessibleObject.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,8 @@ package java.lang.reflect; -import java.security.AccessController; -import sun.reflect.Reflection; import java.lang.annotation.Annotation; -import libcore.reflect.AnnotatedElements; - /** * The AccessibleObject class is the base class for Field, Method and * Constructor objects. It provides the ability to flag a reflected @@ -119,7 +115,8 @@ public class AccessibleObject implements AnnotatedElement { setAccessible0(this, flag); } - /* Check that you aren't exposing java.lang.Class.<init>. */ + /* Check that you aren't exposing java.lang.Class.<init> or sensitive + fields in java.lang.Class. */ private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException { @@ -174,6 +171,25 @@ public class AccessibleObject implements AnnotatedElement { } /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + @Override + public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { + return AnnotatedElement.super.isAnnotationPresent(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + + /** * @since 1.5 */ public Annotation[] getAnnotations() { @@ -181,6 +197,30 @@ public class AccessibleObject implements AnnotatedElement { } /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotation is the same as + // getAnnotation. + return getAnnotation(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotationsByType is the same as + // getAnnotationsByType. + return getAnnotationsByType(annotationClass); + } + + /** * @since 1.5 */ public Annotation[] getDeclaredAnnotations() { diff --git a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java index 9d2158c012..96be4e4b4d 100644 --- a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java +++ b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2016 The Android Open Source Project - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package java.lang.reflect; import java.lang.annotation.Annotation; +import java.util.Objects; import libcore.reflect.AnnotatedElements; /** @@ -102,17 +103,19 @@ public interface AnnotatedElement { Annotation[] getAnnotations(); /** - * Returns all annotations that are directly present on this - * element. Unlike the other methods in this interface, this method - * ignores inherited annotations. (Returns an array of length zero if - * no annotations are directly present on this element.) The caller of - * this method is free to modify the returned array; it will have no - * effect on the arrays returned to other callers. + * Returns an associated list of annotations on {@code this} element, + * whose class is {@code annotationClass}, or an empty array if nothing was found. * - * @return All annotations directly present on this element - * @since 1.5 + * @since 1.8 */ - Annotation[] getDeclaredAnnotations(); + default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { + // This method does not handle inherited annotations and is intended for use for + // {@code Method}, {@code Field}, {@code Package}. The {@link Class#getAnnotationsByType} + // is implemented explicitly. Therefore this implementation does not fulfill the documented + // default implementation for {@link AnnotatedElement#getAnnotationsByType(Class)} but in an + // undetectable way because Class is final. + return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); + } /** * Returns a directly-present annotation on {@code this} element, whose class is @@ -121,7 +124,16 @@ public interface AnnotatedElement { * @since 1.8 */ default <T extends Annotation> Annotation getDeclaredAnnotation(Class<T> annotationClass) { - return AnnotatedElements.getDeclaredAnnotation(this, annotationClass); + Objects.requireNonNull(annotationClass); + // Loop over all directly-present annotations looking for a matching one + for (Annotation annotation : getDeclaredAnnotations()) { + if (annotationClass.equals(annotation.annotationType())) { + // More robust to do a dynamic cast at runtime instead + // of compile-time only. + return annotationClass.cast(annotation); + } + } + return null; } /** @@ -131,16 +143,19 @@ public interface AnnotatedElement { * @since 1.8 */ default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { - return AnnotatedElements.getDeclaredAnnotationsByType(this, annotationClass); + return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); } /** - * Returns an associated list of annotations on {@code this} element, - * whose class is {@code annotationClass}, or an empty array if nothing was found. + * Returns all annotations that are directly present on this + * element. Unlike the other methods in this interface, this method + * ignores inherited annotations. (Returns an array of length zero if + * no annotations are directly present on this element.) The caller of + * this method is free to modify the returned array; it will have no + * effect on the arrays returned to other callers. * - * @since 1.8 + * @return All annotations directly present on this element + * @since 1.5 */ - default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { - return AnnotatedElements.getAnnotationsByType(this, annotationClass); - } + Annotation[] getDeclaredAnnotations(); } diff --git a/ojluni/src/main/java/java/lang/reflect/Constructor.java b/ojluni/src/main/java/java/lang/reflect/Constructor.java index 9742f0cb50..76ecabf778 100644 --- a/ojluni/src/main/java/java/lang/reflect/Constructor.java +++ b/ojluni/src/main/java/java/lang/reflect/Constructor.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,7 @@ package java.lang.reflect; -import sun.reflect.CallerSensitive; import java.util.Comparator; -import java.util.List; import libcore.reflect.Types; import java.lang.annotation.Annotation; @@ -53,9 +51,7 @@ import java.lang.annotation.Annotation; * @author Kenneth Russell * @author Nakul Saraiya */ -public final class Constructor<T> extends AbstractMethod implements - GenericDeclaration, - Member { +public final class Constructor<T> extends AbstractMethod { private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method. private final Class<?> serializationClass; @@ -79,10 +75,12 @@ public final class Constructor<T> extends AbstractMethod implements } /** - * Returns the {@code Class} object representing the class that declares - * the constructor represented by this {@code Constructor} object. + * {@inheritDoc} */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) public Class<T> getDeclaringClass() { + // Android-changed: This is handled by AbstractMethod. return (Class<T>) super.getDeclaringClass(); } @@ -90,124 +88,79 @@ public final class Constructor<T> extends AbstractMethod implements * Returns the name of this constructor, as a string. This is * the binary name of the constructor's declaring class. */ + @Override public String getName() { return getDeclaringClass().getName(); } /** - * Returns the Java language modifiers for the constructor - * represented by this {@code Constructor} object, as an integer. The - * {@code Modifier} class should be used to decode the modifiers. - * - * @see Modifier + * {@inheritDoc} */ + @Override public int getModifiers() { + // Android-changed: This is handled by AbstractMethod. return super.getModifiers(); } /** - * Returns an array of {@code TypeVariable} objects that represent the - * type variables declared by the generic declaration represented by this - * {@code GenericDeclaration} object, in declaration order. Returns an - * array of length 0 if the underlying generic declaration declares no type - * variables. - * - * @return an array of {@code TypeVariable} objects that represent - * the type variables declared by this generic declaration - * @throws GenericSignatureFormatError if the generic - * signature of this generic declaration does not conform to - * the format specified in - * <cite>The Java™ Virtual Machine Specification</cite> + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} * @since 1.5 */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) public TypeVariable<Constructor<T>>[] getTypeParameters() { - GenericInfo info = getMethodOrConstructorGenericInfo(); - return (TypeVariable<Constructor<T>>[]) info.formalTypeParameters.clone(); + // Android-changed: This is mostly handled by AbstractMethod. + GenericInfo info = getMethodOrConstructorGenericInfoInternal(); + return (TypeVariable<Constructor<T>>[]) info.formalTypeParameters.clone(); } - /** - * Returns an array of {@code Class} objects that represent the formal - * parameter types, in declaration order, of the constructor - * represented by this {@code Constructor} object. Returns an array of - * length 0 if the underlying constructor takes no parameters. - * - * @return the parameter types for the constructor this object - * represents + * {@inheritDoc} */ + @Override public Class<?>[] getParameterTypes() { + // Android-changed: This is handled by AbstractMethod. return super.getParameterTypes(); } + /** + * {@inheritDoc} + */ + public int getParameterCount() { + // Android-changed: This is handled by AbstractMethod. + return super.getParameterCount(); + } /** - * Returns an array of {@code Type} objects that represent the formal - * parameter types, in declaration order, of the method represented by - * this {@code Constructor} object. Returns an array of length 0 if the - * underlying method takes no parameters. - * - * <p>If a formal parameter type is a parameterized type, - * the {@code Type} object returned for it must accurately reflect - * the actual type parameters used in the source code. - * - * <p>If a formal parameter type is a type variable or a parameterized - * type, it is created. Otherwise, it is resolved. - * - * @return an array of {@code Type}s that represent the formal - * parameter types of the underlying method, in declaration order - * @throws GenericSignatureFormatError - * if the generic method signature does not conform to the format - * specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if any of the parameter - * types of the underlying method refers to a non-existent type - * declaration - * @throws MalformedParameterizedTypeException if any of - * the underlying method's parameter types refer to a parameterized - * type that cannot be instantiated for any reason + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ + @Override public Type[] getGenericParameterTypes() { return super.getGenericParameterTypes(); } - /** - * Returns an array of {@code Class} objects that represent the types - * of exceptions declared to be thrown by the underlying constructor - * represented by this {@code Constructor} object. Returns an array of - * length 0 if the constructor declares no exceptions in its {@code throws} clause. - * - * @return the exception types declared as being thrown by the - * constructor this object represents + * {@inheritDoc} */ + @Override public native Class<?>[] getExceptionTypes(); /** - * Returns an array of {@code Type} objects that represent the - * exceptions declared to be thrown by this {@code Constructor} object. - * Returns an array of length 0 if the underlying method declares - * no exceptions in its {@code throws} clause. - * - * <p>If an exception type is a type variable or a parameterized - * type, it is created. Otherwise, it is resolved. - * - * @return an array of Types that represent the exception types - * thrown by the underlying method - * @throws GenericSignatureFormatError - * if the generic method signature does not conform to the format - * specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if the underlying method's - * {@code throws} clause refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if - * the underlying method's {@code throws} clause refers to a - * parameterized type that cannot be instantiated for any reason + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ - public Type[] getGenericExceptionTypes() { - return super.getGenericExceptionTypes(); - } + @Override + public Type[] getGenericExceptionTypes() { + return super.getGenericExceptionTypes(); + } /** * Compares this {@code Constructor} against the specified object. @@ -219,17 +172,8 @@ public final class Constructor<T> extends AbstractMethod implements if (obj != null && obj instanceof Constructor) { Constructor<?> other = (Constructor<?>)obj; if (getDeclaringClass() == other.getDeclaringClass()) { - /* Avoid unnecessary cloning */ // Android changed: Use getParameterTypes. - Class<?>[] params1 = getParameterTypes(); - Class<?>[] params2 = other.getParameterTypes(); - if (params1.length == params2.length) { - for (int i = 0; i < params1.length; i++) { - if (params1[i] != params2[i]) - return false; - } - return true; - } + return equalParamTypes(getParameterTypes(), other.getParameterTypes()); } } return false; @@ -258,36 +202,21 @@ public final class Constructor<T> extends AbstractMethod implements * modifiers {@code public}, {@code protected} or * {@code private}. Only one of these may appear, or none if the * constructor has default (package) access. + * + * @return a string describing this {@code Constructor} + * @jls 8.8.3. Constructor Modifiers */ public String toString() { - try { - StringBuffer sb = new StringBuffer(); - int mod = getModifiers() & Modifier.constructorModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod) + " "); - } - sb.append(Field.getTypeName(getDeclaringClass())); - sb.append("("); - Class<?>[] params = getParameterTypes(); - for (int j = 0; j < params.length; j++) { - sb.append(Field.getTypeName(params[j])); - if (j < (params.length - 1)) - sb.append(","); - } - sb.append(")"); - Class<?>[] exceptions = getExceptionTypes(); - if (exceptions.length > 0) { - sb.append(" throws "); - for (int k = 0; k < exceptions.length; k++) { - sb.append(exceptions[k].getName()); - if (k < (exceptions.length - 1)) - sb.append(","); - } - } - return sb.toString(); - } catch (Exception e) { - return "<" + e + ">"; - } + // Android changed: Use getParameterTypes. + return sharedToString(Modifier.constructorModifiers(), + false, + getParameterTypes(), + getExceptionTypes()); + } + + @Override + void specificToStringHeader(StringBuilder sb) { + sb.append(getDeclaringClass().getTypeName()); } /** @@ -322,57 +251,16 @@ public final class Constructor<T> extends AbstractMethod implements * include type parameters * * @since 1.5 + * @jls 8.8.3. Constructor Modifiers */ + @Override public String toGenericString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.constructorModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod) + " "); - } - TypeVariable<?>[] typeparms = getTypeParameters(); - if (typeparms.length > 0) { - boolean first = true; - sb.append("<"); - for(TypeVariable<?> typeparm: typeparms) { - if (!first) - sb.append(","); - // Class objects can't occur here; no need to test - // and call Class.getName(). - sb.append(typeparm.toString()); - first = false; - } - sb.append("> "); - } - sb.append(Field.getTypeName(getDeclaringClass())); - sb.append("("); - Type[] params = getGenericParameterTypes(); - for (int j = 0; j < params.length; j++) { - String param = (params[j] instanceof Class<?>)? - Field.getTypeName((Class<?>)params[j]): - (params[j].toString()); - if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... - param = param.replaceFirst("\\[\\]$", "..."); - sb.append(param); - if (j < (params.length - 1)) - sb.append(","); - } - sb.append(")"); - Type[] exceptions = getGenericExceptionTypes(); - if (exceptions.length > 0) { - sb.append(" throws "); - for (int k = 0; k < exceptions.length; k++) { - sb.append((exceptions[k] instanceof Class)? - ((Class<?>)exceptions[k]).getName(): - exceptions[k].toString()); - if (k < (exceptions.length - 1)) - sb.append(","); - } - } - return sb.toString(); - } catch (Exception e) { - return "<" + e + ">"; - } + return sharedToGenericString(Modifier.constructorModifiers(), false); + } + + @Override + void specificToGenericStringHeader(StringBuilder sb) { + specificToStringHeader(sb); } /** @@ -440,29 +328,22 @@ public final class Constructor<T> extends AbstractMethod implements IllegalAccessException, IllegalArgumentException, InvocationTargetException; /** - * Returns {@code true} if this constructor was declared to take - * a variable number of arguments; returns {@code false} - * otherwise. - * - * @return {@code true} if an only if this constructor was declared to - * take a variable number of arguments. + * {@inheritDoc} * @since 1.5 */ + @Override public boolean isVarArgs() { - return (getModifiers() & Modifier.VARARGS) != 0; + return super.isVarArgs(); } /** - * Returns {@code true} if this constructor is a synthetic - * constructor; returns {@code false} otherwise. - * - * @return true if and only if this constructor is a synthetic - * constructor as defined by - * <cite>The Java™ Language Specification</cite>. + * {@inheritDoc} + * @jls 13.1 The Form of a Binary * @since 1.5 */ + @Override public boolean isSynthetic() { - return Modifier.isSynthetic(getModifiers()); + return super.isSynthetic(); } String getSignature() { @@ -479,52 +360,29 @@ public final class Constructor<T> extends AbstractMethod implements } /** - * @throws NullPointerException {@inheritDoc} + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return getAnnotationNative(annotationType); + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + return super.getAnnotation(annotationClass); } - private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType); /** + * {@inheritDoc} * @since 1.5 */ - @Override public native Annotation[] getDeclaredAnnotations(); - - @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return isAnnotationPresentNative(annotationType); + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); } - private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType); /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this {@code Constructor} object. (Returns an array of length zero if the - * underlying method is parameterless. If the method has one or more - * parameters, a nested array of length zero is returned for each parameter - * with no annotations.) The annotation objects contained in the returned - * arrays are serializable. The caller of this method is free to modify - * the returned arrays; it will have no effect on the arrays returned to - * other callers. - * - * @return an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by this - * Constructor object + * {@inheritDoc} * @since 1.5 */ + @Override public Annotation[][] getParameterAnnotations() { - Annotation[][] parameterAnnotations = getParameterAnnotationsNative(); - if (parameterAnnotations == null) { - parameterAnnotations = new Annotation[getParameterTypes().length][0]; - } - return parameterAnnotations; + // Android-changed: This is handled by AbstractMethod. + return super.getParameterAnnotations(); } - private native Annotation[][] getParameterAnnotationsNative(); } diff --git a/ojluni/src/main/java/java/lang/reflect/Executable.java b/ojluni/src/main/java/java/lang/reflect/Executable.java new file mode 100644 index 0000000000..1840566efa --- /dev/null +++ b/ojluni/src/main/java/java/lang/reflect/Executable.java @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; +import libcore.reflect.AnnotatedElements; + +/** + * A shared superclass for the common functionality of {@link Method} + * and {@link Constructor}. + * + * @since 1.8 + */ +public abstract class Executable extends AccessibleObject + implements Member, GenericDeclaration { + /* + * Only grant package-visibility to the constructor. + */ + Executable() {} + + boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) { + /* Avoid unnecessary cloning */ + if (params1.length == params2.length) { + for (int i = 0; i < params1.length; i++) { + if (params1[i] != params2[i]) + return false; + } + return true; + } + return false; + } + + void separateWithCommas(Class<?>[] types, StringBuilder sb) { + for (int j = 0; j < types.length; j++) { + sb.append(types[j].getTypeName()); + if (j < (types.length - 1)) + sb.append(","); + } + + } + + void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) { + int mod = getModifiers() & mask; + + if (mod != 0 && !isDefault) { + sb.append(Modifier.toString(mod)).append(' '); + } else { + int access_mod = mod & Modifier.ACCESS_MODIFIERS; + if (access_mod != 0) + sb.append(Modifier.toString(access_mod)).append(' '); + if (isDefault) + sb.append("default "); + mod = (mod & ~Modifier.ACCESS_MODIFIERS); + if (mod != 0) + sb.append(Modifier.toString(mod)).append(' '); + } + } + + String sharedToString(int modifierMask, + boolean isDefault, + Class<?>[] parameterTypes, + Class<?>[] exceptionTypes) { + try { + StringBuilder sb = new StringBuilder(); + + printModifiersIfNonzero(sb, modifierMask, isDefault); + specificToStringHeader(sb); + + sb.append('('); + separateWithCommas(parameterTypes, sb); + sb.append(')'); + if (exceptionTypes.length > 0) { + sb.append(" throws "); + separateWithCommas(exceptionTypes, sb); + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Generate toString header information specific to a method or + * constructor. + */ + abstract void specificToStringHeader(StringBuilder sb); + + + String sharedToGenericString(int modifierMask, boolean isDefault) { + try { + StringBuilder sb = new StringBuilder(); + + printModifiersIfNonzero(sb, modifierMask, isDefault); + + TypeVariable<?>[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable<?> typeparm: typeparms) { + if (!first) + sb.append(','); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + + specificToGenericStringHeader(sb); + + sb.append('('); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = params[j].getTypeName(); + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + param = param.replaceFirst("\\[\\]$", "..."); + sb.append(param); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Generate toGenericString header information specific to a + * method or constructor. + */ + abstract void specificToGenericStringHeader(StringBuilder sb); + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the executable represented by this object. + */ + public abstract Class<?> getDeclaringClass(); + + /** + * Returns the name of the executable represented by this object. + */ + public abstract String getName(); + + /** + * Returns the Java language {@linkplain Modifier modifiers} for + * the executable represented by this object. + */ + public abstract int getModifiers(); + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * <cite>The Java™ Virtual Machine Specification</cite> + */ + public abstract TypeVariable<?>[] getTypeParameters(); + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the executable + * represented by this object. Returns an array of length + * 0 if the underlying executable takes no parameters. + * + * @return the parameter types for the executable this object + * represents + */ + public abstract Class<?>[] getParameterTypes(); + + /** + * Returns the number of formal parameters (whether explicitly + * declared or implicitly declared or neither) for the executable + * represented by this object. + * + * @since 1.8 + * @return The number of formal parameters for the executable this + * object represents + */ + public int getParameterCount() { + throw new AbstractMethodError(); + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the executable represented by + * this object. Returns an array of length 0 if the + * underlying executable takes no parameters. + * + * <p>If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + * <p>If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of {@code Type}s that represent the formal + * parameter types of the underlying executable, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * <cite>The Java™ Virtual Machine Specification</cite> + * @throws TypeNotPresentException if any of the parameter + * types of the underlying executable refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying executable's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + */ + public Type[] getGenericParameterTypes() { + // Android-changed: Implemented in AbstractMethod instead. + throw new UnsupportedOperationException( + "Executable.getGenericParameterTypes() not implemented"); + } + + /** + * Returns an array of {@code Class} objects that represent the + * types of exceptions declared to be thrown by the underlying + * executable represented by this object. Returns an array of + * length 0 if the executable declares no exceptions in its {@code + * throws} clause. + * + * @return the exception types declared as being thrown by the + * executable this object represents + */ + public abstract Class<?>[] getExceptionTypes(); + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this executable object. + * Returns an array of length 0 if the underlying executable declares + * no exceptions in its {@code throws} clause. + * + * <p>If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying executable + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * <cite>The Java™ Virtual Machine Specification</cite> + * @throws TypeNotPresentException if the underlying executable's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying executable's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + */ + public Type[] getGenericExceptionTypes() { + // Android-changed: Implemented in AbstractMethod instead. + throw new UnsupportedOperationException( + "Executable.getGenericExceptionTypes() not implemented"); + } + + /** + * Returns a string describing this {@code Executable}, including + * any type parameters. + * @return a string describing this {@code Executable}, including + * any type parameters + */ + public abstract String toGenericString(); + + /** + * Returns {@code true} if this executable was declared to take a + * variable number of arguments; returns {@code false} otherwise. + * + * @return {@code true} if an only if this executable was declared + * to take a variable number of arguments. + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this executable is a synthetic + * construct; returns {@code false} otherwise. + * + * @return true if and only if this executable is a synthetic + * construct as defined by + * <cite>The Java™ Language Specification</cite>. + * @jls 13.1 The Form of a Binary + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + /** + * Returns an array of arrays of {@code Annotation}s that + * represent the annotations on the formal parameters, in + * declaration order, of the {@code Executable} represented by + * this object. Synthetic and mandated parameters (see + * explanation below), such as the outer "this" parameter to an + * inner class constructor will be represented in the returned + * array. If the executable has no parameters (meaning no formal, + * no synthetic, and no mandated parameters), a zero-length array + * will be returned. If the {@code Executable} has one or more + * parameters, a nested array of length zero is returned for each + * parameter with no annotations. The annotation objects contained + * in the returned arrays are serializable. The caller of this + * method is free to modify the returned arrays; it will have no + * effect on the arrays returned to other callers. + * + * A compiler may add extra parameters that are implicitly + * declared in source ("mandated"), as well as parameters that + * are neither implicitly nor explicitly declared in source + * ("synthetic") to the parameter list for a method. + * + * @return an array of arrays that represent the annotations on + * the formal and implicit parameters, in declaration order, of + * the executable represented by this object + */ + public abstract Annotation[][] getParameterAnnotations(); + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + */ + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + // Android-changed: Implemented in AbstractMethod instead. + throw new UnsupportedOperationException("Executable.getAnnotation(Class) not implemented"); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { + // Android-changed: Uses AnnotatedElements instead. + return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); + } + + /** + * {@inheritDoc} + */ + public Annotation[] getDeclaredAnnotations() { + // Android-changed: Implemented in AbstractMethod instead. + throw new UnsupportedOperationException( + "Executable.getDeclaredAnnotations() not implemented"); + } +} diff --git a/ojluni/src/main/java/java/lang/reflect/Field.java b/ojluni/src/main/java/java/lang/reflect/Field.java index 315b1edbf1..db56ba4314 100644 --- a/ojluni/src/main/java/java/lang/reflect/Field.java +++ b/ojluni/src/main/java/java/lang/reflect/Field.java @@ -26,13 +26,11 @@ package java.lang.reflect; -import sun.reflect.CallerSensitive; -import sun.reflect.Reflection; -import java.lang.annotation.Annotation; -import java.util.Map; import com.android.dex.Dex; + +import java.lang.annotation.Annotation; +import libcore.reflect.AnnotatedElements; import libcore.reflect.GenericSignatureParser; -import java.util.List; /** @@ -849,6 +847,18 @@ class Field extends AccessibleObject implements Member { } private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType); + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + @Override + public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { + // Android-changed: Uses AnnotatedElements instead. + return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass); + } + + @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { if (annotationType == null) { throw new NullPointerException("annotationType == null"); diff --git a/ojluni/src/main/java/java/lang/reflect/Method.java b/ojluni/src/main/java/java/lang/reflect/Method.java index 8ee7bd5c48..ec0cdcf559 100644 --- a/ojluni/src/main/java/java/lang/reflect/Method.java +++ b/ojluni/src/main/java/java/lang/reflect/Method.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,8 @@ package java.lang.reflect; -import sun.reflect.CallerSensitive; import java.lang.annotation.Annotation; -import java.lang.annotation.AnnotationFormatError; -import com.android.dex.Dex; import java.util.Comparator; -import java.util.List; import libcore.reflect.Types; /** @@ -54,9 +50,7 @@ import libcore.reflect.Types; * @author Kenneth Russell * @author Nakul Saraiya */ -public final - class Method extends AbstractMethod implements GenericDeclaration, - Member { +public final class Method extends AbstractMethod { /** * Orders methods by their name, parameters and return type. * @@ -69,7 +63,7 @@ public final } int comparison = a.getName().compareTo(b.getName()); if (comparison == 0) { - comparison = a.compareParameters(b.getParameterTypes()); + comparison = a.compareMethodParametersInternal(b.getParameterTypes()); if (comparison == 0) { // This is necessary for methods that have covariant return types. Class<?> aReturnType = a.getReturnType(); @@ -89,10 +83,11 @@ public final } /** - * Returns the {@code Class} object representing the class or interface - * that declares the method represented by this {@code Method} object. - */ + * {@inheritDoc} + */ + @Override public Class<?> getDeclaringClass() { + // Android-changed: This is handled by AbstractMethod. return super.getDeclaringClass(); } @@ -100,40 +95,31 @@ public final * Returns the name of the method represented by this {@code Method} * object, as a {@code String}. */ + @Override public String getName() { - Dex dex = declaringClassOfOverriddenMethod.getDex(); - int nameIndex = dex.nameIndexFromMethodIndex(dexMethodIndex); - return declaringClassOfOverriddenMethod.getDexCacheString(dex, nameIndex); + // Android-changed: This is handled by AbstractMethod. + return getMethodNameInternal(); } /** - * Returns the Java language modifiers for the method represented - * by this {@code Method} object, as an integer. The {@code Modifier} class should - * be used to decode the modifiers. - * - * @see Modifier + * {@inheritDoc} */ + @Override public int getModifiers() { + // Android-changed: This is handled by AbstractMethod. return super.getModifiers(); } /** - * Returns an array of {@code TypeVariable} objects that represent the - * type variables declared by the generic declaration represented by this - * {@code GenericDeclaration} object, in declaration order. Returns an - * array of length 0 if the underlying generic declaration declares no type - * variables. - * - * @return an array of {@code TypeVariable} objects that represent - * the type variables declared by this generic declaration - * @throws GenericSignatureFormatError if the generic - * signature of this generic declaration does not conform to - * the format specified in - * <cite>The Java™ Virtual Machine Specification</cite> + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} * @since 1.5 */ + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) public TypeVariable<Method>[] getTypeParameters() { - GenericInfo info = getMethodOrConstructorGenericInfo(); + // Android-changed: This is mostly handled by AbstractMethod. + GenericInfo info = getMethodOrConstructorGenericInfoInternal(); return (TypeVariable<Method>[]) info.formalTypeParameters.clone(); } @@ -144,10 +130,8 @@ public final * @return the return type for the method this object represents */ public Class<?> getReturnType() { - Dex dex = declaringClassOfOverriddenMethod.getDex(); - int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); - // Note, in the case of a Proxy the dex cache types are equal. - return declaringClassOfOverriddenMethod.getDexCacheType(dex, returnTypeIndex); + // Android-changed: This is handled by AbstractMethod. + return getMethodReturnTypeInternal(); } /** @@ -175,91 +159,54 @@ public final * @since 1.5 */ public Type getGenericReturnType() { - return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType); + return Types.getType(getMethodOrConstructorGenericInfoInternal().genericReturnType); } - /** - * Returns an array of {@code Class} objects that represent the formal - * parameter types, in declaration order, of the method - * represented by this {@code Method} object. Returns an array of length - * 0 if the underlying method takes no parameters. - * - * @return the parameter types for the method this object - * represents + * {@inheritDoc} */ @Override public Class<?>[] getParameterTypes() { + // Android-changed: This is handled by AbstractMethod. return super.getParameterTypes(); } /** - * Returns an array of {@code Type} objects that represent the formal - * parameter types, in declaration order, of the method represented by - * this {@code Method} object. Returns an array of length 0 if the - * underlying method takes no parameters. - * - * <p>If a formal parameter type is a parameterized type, - * the {@code Type} object returned for it must accurately reflect - * the actual type parameters used in the source code. - * - * <p>If a formal parameter type is a type variable or a parameterized - * type, it is created. Otherwise, it is resolved. - * - * @return an array of Types that represent the formal - * parameter types of the underlying method, in declaration order - * @throws GenericSignatureFormatError - * if the generic method signature does not conform to the format - * specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if any of the parameter - * types of the underlying method refers to a non-existent type - * declaration - * @throws MalformedParameterizedTypeException if any of - * the underlying method's parameter types refer to a parameterized - * type that cannot be instantiated for any reason + * {@inheritDoc} + */ + public int getParameterCount() { + // Android-changed: This is handled by AbstractMethod. + return super.getParameterCount(); + } + + /** + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ + @Override public Type[] getGenericParameterTypes() { - return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false); + return super.getGenericParameterTypes(); } /** - * Returns an array of {@code Class} objects that represent - * the types of the exceptions declared to be thrown - * by the underlying method - * represented by this {@code Method} object. Returns an array of length - * 0 if the method declares no exceptions in its {@code throws} clause. - * - * @return the exception types declared as being thrown by the - * method this object represents + * {@inheritDoc} */ + @Override public native Class<?>[] getExceptionTypes(); /** - * Returns an array of {@code Type} objects that represent the - * exceptions declared to be thrown by this {@code Method} object. - * Returns an array of length 0 if the underlying method declares - * no exceptions in its {@code throws} clause. - * - * <p>If an exception type is a type variable or a parameterized - * type, it is created. Otherwise, it is resolved. - * - * @return an array of Types that represent the exception types - * thrown by the underlying method - * @throws GenericSignatureFormatError - * if the generic method signature does not conform to the format - * specified in - * <cite>The Java™ Virtual Machine Specification</cite> - * @throws TypeNotPresentException if the underlying method's - * {@code throws} clause refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if - * the underlying method's {@code throws} clause refers to a - * parameterized type that cannot be instantiated for any reason + * {@inheritDoc} + * @throws GenericSignatureFormatError {@inheritDoc} + * @throws TypeNotPresentException {@inheritDoc} + * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ + @Override public Type[] getGenericExceptionTypes() { - return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false); + return super.getGenericExceptionTypes(); } /** @@ -275,16 +222,8 @@ public final && (getName() == other.getName())) { if (!getReturnType().equals(other.getReturnType())) return false; - /* Avoid unnecessary cloning */ - Class<?>[] params1 = getParameterTypes(); - Class<?>[] params2 = other.getParameterTypes(); - if (params1.length == params2.length) { - for (int i = 0; i < params1.length; i++) { - if (params1[i] != params2[i]) - return false; - } - return true; - } + // Android changed: Use getParameterTypes. + return equalParamTypes(getParameterTypes(), other.getParameterTypes()); } } return false; @@ -299,6 +238,7 @@ public final return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); } + /** * Returns a string describing this {@code Method}. The string is * formatted as the method access modifiers, if any, followed by @@ -318,39 +258,26 @@ public final * specified by "The Java Language Specification". This is * {@code public}, {@code protected} or {@code private} first, * and then other modifiers in the following order: - * {@code abstract}, {@code static}, {@code final}, + * {@code abstract}, {@code default}, {@code static}, {@code final}, * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method} + * + * @jls 8.4.3 Method Modifiers */ public String toString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.methodModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod)).append(' '); - } - sb.append(Field.getTypeName(getReturnType())).append(' '); - sb.append(Field.getTypeName(getDeclaringClass())).append('.'); - sb.append(getName()).append('('); - Class<?>[] params = getParameterTypes(); - for (int j = 0; j < params.length; j++) { - sb.append(Field.getTypeName(params[j])); - if (j < (params.length - 1)) - sb.append(','); - } - sb.append(')'); - Class<?>[] exceptions = getExceptionTypes(); - if (exceptions.length > 0) { - sb.append(" throws "); - for (int k = 0; k < exceptions.length; k++) { - sb.append(exceptions[k].getName()); - if (k < (exceptions.length - 1)) - sb.append(','); - } - } - return sb.toString(); - } catch (Exception e) { - return "<" + e + ">"; - } + // Android changed: Use getParameterTypes. + return sharedToString(Modifier.methodModifiers(), + isDefault(), + getParameterTypes(), + getExceptionTypes()); + } + + @Override + void specificToStringHeader(StringBuilder sb) { + sb.append(getReturnType().getTypeName()).append(' '); + sb.append(getDeclaringClass().getTypeName()).append('.'); + sb.append(getName()); } /** @@ -376,79 +303,36 @@ public final * class name. If the method is declared to throw exceptions, the * parameter list is followed by a space, followed by the word * throws followed by a comma-separated list of the generic thrown - * exception types. If there are no type parameters, the type - * parameter list is elided. + * exception types. * * <p>The access modifiers are placed in canonical order as * specified by "The Java Language Specification". This is * {@code public}, {@code protected} or {@code private} first, * and then other modifiers in the following order: - * {@code abstract}, {@code static}, {@code final}, + * {@code abstract}, {@code default}, {@code static}, {@code final}, * {@code synchronized}, {@code native}, {@code strictfp}. * * @return a string describing this {@code Method}, * include type parameters * * @since 1.5 + * + * @jls 8.4.3 Method Modifiers */ + @Override public String toGenericString() { - try { - StringBuilder sb = new StringBuilder(); - int mod = getModifiers() & Modifier.methodModifiers(); - if (mod != 0) { - sb.append(Modifier.toString(mod)).append(' '); - } - TypeVariable<?>[] typeparms = getTypeParameters(); - if (typeparms.length > 0) { - boolean first = true; - sb.append('<'); - for(TypeVariable<?> typeparm: typeparms) { - if (!first) - sb.append(','); - // Class objects can't occur here; no need to test - // and call Class.getName(). - sb.append(typeparm.toString()); - first = false; - } - sb.append("> "); - } + return sharedToGenericString(Modifier.methodModifiers(), isDefault()); + } - Type genRetType = getGenericReturnType(); - sb.append( ((genRetType instanceof Class<?>)? - Field.getTypeName((Class<?>)genRetType):genRetType.toString())) - .append(' '); - - sb.append(Field.getTypeName(getDeclaringClass())).append('.'); - sb.append(getName()).append('('); - Type[] params = getGenericParameterTypes(); - for (int j = 0; j < params.length; j++) { - String param = (params[j] instanceof Class)? - Field.getTypeName((Class)params[j]): - (params[j].toString()); - if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... - param = param.replaceFirst("\\[\\]$", "..."); - sb.append(param); - if (j < (params.length - 1)) - sb.append(','); - } - sb.append(')'); - Type[] exceptions = getGenericExceptionTypes(); - if (exceptions.length > 0) { - sb.append(" throws "); - for (int k = 0; k < exceptions.length; k++) { - sb.append((exceptions[k] instanceof Class)? - ((Class)exceptions[k]).getName(): - exceptions[k].toString()); - if (k < (exceptions.length - 1)) - sb.append(','); - } - } - return sb.toString(); - } catch (Exception e) { - return "<" + e + ">"; - } + @Override + void specificToGenericStringHeader(StringBuilder sb) { + Type genRetType = getGenericReturnType(); + sb.append(genRetType.getTypeName()).append(' '); + sb.append(getDeclaringClass().getTypeName()).append('.'); + sb.append(getName()); } + /** * Invokes the underlying method represented by this {@code Method} * object, on the specified object with the specified parameters. @@ -480,7 +364,7 @@ public final * underlying method return type is void, the invocation returns * null. * - * @param receiver the object the underlying method is invoked from + * @param obj the object the underlying method is invoked from * @param args the arguments used for the method call * @return the result of dispatching the method represented by * this object on {@code obj} with parameters @@ -506,7 +390,7 @@ public final * @exception ExceptionInInitializerError if the initialization * provoked by this method fails. */ - public native Object invoke(Object receiver, Object... args) + public native Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; /** @@ -518,45 +402,46 @@ public final * @since 1.5 */ public boolean isBridge() { - return (getModifiers() & Modifier.BRIDGE) != 0; + // Android-changed: This is handled by AbstractMethod. + return super.isBridgeMethodInternal(); } /** - * Returns {@code true} if this method was declared to take - * a variable number of arguments; returns {@code false} - * otherwise. - * - * @return {@code true} if an only if this method was declared to - * take a variable number of arguments. + * {@inheritDoc} * @since 1.5 */ + @Override public boolean isVarArgs() { - return (getModifiers() & Modifier.VARARGS) != 0; + return super.isVarArgs(); } /** - * Returns {@code true} if this method is a synthetic - * method; returns {@code false} otherwise. - * - * @return true if and only if this method is a synthetic - * method as defined by the Java Language Specification. + * {@inheritDoc} + * @jls 13.1 The Form of a Binary * @since 1.5 */ + @Override public boolean isSynthetic() { - return Modifier.isSynthetic(getModifiers()); + return super.isSynthetic(); } + /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 + * Returns {@code true} if this method is a default + * method; returns {@code false} otherwise. + * + * A default method is a public non-abstract instance method, that + * is, a non-static method with a body, declared in an interface + * type. + * + * @return true if and only if this method is a default + * method as defined by the Java Language Specification. + * @since 1.8 */ - @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { - if (annotationType == null) { - throw new NullPointerException("annotationType == null"); - } - return getAnnotationNative(annotationType); + public boolean isDefault() { + // Android-changed: This is handled by AbstractMethod. + return super.isDefaultMethodInternal(); } - private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType); /** * Returns the default value for the annotation member represented by @@ -575,29 +460,31 @@ public final public native Object getDefaultValue(); /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this {@code Method} object. (Returns an array of length zero if the - * underlying method is parameterless. If the method has one or more - * parameters, a nested array of length zero is returned for each parameter - * with no annotations.) The annotation objects contained in the returned - * arrays are serializable. The caller of this method is free to modify - * the returned arrays; it will have no effect on the arrays returned to - * other callers. - * - * @return an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by this - * Method object + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + return super.getAnnotation(annotationClass); + } + + /** + * {@inheritDoc} + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + return super.getDeclaredAnnotations(); + } + + /** + * {@inheritDoc} * @since 1.5 */ + @Override public Annotation[][] getParameterAnnotations() { - Annotation[][] parameterAnnotations = getParameterAnnotationsNative(); - if (parameterAnnotations == null) { - parameterAnnotations = new Annotation[getParameterTypes().length][0]; - } - return parameterAnnotations; + // Android-changed: This is handled by AbstractMethod. + return super.getParameterAnnotations(); } - private native Annotation[][] getParameterAnnotationsNative(); /** * Returns the constructor's signature in non-printable form. This is called @@ -628,13 +515,6 @@ public final * @hide needed by Proxy */ boolean equalNameAndParameters(Method m) { - return getName().equals(m.getName()) && equalMethodParameters(m.getParameterTypes()); - } - - /** - * Returns {@code true} if this method is a default method; returns {@code false} otherwise. - */ - public boolean isDefault() { - return super.isDefault(); + return equalNameAndParametersInternal(m); } } diff --git a/ojluni/src/main/java/java/lang/reflect/Modifier.java b/ojluni/src/main/java/java/lang/reflect/Modifier.java index 78e0dbcde4..f461be5690 100644 --- a/ojluni/src/main/java/java/lang/reflect/Modifier.java +++ b/ojluni/src/main/java/java/lang/reflect/Modifier.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -398,6 +398,12 @@ class Modifier { Modifier.VOLATILE; /** + * + */ + static final int ACCESS_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; + + /** * Return an {@code int} value OR-ing together the source language * modifiers that can be applied to a class. * @return an {@code int} value OR-ing together the source language diff --git a/ojluni/src/main/java/java/lang/reflect/Type.java b/ojluni/src/main/java/java/lang/reflect/Type.java index 76b40d66e2..fb98684bce 100644 --- a/ojluni/src/main/java/java/lang/reflect/Type.java +++ b/ojluni/src/main/java/java/lang/reflect/Type.java @@ -34,4 +34,17 @@ package java.lang.reflect; */ public interface Type { + /** + * Returns a string describing this type, including information + * about any type parameters. + * + * @implSpec The default implementation calls {@code toString}. + * + * @return a string describing this type + * @since 1.8 + * @hide Pending tests + */ + default String getTypeName() { + return toString(); + } } diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk index fe4ad2db85..1238d5aee6 100644 --- a/openjdk_java_files.mk +++ b/openjdk_java_files.mk @@ -178,6 +178,7 @@ openjdk_javadoc_files := \ ojluni/src/main/java/java/lang/reflect/Array.java \ ojluni/src/main/java/java/lang/reflect/Constructor.java \ ojluni/src/main/java/java/lang/reflect/Field.java \ + ojluni/src/main/java/java/lang/reflect/Executable.java \ ojluni/src/main/java/java/lang/reflect/GenericArrayType.java \ ojluni/src/main/java/java/lang/reflect/GenericDeclaration.java \ ojluni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java \ |