具有泛型返回类型的Java方法

问题描述 投票:-1回答:2

在Java中有一种方法可以通过一个方法声明返回不同的类型吗?

public Object loadSerialized(String path) {
        Object tmpObject;
        try {
        FileInputStream fis = new FileInputStream(path);
        ObjectInputStream ois = new ObjectInputStream(fis);
        tmpObject = (Object) ois.readObject();
        ois.close();
        fis.close();
        return tmpObject;
        }
        catch(FileNotFoundException e) {return null;}
        catch(Exception e) {}
    }

我希望这个方法返回一个Object,然后我在函数调用中将它强制转换为正确的类型。这就是我的想法,但它不会像这样工作。我需要某种通用的返回类型才能执行此操作吗?解决这个问题的最佳方法是什么?

java generics casting return-type generic-method
2个回答
5
投票

要安全地执行此操作,您需要将所需类型作为Class对象传递:

public <T> T loadSerialized(String path, Class<T> targetType) {
    try (ObjectInputStream ois = new ObjectInputStream(
        new BufferedInputStream(
            new FileInputStream(path)))) {

        Object tmpObject = (Object) ois.readObject();
        return targetType.cast(tmpObject);
    } catch (FileNotFoundException e) {
        return null;
    } catch (IOException | ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

虽然你可以编写return (T) tmpObject;,但会生成编译器警告,因为它不安全:因为编译器只知道T可能是Object(或Object本身)的某个后代,编译器会生成(Object),这与无所事事相同一点都不代码盲目地假设返回的对象是T类型,但如果不是,当程序试图调用T中定义的方法时,您将得到一个惊喜异常。一旦您对对象进行反序列化,最好知道它是否是您期望的类型。

如果您对List执行不安全的强制转换,则会发生类似的事情:

List<Integer> numbers = Arrays.asList(1, 2, 3);

List<?> list = numbers;
List<String> names = (List<String>) list;  // Unsafe!

String name = names.get(0);    // ClassCastException - not really a String!

1
投票

您可以在返回类型中使用泛型。它可能看起来像这样。简单来说,编译器根据方法的调用方式为T选择最佳类型。然后铸造发生在方法内部,而不是外部。

请注意,我使用了try-with-resources语法,以避免与关闭流混乱。

public <T> T loadSerialized(String path) throws IOException, ClassNotFoundException {
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
        return (T) ois.readObject();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.