1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.reflect; 18 19 import java.lang.reflect.GenericArrayType; 20 import java.lang.reflect.ParameterizedType; 21 import java.lang.reflect.Type; 22 import java.lang.reflect.TypeVariable; 23 import java.util.HashMap; 24 import java.util.Map; 25 import libcore.util.EmptyArray; 26 27 public final class Types { Types()28 private Types() { 29 } 30 31 // Holds a mapping from Java type names to native type codes. 32 private static final Map<Class<?>, String> PRIMITIVE_TO_SIGNATURE; 33 static { 34 PRIMITIVE_TO_SIGNATURE = new HashMap<Class<?>, String>(9); PRIMITIVE_TO_SIGNATURE.put(byte.class, "B")35 PRIMITIVE_TO_SIGNATURE.put(byte.class, "B"); PRIMITIVE_TO_SIGNATURE.put(char.class, "C")36 PRIMITIVE_TO_SIGNATURE.put(char.class, "C"); PRIMITIVE_TO_SIGNATURE.put(short.class, "S")37 PRIMITIVE_TO_SIGNATURE.put(short.class, "S"); PRIMITIVE_TO_SIGNATURE.put(int.class, "I")38 PRIMITIVE_TO_SIGNATURE.put(int.class, "I"); PRIMITIVE_TO_SIGNATURE.put(long.class, "J")39 PRIMITIVE_TO_SIGNATURE.put(long.class, "J"); PRIMITIVE_TO_SIGNATURE.put(float.class, "F")40 PRIMITIVE_TO_SIGNATURE.put(float.class, "F"); PRIMITIVE_TO_SIGNATURE.put(double.class, "D")41 PRIMITIVE_TO_SIGNATURE.put(double.class, "D"); PRIMITIVE_TO_SIGNATURE.put(void.class, "V")42 PRIMITIVE_TO_SIGNATURE.put(void.class, "V"); PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z")43 PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z"); 44 } 45 getTypeArray(ListOfTypes types, boolean clone)46 public static Type[] getTypeArray(ListOfTypes types, boolean clone) { 47 if (types.length() == 0) { 48 return EmptyArray.TYPE; 49 } 50 Type[] result = types.getResolvedTypes(); 51 return clone ? result.clone() : result; 52 } 53 getType(Type type)54 public static Type getType(Type type) { 55 if (type instanceof ParameterizedTypeImpl) { 56 return ((ParameterizedTypeImpl)type).getResolvedType(); 57 } 58 return type; 59 } 60 61 /** 62 * Returns the internal name of {@code clazz} (also known as the descriptor). 63 */ getSignature(Class<?> clazz)64 public static String getSignature(Class<?> clazz) { 65 String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz); 66 if (primitiveSignature != null) { 67 return primitiveSignature; 68 } else if (clazz.isArray()) { 69 return "[" + getSignature(clazz.getComponentType()); 70 } else { 71 // TODO: this separates packages with '.' rather than '/' 72 return "L" + clazz.getName() + ";"; 73 } 74 } 75 76 /** 77 * Returns the names of {@code types} separated by commas. 78 */ toString(Class<?>[] types)79 public static String toString(Class<?>[] types) { 80 if (types.length == 0) { 81 return ""; 82 } 83 StringBuilder result = new StringBuilder(); 84 appendTypeName(result, types[0]); 85 for (int i = 1; i < types.length; i++) { 86 result.append(','); 87 appendTypeName(result, types[i]); 88 } 89 return result.toString(); 90 } 91 92 /** 93 * Appends the best {@link #toString} name for {@code c} to {@code out}. 94 * This works around the fact that {@link Class#getName} is lousy for 95 * primitive arrays (it writes "[C" instead of "char[]") and {@link 96 * Class#getCanonicalName()} is lousy for nested classes (it uses a "." 97 * separator rather than a "$" separator). 98 */ appendTypeName(StringBuilder out, Class<?> c)99 public static void appendTypeName(StringBuilder out, Class<?> c) { 100 int dimensions = 0; 101 while (c.isArray()) { 102 c = c.getComponentType(); 103 dimensions++; 104 } 105 out.append(c.getName()); 106 for (int d = 0; d < dimensions; d++) { 107 out.append("[]"); 108 } 109 } 110 111 /** 112 * Appends names of the {@code types} to {@code out} separated by commas. 113 */ appendArrayGenericType(StringBuilder out, Type[] types)114 public static void appendArrayGenericType(StringBuilder out, Type[] types) { 115 if (types.length == 0) { 116 return; 117 } 118 appendGenericType(out, types[0]); 119 for (int i = 1; i < types.length; i++) { 120 out.append(','); 121 appendGenericType(out, types[i]); 122 } 123 } 124 appendGenericType(StringBuilder out, Type type)125 public static void appendGenericType(StringBuilder out, Type type) { 126 if (type instanceof TypeVariable) { 127 out.append(((TypeVariable) type).getName()); 128 } else if (type instanceof ParameterizedType) { 129 out.append(type.toString()); 130 } else if (type instanceof GenericArrayType) { 131 Type simplified = ((GenericArrayType) type).getGenericComponentType(); 132 appendGenericType(out, simplified); 133 out.append("[]"); 134 } else if (type instanceof Class) { 135 Class c = (Class<?>) type; 136 if (c.isArray()){ 137 String as[] = c.getName().split("\\["); 138 int len = as.length-1; 139 if (as[len].length() > 1){ 140 out.append(as[len].substring(1, as[len].length() - 1)); 141 } else { 142 char ch = as[len].charAt(0); 143 if (ch == 'I') { 144 out.append("int"); 145 } else if (ch == 'B') { 146 out.append("byte"); 147 } else if (ch == 'J') { 148 out.append("long"); 149 } else if (ch == 'F') { 150 out.append("float"); 151 } else if (ch == 'D') { 152 out.append("double"); 153 } else if (ch == 'S') { 154 out.append("short"); 155 } else if (ch == 'C') { 156 out.append("char"); 157 } else if (ch == 'Z') { 158 out.append("boolean"); 159 } else if (ch == 'V') { 160 out.append("void"); 161 } 162 } 163 for (int i = 0; i < len; i++){ 164 out.append("[]"); 165 } 166 } else { 167 out.append(c.getName()); 168 } 169 } 170 } 171 } 172