在java中输入推断

时间:2015-09-01 08:14:24

标签: java generics types

你能否解释一下为什么以下工作方式呢? 在我看来,java类型系统很难推断R的类型

public class Test {

interface Parser<A,R>{
    R parse(A a);
}

static class ResponseParser implements Parser<String,Integer>{

    public Integer parse(String s) {
        return Integer.parseInt(s) + 1;
    }
}

interface Function<A,R>{
    R with(A a);
}

public static <A,R,P extends Parser<A,R>> Function<P,R> getResult(final A res){
        return new Function<P, R>() {
            public R with(P parser) {
                return parser.parse(res);
            }
        };
}

public static void main(String [] args){
    Function<Parser<String,Integer>, Integer> func = getResult("1");
    //this works
    func.with(new ResponseParser());
    // why this does not work
    getResult("1").with(new ResponseParser());
}


}

2 个答案:

答案 0 :(得分:4)

getResult("1").with(new ResponseParser());表达式中,无法从上下文中正确推断出getResult("1")子表达式的类型。您认为它应该是Function<? extends Parser<String, Integer>, Integer>,但此子表达式对Integer一无所知。在第一种情况下,您将结果分配给Function<Parser<String,Integer>, Integer>,因此可以解析R = Integer类型,但是当您只是调用其他方法时,它就无法正常工作。

你可以解决这个推迟推断返回类型的必要性。像这样:

interface ParserFunction<A> {
    <R> R with(Parser<A, R> a);
}

public static <A> ParserFunction<A> getResult(final A res){
        return new ParserFunction<A>() {
            public <R> R with(Parser<A, R> parser) {
                return parser.parse(res);
            }
        };
}

现在getResult("1").with(new ResponseParser());有效。

答案 1 :(得分:1)

泛型仅供编译器使用,以确保您不违反指定类型的规则。在运行时,所有泛型都转换为Object,但确保类型安全,因为编译器会通知您任何违规或类型安全。为了达到这个目的,你需要告诉编译器你正在尝试使用什么,这就是为什么不推断泛型。

使用java generics https://docs.oracle.com/javase/tutorial/java/generics/genMethods.html

检查擦除