具有通用返回类型的Java方法

Har*_*eur 0 java generics casting return-type generic-method

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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望该方法返回一个对象,然后在函数调用中将其云转换为正确的类型。那是我的想法,但它不能像这样工作。我需要某种通用的返回类型来做到这一点吗?解决这个问题的最佳方法是什么?

VGR*_*VGR 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然您可以编写return (T) tmpObject;,但由于不安全,将生成一个编译器警告:由于编译器仅知道T可能是Object(或Object本身)的某个后代,因此编译器生成(Object),这与完全不执行操作相同。代码盲目地假设返回的对象是T类型,但是如果不是,则当程序尝试调用T中定义的方法时,您将得到一个意外的异常。最好在对对象进行反序列化后立即知道它是否为预期的类型。

如果对列表进行不安全的转换,也会发生类似的事情:

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!
Run Code Online (Sandbox Code Playgroud)


Daw*_*ica 2

您可以在返回类型中使用泛型。它可能看起来像这样。简而言之,编译器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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 转换为泛型类型是不安全的,并且会生成编译器警告。该方法应该接受第二个参数,例如“Class&lt;T&gt; targetClass”,并且应该对反序列化值调用“targetClass.cast”。 (2认同)