简体   繁体   English

难以控制的投放警告

[英]Difficult unchecked cast warnings

I'm trying to clean up some legacy code and have some unchecked cast warnings I'm struggeling to get rid of. 我正在尝试清理一些旧代码,并尝试消除一些unchecked cast强制转换警告。

I've extracted the code giving the warnings into a compilable program below. 我将给出警告的代码提取到下面的可编译程序中。 Note that I removed much of the code to make it smaller so all of it might not make complete sense. 请注意,我删除了许多代码以使其更小,因此所有这些代码可能都不完全有意义。 It compiles, but running it wont do anything. 它可以编译,但是运行它不会做任何事情。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;

public class GenericsTest {

    public static void main(String[] args) throws IOException {
        Reader reader = new Reader();
        List<String> stringEntries = reader.readAll(StringEntry.class);
    }

    public static class Reader {

        public <T> ZipInputStream getInputStream(String fileName) throws ZipException, FileNotFoundException {
            return new ZipInputStream(new FileInputStream(fileName));//_file.getInputStream(_paths.get(fileName));
        }

        public <T, TEntry extends Entry<T>> List<T> readAll(Class<TEntry> type) throws IOException {
            List<T> list = new ArrayList<T>();
            List<TEntry> entries = createEntries(type);
            for (TEntry entry : entries) {
                list.add(read(entry));
            }
            return list;
        }

        public <T> T read(Entry<T> entry) throws IOException {
            ZipInputStream is = null;
            try {
                //is = _archive.getInputStream(entry.getName());
                return entry.read(is);
            } finally {
                if (is != null) {
                    is.close();
                }
            }
        }

        public <TEntry extends Entry> List<TEntry> createEntries(Class<TEntry> type) throws ZipException {
            List<TEntry> entries = new ArrayList<TEntry>();
            List<String> paths = new ArrayList<String>();//getPaths(type);
            for (String path : paths) {
                entries.add(createEntry(type, path));
            }
            return entries;
        }

        public <TEntry extends Entry> TEntry createEntry(Class<TEntry> type, String folder) {
            if (StringEntry.class.equals(type)) {
                return (TEntry) new StringEntry(folder);
            } else if (IntegerEntry.class.equals(type)) {
                return (TEntry) new IntegerEntry(folder);
            }
            throw new IllegalArgumentException("Unknown type: " + type);
        }
    }

    public static abstract class Entry<T> extends ZipEntry {

        private T _data;

        public Entry(T data, String folder, String name) {
            super(folder + "/" + name);
            _data = data;
        }

        protected abstract T read(InputStream is) throws IOException;
    };

    public static class StringEntry extends Entry<String> {

        public StringEntry(String folder) {
            super("Hallo world!", folder, "StringEntry");
        }

        @Override
        protected String read(InputStream is) throws IOException {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };

    public static class IntegerEntry extends Entry<Integer> {

        public IntegerEntry(String folder) {
            super(42, folder, "IntegerEntry");
        }

        @Override
        protected Integer read(InputStream is) throws IOException {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };
}

Compiling the above code gives the following warnings 编译以上代码会给出以下警告

GenericsTest.java:57: warning: [unchecked] unchecked cast 
found: GenericsTest.StringEntry
required: TEntry
                return (TEntry) new StringEntry(folder);
GenericsTest.java:59: warning: [unchecked] unchecked cast 
found: GenericsTest.IntegerEntry
required: TEntry
                return (TEntry) new IntegerEntry(folder);
2 warnings

Changing 改变中

public <TEntry extends Entry> TEntry createEntry...

to

public <TEntry extends Entry<T>> TEntry createEntry...

gives a compiler error ( cannot find symbol: class T ). 给出编译器错误( cannot find symbol: class T )。

I don't want to change the code too much since it is working fine, so how can I fix (not hide) the warnings with the least code changes? 我不想对代码进行太多更改,因为它可以正常工作,那么如何在代码更改最少的情况下修复(而不是隐藏)警告?

If you want to use more than one generic parameter you will need to specify it in the parameter list. 如果要使用多个通用参数,则需要在参数列表中指定它。 Can you try this? 你可以试试这个吗?

public <T, TEntry extends Entry<T>> TEntry createEntry(...

UPDATE 更新

I had some time to play with this and put those nice class objects in use: 我花了一些时间来处理这个问题,并使用了那些不错的类对象:

    public <T, TEntry extends Entry<T>> List<TEntry> createEntries(Class<TEntry> type) throws ZipException {
        List<TEntry> entries = new ArrayList<TEntry>();
        List<String> paths = new ArrayList<String>();//getPaths(type);
        for (String path : paths) {
            entries.add(createEntry(type, path));
        }
        return entries;
    }

    public <T, TEntry extends Entry<T>> TEntry createEntry(Class<TEntry> type, String folder) {
        if (StringEntry.class.equals(type)) {
            return type.cast(new StringEntry(folder));
        } else if (IntegerEntry.class.equals(type)) {
            return type.cast(new IntegerEntry(folder));
        }
        throw new IllegalArgumentException("Unknown type: " + type);
    }
}

You're already passing the Class object into the method, just use Class.cast() : 您已经将Class对象传递到方法中,只需使用Class.cast()

public <TEntry extends Entry<?>> TEntry createEntry(Class<TEntry> type, String folder) {
    if (StringEntry.class.equals(type)) {
        return type.cast(new StringEntry(folder));
    } else if (IntegerEntry.class.equals(type)) {
        return type.cast(new IntegerEntry(folder));
    }
    throw new IllegalArgumentException("Unknown type: " + type);
}

The above change makes your code compile without warnings for me. 上面的更改使您的代码在没有警告的情况下进行编译。

Also, the <T> in the signature of getInputStream() is probably not necessary. 另外, getInputStream()签名中的<T>可能不是必需的。

IMHO for legacy code, to make it generic friendly can be quite an experience, specially if you have a large base of code... Since probably this code has been deployed, would you not consider an iterative approach? 对于旧代码的恕我直言,使其具有通用友好性可以是一种很好的体验,特别是如果您有大量的代码基础...由于可能已部署了此代码,您是否不考虑采用迭代方法?

By iterative approach I mean... Get all your warning and eliminate them with @SuppressWarning, and with a TODO annotation then, as the time goes by, every time you need to do a change in your code, if you stumble upon a TODO, just change it then... 用迭代的方法,我的意思是...得到所有警告,并通过@SuppressWarning和TODO注释将其消除,然后,随着时间的流逝,每次您需要更改代码时,如果偶然发现了TODO, ,然后更改它即可...

I am just saying in case that you are just migrating to Java 5 and have thousands of warnings.. 我只是说,以防您刚迁移到Java 5并收到数千条警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM