相关疑难解决方法(0)

Java的类型擦除有什么好处?

我今天读了一条推文说:

当Java用户抱怨类型擦除时,这很有趣,这是Java唯一正确的做法,而忽略了所有错误的东西.

因此我的问题是:

Java的类型擦除是否有好处?除了JVM实现偏向于向后兼容性和运行时性能之外,它(可能)提供的技术或编程风格有哪些优势?

java type-erasure

90
推荐指数
8
解决办法
1万
查看次数

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

为什么以下代码编译?该方法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
查看次数

表观类型违规,但编译

为什么下面的代码片段会编译?OtherInterface没有扩展,Concrete所以我打赌肾脏,这将无法编译.但确实如此.

public class Test {

    public static interface SomeInterface {}

    public static interface OtherInterface{}

    public static class Concrete implements SomeInterface {

       public <T extends Concrete> T getConcrete() {
            return null;
       }
    }

    public static void doStuff() {
        Concrete c = new Concrete();
        OtherInterface iCompile = c.getConcrete();
    }
}
Run Code Online (Sandbox Code Playgroud)

另一方面,下一个片段不能编译,这是我所期望的.

public class Test {

    public static interface SomeInterface {}

    public static class UnrelatedClass{}

    public static class Concrete implements SomeInterface {

       public <T extends Concrete> T getConcrete() { …
Run Code Online (Sandbox Code Playgroud)

java generics

14
推荐指数
1
解决办法
149
查看次数

如何推断泛型方法调用的类型参数?

有这样的方法吗?

public <P, T extends List<P>> T getAwesomeList() {
    // ...
} 
Run Code Online (Sandbox Code Playgroud)

怎么编译没有任何警告?

Set<String> test = getAwesomeList();
Run Code Online (Sandbox Code Playgroud)

我认为这与通用擦除有关,但不确定编译器是怎么回事.这种情况发生在Java 7上,8时你会收到编译错误.

J8上有什么变化让这个不能编译?

更新:

经过仔细检查后,它还可以在Java 8上编译.

java generics type-inference java-7 java-8

6
推荐指数
0
解决办法
238
查看次数

为什么javac无法使用有界类型参数作为返回类型来检查静态方法的调用站点?

为什么javac不在此代码示例中中止类型错误

import java.util.List;

public class StaticMethodWithBoundedReturnType {
    static class Foo {
    }

    static class Bar extends Foo {
    }

    static <F extends Foo> F getFoo(String string) {
        …
    }

    public static void main(String[] args) {
        // Compiles without error, even though List does not extend Foo.
        List<Integer> list = getFoo("baz");
    }
}
Run Code Online (Sandbox Code Playgroud)

显然List永远不可能是一个子类型Foo.即使存在一个List以某种方式扩展的子类型Foo,那么list在呼叫站点的分配getFoo()应该是无效的.我知道类型擦除的存在.但是不javac应该看到类型list不满足有界类型约束extends Foo因此失败编译时出现类型错误?

为什么javac无法使用有界类型参数作为返回类型来检查静态方法的调用站点?

看来我可以通过以下轻微修改获得类型安全性:

import java.util.List; …
Run Code Online (Sandbox Code Playgroud)

java generics return-type

6
推荐指数
1
解决办法
95
查看次数

为什么 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
查看次数