相关疑难解决方法(0)

泛型返回类型上限 - 接口与类 - 令人惊讶的有效代码

这是来自第三方库API的真实示例,但已简化.

使用Oracle JDK 8u72编译

考虑这两种方法:

<X extends CharSequence> X getCharSequence() {
    return (X) "hello";
}

<X extends String> X getString() {
    return (X) "hello";
}
Run Code Online (Sandbox Code Playgroud)

两者都报告了"未经检查的演员"警告 - 我明白了.困扰我的是我为什么打电话

Integer x = getCharSequence();
Run Code Online (Sandbox Code Playgroud)

它编译?编译器应该知道Integer没有实现CharSequence.打电话给

Integer y = getString();
Run Code Online (Sandbox Code Playgroud)

给出错误(如预期的那样)

incompatible types: inference variable X has incompatible upper bounds java.lang.Integer,java.lang.String
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么这种行为被认为是有效的?它会有用吗?

客户端不知道此调用是不安全的 - 客户端的代码在没有警告的情况下编译.为什么编译器不会警告/发出错误?

另外,它与这个例子有什么不同:

<X extends CharSequence> void doCharSequence(List<X> l) {
}

List<CharSequence> chsL = new ArrayList<>();
doCharSequence(chsL); // compiles

List<Integer> intL = new ArrayList<>();
doCharSequence(intL); // …
Run Code Online (Sandbox Code Playgroud)

java generics java-8

170
推荐指数
2
解决办法
3万
查看次数

为什么带绑定的泛型方法可以返回任何类型?

为什么以下代码编译?该方法IElement.getX(String)返回该类型IElement或其子类的实例.类中的代码Main调用该getX(String)方法.编译器允许将返回值存储到类型的变量中Integer(显然不在层次结构中IElement).

public interface IElement extends CharSequence {
  <T extends IElement> T getX(String value);
}

public class Main {
  public void example(IElement element) {
    Integer x = element.getX("x");
  }
}
Run Code Online (Sandbox Code Playgroud)

返回类型是否仍然是一个实例IElement - 即使在类型擦除之后?

getX(String)方法的字节码是:

public abstract <T extends IElement> T getX(java.lang.String);
flags: ACC_PUBLIC, ACC_ABSTRACT
Signature: #7                           // <T::LIElement;>(Ljava/lang/String;)TT;
Run Code Online (Sandbox Code Playgroud)

编辑:替换String与一致Integer.

java generics type-inference generic-method

33
推荐指数
1
解决办法
1418
查看次数

字符串被分配给List而没有编译错误

据我所知,Java中泛型的主要目的之一是提供编译时类型安全性.如果它被编译,代码将运行没有问题.

那么为什么要编译以下代码?

public static void main(String[] args) {
    String s = getList();
}

private static <T extends List> T getList() {
    return (T)new ArrayList();
}
Run Code Online (Sandbox Code Playgroud)

它汇编很好.我的类型安全编译在哪里?该getList()方法与String班级没有任何共同之处.

java string generics generic-type-argument type-safety

24
推荐指数
1
解决办法
374
查看次数

为什么 Java 允许使用泛型编译这段代码?

我最近被以下 Java 代码惊呆了:

interface Common {}

interface A extends Common {}

static class B implements Common {}

static class Impl {
  private A a;

  public <T extends A> T translate() {
    return (T) a;
  }
}

static class Usage {
  public void use() {
    Impl impl = new Impl();
    B b = impl.translate(); // Why does this compile?
  }
}
Run Code Online (Sandbox Code Playgroud)

我本来期望的是在类型约束Impl.translate不会允许将结果存储在类型B由编译器所接受,考虑到B不延长A。代码UncheckedCastException在运行时抛出一个,而不是编译器错误。

这仅在方法返回类型时发生T;如果它是方法参数:

  public <T extends A> …
Run Code Online (Sandbox Code Playgroud)

java generics

6
推荐指数
2
解决办法
181
查看次数