gpt4 book ai didi

java - 以下代码是否应该在 Java 1.8 下编译

转载 作者:搜寻专家 更新时间:2023-10-30 19:47:14 26 4
gpt4 key购买 nike

给出以下类:

public class FooTest {

public static class Base {
}

public static class Derived extends Base {
}

public interface Service<T extends Base> {
void service(T value);
}

public abstract class AbstractService<T extends Derived> implements Service<T> {
public void service(T value) {
}
}

private AbstractService service;

public void bar(Base base) {
if(base instanceof Derived) {
service.service(base); // compile error at this line
}
}
}

使用以下 pom.xml 构建类时:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mgm-tp</groupId>
<artifactId>java-compiler-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

在 maven 3.4 中它会产生以下编译错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.3:compile (default-compile) on project java-compiler-test: Compilation failure [ERROR] C:\Users\abrieg\workingcopy\java-compiler-test\src\main\java\FooTest.java:[25] The method service(FooTest.Base) in the type FooTest.Service is not applicable for the arguments (FooTest.Base)

当将 eclipse 编译器的源和目标级别设置为 1.7 或使用 javac 作为编译器时,不会报告编译错误。

问题是 JLS 1.8 是否在类型推断方面更具体,以致于 java 1.8 的 eclipse 编译器实际上不允许此代码,或者这是否是 eclipse 编译器中的回归。

根据编译器错误的文本,我倾向于说它是回归,但我不确定。

我已经确定了以下两个已报告给 jdt 的错误,但我认为它们并不完全适用:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=432603 https://bugs.eclipse.org/bugs/show_bug.cgi?id=430987

如果这是回归,是否已经向 jdt 报告过?

最佳答案

据我所知,这段代码应该可以编译,但当然不是没有未经检查的警告。

你声明了一个变量service 原始类型 AbstractService这是原始类型的子类型Service它有一个方法 void service(Base)这是void service(T)的删除.

所以调用service.service(base)可以调用该方法 void service(Base)Service 中声明,当然,带有未检查警告,因为该方法是通用的,并且没有验证类型参数 T发生了。

这可能是违反直觉的类型 AbstractService使用删除为 void service(Derived) 的方法覆盖该方法但是这个方法只能在通用上下文中覆盖另一个方法,而不是在原始类型继承关系中。

或者,换句话说,类型不能以比被覆盖的父类(super class)型方法对参数类型有更多限制的方式覆盖方法。

这也适用于通用类型继承,但结果不同。如果您的变量类型为 AbstractService<X> , 然后 X必须可分配给 Derived由于类型参数的约束。此类型 AbstractService<X>Service<X> 的子类型它有一个方法 void service(X) (如 T := X )被 AbstractService<X> 覆盖(实现)用一种方法 void service(X)它接受相同的参数类型。


由于您的网站上似乎有些困惑,我想强调这与您的if(… instanceof Derived)无关。陈述。如上所述,此行为是由于使用了原始类型,这意味着您正在使用 AbstractService没有实际的类型参数并且基本上关闭了泛型类型检查。如果你写了,这甚至会起作用

public void bar(Base base) {
service.service(base); // UNCHECKED invocation
}

如果您将变量的声明更改为

private AbstractService<Derived> service;

它不再是原始类型,类型检查将会发生并且service.service(base)将产生一个编译器错误,无论你是否用 if(base instanceof Derived) { … } 将其括起来还是不是。

原始类型 的存在只是为了与泛型之前的代码兼容,您应该避免使用它们,并且不要忽略因使用原始类型 而引发的警告。

关于java - 以下代码是否应该在 Java 1.8 下编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29700417/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com