通用方法中需要的Java冗余转换

Mik*_*iku 6 java generics instanceof

我正在寻找一种使用通用函数优化代码库中某些内容的方法。有一个带有返回类型的函数,该函数List<Object>可能具有return type List<SpecifiedType>

贝娄是该函数的简约版本function。它采用参数类型,并基于它调用相应的函数(在此限于String)或泛型函数。

public static ArrayList<String> forString(){
    ArrayList<String> res = new ArrayList<>();
    // Fetching and processing data specific to String
    return res;
}

public static <T> ArrayList<T> forGeneric(Class<T> type){
    ArrayList<T> res = new ArrayList<>();
    // Fetching data
    return res;
}

public static <T> ArrayList<T> function(Class<T> type){
    if(type == String.class)
        return (ArrayList<T>) forString();
    return forGeneric(type);
}
Run Code Online (Sandbox Code Playgroud)

上面的函数的目标是这样调用的: ArrayList<SomeType> someTypes = function(SomeType.class);

关于以上代码,我注意到了两件事:

  1. 投射到ArrayList<T>尽管我们知道,如果类型需要String被作为参数传递它将返回ArrayList<String>就像forString()方法

  2. 演员要ArrayList<T>给予Unchecked cast警告,即使返回类型将是ArrayList<String>

我的问题是是否有更好的方法(最好没有演员),如果没有,那为什么

Mic*_*ael 4

首先,这个说法在逻辑上是错误的

if(type.isInstance(String.class))
Run Code Online (Sandbox Code Playgroud)

If typeis Class<String>thenisInstance正在检查参数是否是字符串实例。您传递的参数是一个类实例(具体来说, a Class<String>)。

如果你更喜欢,

String.class.isInstance(String.class) == false
Run Code Online (Sandbox Code Playgroud)

你的意思是

if(type == String.class)
Run Code Online (Sandbox Code Playgroud)

然而,即使解决了这个逻辑错误,您的代码仍然会出现未经检查的强制转换警告。

你缺少的部分就在这里

ArrayList<T>即使我们知道如果 String 类型作为参数传递,它也会ArrayList<String>forString()方法一样返回

确切地。我们知道。但我们所知道的和编译器所知道的是两件不同的事情。编译器不够聪明,无法检查条件并意识到类型是正确的。可以想象它可能足够聪明,但事实并非如此。

这正是为什么这表现为警告而不是错误的原因。这是一个警告,因为您所做的事情可能是错误的;它并不是绝对错误的,否则根本无法编译。在这种情况下,警告应该提示您仔细检查您正在做的事情是否正确,然后您就可以愉快地抑制它。

@SuppressWarnings("unchecked")
public static <T> ArrayList<T> function(Class<T> type){
    if(type == String.class)
        return (ArrayList<T>) forString();
    return forGeneric(type);
}
Run Code Online (Sandbox Code Playgroud)

最后——这可能是你设计的例子的产物——但所有这些方法都是无用的。与直接调用相比,似乎没有任何优势new ArrayList<>()。在运行时,实际实例是相同的,无论它来自 3 个方法中的哪一个。