Java方法调用中与类型参数相关的问题
Java 8的Java语言规范在“示例4.11-1.类型的使用”中提供了一个带有类型参数的方法调用示例:Java方法调用中与类型参数相关的问题,java,java-8,Java,Java 8,Java 8的Java语言规范在“示例4.11-1.类型的使用”中提供了一个带有类型参数的方法调用示例: void循环{ this.loop(s);//是方法调用的类型参数。 } 在该示例中,提供的类型参数是有意义的,但是显然,方法调用的类型参数也可能是冗余的,完全没有意义,甚至不需要涉及泛型。例如: void m() { } void test() { m(); this.m(); this.<Integer>m(); // Compiles and
void循环{
this.loop(s);//是方法调用的类型参数。
}
在该示例中,提供的类型参数是有意义的,但是显然,方法调用的类型参数也可能是冗余的,完全没有意义,甚至不需要涉及泛型。例如:
void m() { }
void test() {
m();
this.m();
this.<Integer>m(); // Compiles and runs OK!
this.<String, Byte, StringBuilder, Thread[], Throwable>m(); // Compiles and runs OK!
<Integer>m(); // Won't compile: "illegal start of expression"
}
void m(){}
无效测试(){
m();
这个.m();
this.m();//编译并运行正常!
this.m();//编译并运行正常!
m();//将不编译:“表达式的开头非法”
}
我有几个问题:
void m() { }
this.<String>m(); //legal
void m(){}
这个.m()//合法的
方法(和构造函数)引用仅继承此行为,如15.13所示:
“”如果方法引用表达式的形式为ReferenceType::[TypeArguments]标识符,则可能适用的方法是要搜索的类型的成员方法,其具有§15.12.2.1中规定的适当名称(由标识符给出)、可访问性、arity(n或n-1)和类型参数arity(源自[TypeArguments])。"
(注意:这没有类型参数)MethodName([ArgumentList])
TypeName.[TypeArguments]标识符([ArgumentList])
ExpressionName.[TypeArguments]标识符([ArgumentList])
Primary.[TypeArguments]标识符([ArgumentList])
super.[TypeArguments]标识符([ArgumentList])
TypeName.super.[TypeArguments]标识符([ArgumentList])
this
不允许这样做,但是static
调用和super
方法调用也可以有类型参数,这些参数是完全合法的
static void m() { }
void test() {
ClassName.<Integer>m();//Also compiles
}
static void m(){}
无效测试(){
ClassName.m();//也编译
}
除此之外,您将收到以下警告:
非泛型方法m()未使用的类型参数
代表以下的声明:
本条款意味着非泛型方法可能是潜在的
适用于提供显式类型参数的调用。
事实上,它可能被证明是适用的。在这种情况下,类型
参数将被忽略
它确实说,它可能(在运行时)被证明是适用的
而且
这一规则源于兼容性问题和可替代性原则。由于接口或超类可以独立于其子类型进行泛型,我们可以用非泛型方法重写泛型方法。但是,重写(非泛型)方法必须适用于泛型方法的调用,包括显式传递类型参数的调用。否则,子类型将无法替换其泛型超类型
我不知道为什么允许这样做,但在Eclipse中,您会收到一条警告“类型测试的非泛型方法m()未使用的类型参数;不应使用参数对其进行参数化”,这意味着不要这样做。--
this.m()
在语法上是有效的,如果键入了m
则有意义,但m()
是完全无效的语法。请参阅第二个问题,因为某些解析/语法困难。例如,x@bayou.io你的链接非常相关。Gábor Bakos在那里给出的关于为什么允许“无效”使用类型参数的答案有一定的说服力,尽管它解决了一个非常罕见的情况。@skomisa-我认为Bakos的答案是完全没有根据的。从未有过与非泛型的可比性目标。您在JLS15.12.2.1中的引用肯定明确了允许/忽略类型参数的原因,尽管在不使用泛型且调用的方法没有参数的情况下,这似乎有点牵强。Andreas在上面的评论中指出,Eclipse至少给出了一个编译器警告。我使用的是OracleJDK8U60,它根本不提供任何警告。
static void m() { }
void test() {
ClassName.<Integer>m();//Also compiles
}