在通用方法中对必须在列表中使用的参数取消选中强制转换警告 [英] Unchecked cast warnings in generic method on parameter that must be used in a List

查看:101
本文介绍了在通用方法中对必须在列表中使用的参数取消选中强制转换警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,类型参数 D 可以是 List< Byte> c $ c> List > (它是 Fields<?,?,D> 接口中的第三个通用参数但仍然可能会忽略它 - 但它也存在于方法的返回类型中)。似乎找不到一种方法告诉编译器这个 - $ // * 警告>:

In the code below, the type parameter D can be either a List<Byte> or a List<List<Byte>> (it is the third generic parameter in the Fields<?, ?, D> interface but still I might omit it there - but it is present also in the return type of the method). Can't seem to find a way to tell the compiler this - get Unchecked cast warnings in the lines marked //* :

public static <D, K, T extends Enum<T> & Fields<?, ?, D>> List<EnumMap<T, D>> 
        getEntries(InputStream is, Class<T> fields) throws IOException {
    final List<List<Byte>> entries = new ArrayList<List<Byte>>();
    // populate "entries"
    final boolean hasLists = hasLists(fields);
    List<K> daBytes;
    if (hasLists) {
        daBytes = (List<K>) new ArrayList<EnumMap<T, List<List<Byte>>>>(); //*
    } else {
        daBytes = (List<K>) new ArrayList<EnumMap<T, List<Byte>>>(); //*
    }
    final int numOfEntries = entries.size();
    for (int currentEntry = 0; currentEntry < numOfEntries; ++currentEntry) {
        // add an element in daBytes for this currentEntry
        if (hasLists) {
            daBytes.add((K) new EnumMap<T, List<List<Byte>>>(fields)); //*
        } else {
            daBytes.add((K) new EnumMap<T, List<Byte>>(fields)); //*
        }
        for (T daField : fields.getEnumConstants()) {
            List<Byte> field = new ArrayList<Byte>();
            // populate "field"
            D map = (D) daBytes.get(currentEntry);
            if (hasLists) {
                List<List<Byte>> fieldEntries = new ArrayList<List<Byte>>();
                // populate "fieldEntries"
                ((EnumMap<T, List<List<Byte>>>) map).put(daField,
                    fieldEntries); //*
            } else {
                ((EnumMap<T, List<Byte>>) map).put(daField, field); //*
            }
        }
    }
    return (List<EnumMap<T, D>>) daBytes; //*
}

如果 hasLists 是false,那么我需要D作为 List else a List< List< Byte>> daList 变量是 List< EnumMap< T,D>> 。现在看起来很自然(对我)定义:

If hasLists is false then I need D to be a List<Byte> else a List<List<Byte>>. The daList variable is a List<EnumMap<T, D>>. Now it would seem natural (to me) to define :

List<EnumMap<T, D>> daBytes;

但是一旦我这样做并改变:

But as soon as I do this and change :

if (hasLists) {
    daBytes = (List<EnumMap<T, D>>) new ArrayList<EnumMap<T, List<List<Byte>>>>();
}

我收到错误:


无法从 ArrayList >>> 转换为 List< EnumMap< T,D>>

对象,列表<?> 等,但总是使用导致警告的直接投射或通用投射。必须有一个方法来让这个编译干净,没有转换

Been going round in circles making daBytes an Object, a List<?> etc but always getting to use either outright casts or generic casts that lead to warnings. There must a way to have this compile cleanly with no casts

推荐答案

我做了一些重构,提取一个方法对象正如其他海报所建议的。这是所谓的策略类设计模式的一个实例。

I did a bit of refactoring, extracting a "method object" as suggested by other posters. This is an instance of the so called "strategy class" design pattern.

无论您在上有支票hasLists 我介绍了一个抽象方法。事实证明,你不再需要 K 类型参数。

Wherever you have a check on hasLists I introduced an abstract method. It turns out that you do not need the K type parameter anymore.

代码产生一个未检查的警告顶部,我在 hasLists 上选中了抽象类的实现。

The code produces one unchecked warning at the top, where I have put a check on hasLists to choose an implementation of the abstract class.

public static <X, T extends Enum<T> & Fields<?, ?, List<X>>>
List<EnumMap<T, List<X>>> getEntries(InputStream is, Class<T> fields) throws IOException {
    final List<List<Byte>> entries = new ArrayList<List<Byte>>();
    // populate "entries"

    FieldsStrategy<X, T> strategy = selectStrategy(fields);
    return strategy.getEntries(entries);
}

private static <X, T extends Enum<T> & Fields<?, ?, List<X>>>
FieldsStrategy<X, T> selectStrategy(Class<T> fields) {
    final boolean hasLists = hasLists(fields);
    return hasLists
            ? (FieldsStrategy<X, T>) new ByteListFieldsStrategy(fields) //* this is the only unchecked warning
            : (FieldsStrategy<X, T>) new ByteFieldsStrategy(fields);    //* this is the only unchecked warning
}

private abstract static class FieldsStrategy<X, T extends Enum<T> & Fields<?, ?, List<X>>> {
    private Class<T> fields;

    public FieldsStrategy(Class<T> fields) {
        this.fields = fields;
    }

    public List<EnumMap<T, List<X>>> getEntries(List<List<Byte>> entries) {

        List<EnumMap<T, List<X>>> daBytes = new ArrayList<EnumMap<T, List<X>>>();
        final int numOfEntries = entries.size();
        for (int currentEntry = 0; currentEntry < numOfEntries; ++currentEntry) {
            // add an element in daBytes for this currentEntry
            daBytes.add(new EnumMap<T, List<X>>(fields));
            for (T daField : fields.getEnumConstants()) {
                EnumMap<T, List<X>> map = daBytes.get(currentEntry);
                map.put(daField, getFieldData(daField));
            }
        }
        return daBytes;
    }

    protected abstract List<X> getFieldData(T daField);

}

public static class ByteFieldsStrategy<T extends Enum<T> & Fields<?, ?, List<Byte>>>
        extends FieldsStrategy<Byte, T> {
    public ByteFieldsStrategy(Class<T> fields) {
        super(fields);
    }

    protected List<Byte> getFieldData(T daField) {
        ArrayList<Byte> field = new ArrayList<Byte>();
        // populate "field"
        return field;
    }
}

public static class ByteListFieldsStrategy<T extends Enum<T> & Fields<?, ?, List<List<Byte>>>>
        extends FieldsStrategy<List<Byte>, T> {
    public ByteListFieldsStrategy(Class<T> fields) {
        super(fields);
    }

    protected List<List<Byte>> getFieldData(T daField) {
        List<List<Byte>> fieldEntries = new ArrayList<List<Byte>>();
        // populate "fieldEntries"
        return fieldEntries;
    }
}

您可能可以移除 hasLists()逻辑,并切换到 Fields 接口选择使用哪个策略类, code> enum 类。

You probably can remove the sole remaining unchecked warning by moving hasLists() logic and the switch to choose which strategy class to use to the Fields interface and implementing it in the enum classes.

UPDATE: > selectStrategy 和字段不会提出任何警告:

UPDATE: here is the updated definition of selectStrategy and Fields which does not raise any warnings:

public static interface Fields<T extends Enum<T> & Fields<T, D, K>, D extends Data, K> {
    // ....

    GetEntries<K, T> selectStrategy();
}

private static <K, T extends Enum<T> & Fields<T, ?, K>>
GetEntries<K, T> selectStrategy(Class<T> fields) {
    for (T field : fields.getEnumConstants()) {
        return field.selectStrategy();
    }
    throw new IllegalArgumentException("Enum type has no instances: " + fields);
}

您需要实现 selectStrategy c $ c>在枚举类型并返回一个适当的 GetByteEntries GetByteListEntries

You need to implement selectStrategy() in your enum types and return either an appropriate GetByteEntries or GetByteListEntries.

现在可以移除 hasLists()

这篇关于在通用方法中对必须在列表中使用的参数取消选中强制转换警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆