有时候,我们会希望由值来决定程序的行为。例如,在一种持久存储机制中,你可能希望用户用一种方法来保存特定类的对象,通常的实现方法是将Class对象与一个动作关联(这句话是什么意思?)
不过,如果方法中有一个泛型类,在类型擦除时会带来问题,比如ArrayList<Interger>
和ArrayList<String>
都擦除为一ArrayList。如何让他们拥有不同的动作呢?
看下面的例子:
package genericReflection;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
class TypeLiteral<T> {
private Type type;
public TypeLiteral() {
Type parentType = getClass().getGenericSuperclass();
if (parentType instanceof ParameterizedType) {
type = ((ParameterizedType)parentType).getActualTypeArguments()[0];
}
else {
throw new UnsupportedOperationException("Construct as new TypeLiteral<...>");
}
}
private TypeLiteral(Type type) {
this.type = type;
}
public static TypeLiteral<?> of(Type type) {
return new TypeLiteral<Object>(type);
}
public String toString() {
if (type instanceof Class) {
return ((Class<?>) type).getName();
}
else {
return type.toString();
}
}
@Override
public boolean equals(Object otherObject) {
return otherObject instanceof TypeLiterals
&&type.equals((TypeLiteral<?>) ((TypeLiteral) otherObject).type);
}
public int hashCode() {
return type.hashCode();
}
}
class Formatter {
private Map<TypeLiteral<?>, Function<?,String>> rules = new HashMap<>();
public <T> void forType(TypeLiteral<T> type,Function<T,String> formatterForType) {
rules.put(type,formatterForType);
}
public String formatFields(Object obj) throws IllegalArgumentException,IllegalAccessException {
StringBuilder result = new StringBuilder();
for (Field f : obj.getClass().getDeclaredFields()) {
result.append(f.getName());
result.append("=");
f.setAccessible(true);
Function<?,String> formatterForType = rules.get(TypeLiteral.of(f.getGenericType()));
if (formatterForType != null) {
Function<Object,String> objectFormatter = (Function<Object, String>)formatterForType;
result.append(objectFormatter.apply(f.get(obj)));
}
else {
result.append(f.get(obj).toString());
}
result.append("\n");
};
return result.toString();
}
}
public class TypeLiterals {
public static class Sample {
ArrayList<Integer> nums;
ArrayList<Character> chars;
ArrayList<String> strings;
public Sample() {
nums = new ArrayList<>();
nums.add(42);
nums.add(1729);
chars = new ArrayList<>();
chars.add('H');
chars.add('i');
strings = new ArrayList<>();
strings.add("Hello");
strings.add("World");
}
}
private static <T> String join(String separator,ArrayList<T> element) {
StringBuilder result = new StringBuilder();
for (T e : element) {
if (result.length() > 0) {
result.append(separator);
}
result.append(e.toString());
}
return result.toString();
}
public static void main(String[] args) throws IllegalAccessException {
Formatter formatter = new Formatter();
formatter.forType(new TypeLiteral<ArrayList<Integer>>(){}, lst -> join(" ",lst));
formatter.forType(new TypeLiteral<ArrayList<Character>>(){},lst -> "\"" + join("",lst) + "\"");
System.out.println(formatter.formatFields(new Sample()));
}
}
运行结果为:
nums=[42, 1729]
chars=[H, i]
strings=[Hello, World]