类型字面量—0104

有时候,我们会希望由值来决定程序的行为。例如,在一种持久存储机制中,你可能希望用户用一种方法来保存特定类的对象,通常的实现方法是将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]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值