summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/java/lang/reflect/AccessibleObject.java24
-rw-r--r--luni/src/main/java/java/lang/reflect/Constructor.java2
-rw-r--r--luni/src/main/java/java/lang/reflect/Field.java3
-rw-r--r--luni/src/main/java/java/lang/reflect/Method.java4
-rw-r--r--luni/src/main/java/java/lang/reflect/WildcardType.java19
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java3
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java124
7 files changed, 145 insertions, 34 deletions
diff --git a/luni/src/main/java/java/lang/reflect/AccessibleObject.java b/luni/src/main/java/java/lang/reflect/AccessibleObject.java
index 83763a2..6803a46 100644
--- a/luni/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/luni/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -245,10 +245,10 @@ public class AccessibleObject implements AnnotatedElement {
StringBuilder result = new StringBuilder();
if (types.length != 0) {
- result.append(types[0].getCanonicalName());
+ result.append(types[0].getName());
for (int i = 1; i < types.length; i++) {
result.append(',');
- result.append(types[i].getCanonicalName());
+ result.append(types[i].getName());
}
}
@@ -348,26 +348,6 @@ public class AccessibleObject implements AnnotatedElement {
*
* @throws NullPointerException if any of the arguments is null
*/
- void appendArrayType(StringBuilder sb, Class[] objs) {
- if (objs.length > 0) {
- appendArrayType(sb, objs[0]);
- for (int i = 1; i < objs.length; i++) {
- sb.append(',');
- appendArrayType(sb, objs[i]);
- }
- }
- }
-
- /**
- * Appends names of the specified array classes to the buffer. The array
- * elements may represent a simple type, a reference type or an array type.
- * Output format: java.lang.Object[], java.io.File, void
- *
- * @param sb buffer
- * @param objs array of classes to print the names
- *
- * @throws NullPointerException if any of the arguments is null
- */
void appendArrayGenericType(StringBuilder sb, Type[] objs) {
if (objs.length > 0) {
appendGenericType(sb, objs[0]);
diff --git a/luni/src/main/java/java/lang/reflect/Constructor.java b/luni/src/main/java/java/lang/reflect/Constructor.java
index f511687..2a29822 100644
--- a/luni/src/main/java/java/lang/reflect/Constructor.java
+++ b/luni/src/main/java/java/lang/reflect/Constructor.java
@@ -144,7 +144,7 @@ public final class Constructor<T> extends AccessibleObject implements GenericDec
for (int i = 0; i < formalTypeParameters.length; i++) {
appendGenericType(sb, formalTypeParameters[i]);
if (i < formalTypeParameters.length - 1) {
- sb.append(", ");
+ sb.append(",");
}
}
sb.append("> ");
diff --git a/luni/src/main/java/java/lang/reflect/Field.java b/luni/src/main/java/java/lang/reflect/Field.java
index d7898b9..1d2726c 100644
--- a/luni/src/main/java/java/lang/reflect/Field.java
+++ b/luni/src/main/java/java/lang/reflect/Field.java
@@ -32,7 +32,6 @@
package java.lang.reflect;
-import dalvik.system.VMStack;
import java.lang.annotation.Annotation;
import org.apache.harmony.kernel.vm.StringUtils;
import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
@@ -838,7 +837,7 @@ public final class Field extends AccessibleObject implements Member {
if (result.length() != 0) {
result.append(' ');
}
- result.append(type.getName());
+ appendArrayType(result, type);
result.append(' ');
result.append(declaringClass.getName());
result.append('.');
diff --git a/luni/src/main/java/java/lang/reflect/Method.java b/luni/src/main/java/java/lang/reflect/Method.java
index 68fe219..2e2c03f 100644
--- a/luni/src/main/java/java/lang/reflect/Method.java
+++ b/luni/src/main/java/java/lang/reflect/Method.java
@@ -175,7 +175,7 @@ public final class Method extends AccessibleObject implements GenericDeclaration
for (int i = 0; i < formalTypeParameters.length; i++) {
appendGenericType(sb, formalTypeParameters[i]);
if (i < formalTypeParameters.length - 1) {
- sb.append(", ");
+ sb.append(",");
}
}
sb.append("> ");
@@ -185,7 +185,7 @@ public final class Method extends AccessibleObject implements GenericDeclaration
sb.append(' ');
// append method name
appendArrayType(sb, getDeclaringClass());
- sb.append("."+getName());
+ sb.append(".").append(getName());
// append parameters
sb.append('(');
appendArrayGenericType(sb,
diff --git a/luni/src/main/java/java/lang/reflect/WildcardType.java b/luni/src/main/java/java/lang/reflect/WildcardType.java
index affd526..31e1023 100644
--- a/luni/src/main/java/java/lang/reflect/WildcardType.java
+++ b/luni/src/main/java/java/lang/reflect/WildcardType.java
@@ -18,12 +18,21 @@
package java.lang.reflect;
/**
- * This interface represents a wildcard type, such as the simple wildcard
- * {@code '?'}, the upper bounded wildcard {@code '? extends Closeable'}, the
- * multiple upper bounded wildcard {@code '? extends Closeable & Flushable'} or
- * the lower bounded wildcard {@code '? super OutputStream'}.
+ * A pattern type, such as the upper bounded wildcard {@code
+ * ? extends Closeable} or the lower bounded wildcard {@code ? super String}.
*
- * @since 1.5
+ * <p>Although this interface permits an arbitrary number of upper and lower
+ * bounds, all wildcard types of Java language programs are in one of two forms:
+ * <ol>
+ * <li><strong>No lower bound and one upper bound.</strong> Such types are
+ * written like {@code ? extends java.lang.Number}. When the upper bound is
+ * {@code java.lang.Object}, the {@code extends java.lang.Object} suffix is
+ * optional: {@code Set<?>} is shorthand for {@code
+ * Set<? extends java.lang.Object>}.
+ * <li><strong>One lower bound and an upper bound of {@code
+ * java.lang.Object}.</strong> Such types are written like {@code
+ * ? super java.lang.String}.
+ * </ol>
*/
public interface WildcardType extends Type {
/**
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java b/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
index 3d60a0e..b0605f2 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
+++ b/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
@@ -59,7 +59,8 @@ public final class ImplForWildcard implements WildcardType {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("?");
- if (extendsBound.length() > 0) {
+ if ((extendsBound.length() == 1 && extendsBound.getResolvedTypes()[0] != Object.class)
+ || extendsBound.length() > 1) {
sb.append(" extends ").append(extendsBound);
} else if (superBound.length() > 0) {
sb.append(" super ").append(superBound);
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java b/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
index 19092c5..80c76e6 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
@@ -16,19 +16,141 @@
package libcore.java.lang.reflect;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.Set;
import junit.framework.TestCase;
public final class ReflectionTest extends TestCase {
+ String classA = "libcore.java.lang.reflect.ReflectionTest$A";
+ String classB = "libcore.java.lang.reflect.ReflectionTest$B";
+ String classC = "libcore.java.lang.reflect.ReflectionTest$C";
+
/**
* http://code.google.com/p/android/issues/detail?id=6636
*/
public void testGenericSuperclassToString() throws Exception {
- assertEquals("java.util.ArrayList<libcore.java.lang.reflect.ReflectionTest$A>",
+ assertEquals("java.util.ArrayList<" + classA + ">",
AList.class.getGenericSuperclass().toString());
}
+ public void testFieldToString() throws Exception {
+ Field fieldOne = C.class.getDeclaredField("fieldOne");
+ String fieldOneRaw = "public static " + classA + " " + classC + ".fieldOne";
+ assertEquals(fieldOneRaw, fieldOne.toString());
+ assertEquals(fieldOneRaw, fieldOne.toGenericString());
+
+ Field fieldTwo = C.class.getDeclaredField("fieldTwo");
+ assertEquals("transient volatile java.util.Map " + classC + ".fieldTwo",
+ fieldTwo.toString());
+ assertEquals("transient volatile java.util.Map<" + classA + ", java.lang.String> "
+ + classC + ".fieldTwo", fieldTwo.toGenericString());
+
+ Field fieldThree = C.class.getDeclaredField("fieldThree");
+ String fieldThreeRaw = "java.lang.Object[] " + classC + ".fieldThree";
+ assertEquals(fieldThreeRaw, fieldThree.toString());
+ String fieldThreeGeneric = "K[] " + classC + ".fieldThree";
+ assertEquals(fieldThreeGeneric, fieldThree.toGenericString());
+
+ Field fieldFour = C.class.getDeclaredField("fieldFour");
+ String fieldFourRaw = "java.util.Map " + classC + ".fieldFour";
+ assertEquals(fieldFourRaw, fieldFour.toString());
+ String fieldFourGeneric = "java.util.Map<? super java.lang.Integer, java.lang.Integer[]> "
+ + classC + ".fieldFour";
+ assertEquals(fieldFourGeneric, fieldFour.toGenericString());
+ }
+
+ public void testConstructorToString() throws Exception {
+ Constructor constructorOne = C.class.getDeclaredConstructor(A.class);
+ String constructorOneRaw = classC + "(" + classA + ") throws " + classB;
+ assertEquals(constructorOneRaw, constructorOne.toString());
+ assertEquals(constructorOneRaw, constructorOne.toGenericString());
+
+ Constructor constructorTwo = C.class.getDeclaredConstructor(Map.class, Object.class);
+ String constructorTwoRaw = "protected " + classC + "(java.util.Map,java.lang.Object)";
+ assertEquals(constructorTwoRaw, constructorTwo.toString());
+ String constructorTwoGeneric = "protected <T1> " + classC
+ + "(java.util.Map<? super " + classA + ", T1>,K)";
+ assertEquals(constructorTwoGeneric, constructorTwo.toGenericString());
+ }
+
+ public void testMethodToString() throws Exception {
+ Method methodOne = C.class.getDeclaredMethod("methodOne", A.class, C.class);
+ String methodOneRaw = "protected final synchronized " + classA + " "
+ + classC + ".methodOne(" + classA + "," + classC + ") throws " + classB;
+ assertEquals(methodOneRaw, methodOne.toString());
+ assertEquals(methodOneRaw, methodOne.toGenericString());
+
+ Method methodTwo = C.class.getDeclaredMethod("methodTwo", List.class);
+ String methodTwoRaw = "public abstract java.util.Map "
+ + classC + ".methodTwo(java.util.List)";
+ assertEquals(methodTwoRaw, methodTwo.toString());
+ String methodTwoGeneric = "public abstract java.util.Map<" + classA + ", java.lang.String> "
+ + classC + ".methodTwo(java.util.List<" + classA + ">)";
+ assertEquals(methodTwoGeneric, methodTwo.toGenericString());
+
+ Method methodThree = C.class.getDeclaredMethod("methodThree", A.class, Set.class);
+ String methodThreeRaw = "private static java.util.Map "
+ + classC + ".methodThree(" + classA + ",java.util.Set)";
+ assertEquals(methodThreeRaw, methodThree.toString());
+ String methodThreeGeneric = "private static <T1,T2> java.util.Map<T1, ?> "
+ + classC + ".methodThree(T1,java.util.Set<? super T2>)";
+ assertEquals(methodThreeGeneric, methodThree.toGenericString());
+
+ Method methodFour = C.class.getDeclaredMethod("methodFour", Set.class);
+ String methodFourRaw = "public java.lang.Comparable " + classC + ".methodFour(java.util.Set)";
+ assertEquals(methodFourRaw, methodFour.toString());
+ String methodFourGeneric = "public <T> T " + classC + ".methodFour(java.util.Set<T>)";
+ assertEquals(methodFourGeneric, methodFour.toGenericString());
+ }
+
+ public void testTypeVariableWithMultipleBounds() throws Exception {
+ TypeVariable t = C.class.getDeclaredMethod("methodFour", Set.class).getTypeParameters()[0];
+ assertEquals("T", t.toString());
+
+ Type[] bounds = t.getBounds();
+ ParameterizedType comparableT = (ParameterizedType) bounds[0];
+ assertEquals(Comparable.class, comparableT.getRawType());
+ assertEquals("T", ((TypeVariable) comparableT.getActualTypeArguments()[0]).getName());
+ assertEquals(3, bounds.length);
+ assertEquals(Serializable.class, bounds[1]);
+ assertEquals(RandomAccess.class, bounds[2]);
+ }
+
static class A {}
static class AList extends ArrayList<A> {}
+
+ static class B extends Exception {}
+
+ public static abstract class C<K> {
+ public static A fieldOne;
+ transient volatile Map<A, String> fieldTwo;
+ K[] fieldThree;
+ Map<? super Integer, Integer[]> fieldFour;
+
+ C(A a) throws B {}
+ protected <T1 extends A> C(Map<? super A, T1> a, K s) {}
+
+ protected final synchronized A methodOne(A parameterOne, C parameterTwo) throws B {
+ return null;
+ }
+ public abstract Map<A, String> methodTwo(List<A> onlyParameter);
+ @Deprecated /** this annotation is used because it has runtime retention */
+ private static <T1 extends A, T2> Map<T1, ?> methodThree(T1 t, Set<? super T2> t2s) {
+ return null;
+ }
+ public <T extends Comparable<T> & Serializable & RandomAccess> T methodFour(Set<T> t) {
+ return null;
+ }
+ }
}