1 /* 2 * Copyright (C) 2011 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 com.android.dx; 18 19 import com.android.dx.rop.cst.CstType; 20 import java.util.HashMap; 21 import java.util.Map; 22 23 /** 24 * A primitive type, interface or class. 25 * 26 * <p><strong>Warning:</strong> Use care when dealing with boxed primitive 27 * types. Java's lack of support for parameterized primitive types means that 28 * a primitive type like {@code int} and its boxed type {@code 29 * java.lang.Integer} have the same type parameter: {@code TypeId<Integer>}. 30 * These types are different and it will be a runtime error if the boxed type 31 * {@code java.lang.Integer} is used where the primitive type {@code int} is 32 * expected. 33 */ 34 public final class TypeId<T> { 35 /** The {@code boolean} primitive type. */ 36 public static final TypeId<Boolean> BOOLEAN = new TypeId<>(com.android.dx.rop.type.Type.BOOLEAN); 37 38 /** The {@code byte} primitive type. */ 39 public static final TypeId<Byte> BYTE = new TypeId<>(com.android.dx.rop.type.Type.BYTE); 40 41 /** The {@code char} primitive type. */ 42 public static final TypeId<Character> CHAR = new TypeId<>(com.android.dx.rop.type.Type.CHAR); 43 44 /** The {@code double} primitive type. */ 45 public static final TypeId<Double> DOUBLE = new TypeId<>(com.android.dx.rop.type.Type.DOUBLE); 46 47 /** The {@code float} primitive type. */ 48 public static final TypeId<Float> FLOAT = new TypeId<>(com.android.dx.rop.type.Type.FLOAT); 49 50 /** The {@code int} primitive type. */ 51 public static final TypeId<Integer> INT = new TypeId<>(com.android.dx.rop.type.Type.INT); 52 53 /** The {@code long} primitive type. */ 54 public static final TypeId<Long> LONG = new TypeId<>(com.android.dx.rop.type.Type.LONG); 55 56 /** The {@code short} primitive type. */ 57 public static final TypeId<Short> SHORT = new TypeId<>(com.android.dx.rop.type.Type.SHORT); 58 59 /** The {@code void} primitive type. Only used as a return type. */ 60 public static final TypeId<Void> VOID = new TypeId<>(com.android.dx.rop.type.Type.VOID); 61 62 /** The {@code Object} type. */ 63 public static final TypeId<Object> OBJECT = new TypeId<>(com.android.dx.rop.type.Type.OBJECT); 64 65 /** The {@code String} type. */ 66 public static final TypeId<String> STRING = new TypeId<>(com.android.dx.rop.type.Type.STRING); 67 68 private static final Map<Class<?>, TypeId<?>> PRIMITIVE_TO_TYPE = new HashMap<>(); 69 static { 70 PRIMITIVE_TO_TYPE.put(boolean.class, BOOLEAN); 71 PRIMITIVE_TO_TYPE.put(byte.class, BYTE); 72 PRIMITIVE_TO_TYPE.put(char.class, CHAR); 73 PRIMITIVE_TO_TYPE.put(double.class, DOUBLE); 74 PRIMITIVE_TO_TYPE.put(float.class, FLOAT); 75 PRIMITIVE_TO_TYPE.put(int.class, INT); 76 PRIMITIVE_TO_TYPE.put(long.class, LONG); 77 PRIMITIVE_TO_TYPE.put(short.class, SHORT); 78 PRIMITIVE_TO_TYPE.put(void.class, VOID); 79 } 80 81 final String name; 82 83 /** cached converted values */ 84 final com.android.dx.rop.type.Type ropType; 85 final CstType constant; 86 87 TypeId(com.android.dx.rop.type.Type ropType) { 88 this(ropType.getDescriptor(), ropType); 89 } 90 91 TypeId(String name, com.android.dx.rop.type.Type ropType) { 92 if (name == null || ropType == null) { 93 throw new NullPointerException(); 94 } 95 this.name = name; 96 this.ropType = ropType; 97 this.constant = CstType.intern(ropType); 98 } 99 100 /** 101 * @param name a descriptor like "Ljava/lang/Class;". 102 */ 103 public static <T> TypeId<T> get(String name) { 104 return new TypeId<>(name, com.android.dx.rop.type.Type.internReturnType(name)); 105 } 106 107 public static <T> TypeId<T> get(Class<T> type) { 108 if (type.isPrimitive()) { 109 // guarded by equals 110 @SuppressWarnings("unchecked") 111 TypeId<T> result = (TypeId<T>) PRIMITIVE_TO_TYPE.get(type); 112 return result; 113 } 114 String name = type.getName().replace('.', '/'); 115 return get(type.isArray() ? name : 'L' + name + ';'); 116 } 117 118 public <V> FieldId<T, V> getField(TypeId<V> type, String name) { 119 return new FieldId<>(this, type, name); 120 } 121 122 public MethodId<T, Void> getConstructor(TypeId<?>... parameters) { 123 return new MethodId<>(this, VOID, "<init>", new TypeList(parameters)); 124 } 125 126 public MethodId<T, Void> getStaticInitializer() { 127 return new MethodId<>(this, VOID, "<clinit>", new TypeList(new TypeId[0])); 128 } 129 130 public <R> MethodId<T, R> getMethod(TypeId<R> returnType, String name, TypeId<?>... parameters) { 131 return new MethodId<>(this, returnType, name, new TypeList(parameters)); 132 } 133 134 public String getName() { 135 return name; 136 } 137 138 @Override 139 public boolean equals(Object o) { 140 return o instanceof TypeId 141 && ((TypeId) o).name.equals(name); 142 } 143 144 @Override 145 public int hashCode() { 146 return name.hashCode(); 147 } 148 149 @Override 150 public String toString() { 151 return name; 152 } 153 } 154