summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2016-08-18 16:25:55 +0100
committerNeil Fuller <nfuller@google.com>2016-08-25 17:58:34 +0100
commit20938c5ed2bc8f5de8047a47caddb146f730868f (patch)
tree3cdcf7318fc5ef529da40ddadf127b5f295e7876
parenta3d5b7120f477b877a3b6dd142c2b5d9b9201a32 (diff)
Pulling in the OpenJDK 8 Executable class and related changes
This change restructures the existing code to accept Executable. This change involves changes to java.lang / java.lang.reflect Java code and ART internals. The Parameter code associated with Executable has been excluded and will be added as a follow up. Many of the upstream JavaDoc changes to some of the pre-existing files will also be handled as a follow-up to make this change smaller / easier to review. This contains the parts that would be hard to split out. The only intentional public API change is the addition of Executable/Method/Constructor getParameterCount() and Type.getTypeName(). Tests have been added for these. Some additional tests have been added to cover existing methods and cases like toString(). The changes to Modifier result in a change to Method.toString() which was previously not outputting "default" for default interface methods. Associated test lines confirming this behavior have now been uncommented. Bug: 28666126 Test: cts ran for libcore (libcore, harmony_java_lang, org) Change-Id: If94f2723b1ac28c08e52921c9860f54da04e168d
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ClassTest.java20
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/GenericArrayTypeTest.java15
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/ParameterizedTypeTest.java14
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/TypeVariableTest.java29
-rw-r--r--harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/WildcardTypeTest.java4
-rw-r--r--libart/src/main/java/java/lang/reflect/AbstractMethod.java248
-rw-r--r--luni/src/main/java/libcore/reflect/AnnotatedElements.java70
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/ConstructorTest.java7
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/MethodTest.java23
-rw-r--r--ojluni/src/main/java/java/lang/Class.java54
-rw-r--r--ojluni/src/main/java/java/lang/reflect/AccessibleObject.java52
-rw-r--r--ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java51
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Constructor.java306
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Executable.java384
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Field.java20
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Method.java374
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Modifier.java8
-rw-r--r--ojluni/src/main/java/java/lang/reflect/Type.java13
-rw-r--r--openjdk_java_files.mk1
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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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&trade; 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 \