繁体   English   中英

如果在编译过程中将Java类型参数替换为其各自的边界,为什么以下代码不起作用?

[英]If Java type parameters are replaced with their respective bounds during compilation why the following code doesn't work?

class World{

  <T extends Class1> World(TreeSet<? extends ClassA> set){
    *some code*
  }

  <T extends Class2> World(TreeSet<? extends ClassB> set){
    *some code*
  }

}

上面的代码显示错误“名称冲突:<T#1> World和<T#2> World具有相同的擦除”。 为什么代码无法编译? 更重要的是,为什么编译器说它们具有相同的擦除? 我在该站点上发现的与该主题相关的所有问题都不会深入解释我的问题。

我在包含以下方法的类上使用Intellij Idea的Bytecode Viewer插件检查了问题:

public <A extends Calendar> void fn(ArrayList<? extends File> abc){  //line number:11
  A a=(A)new Object();  //line 12
}  //line number:13

以下是字节码查看器中与此方法相对应的字节码:

  // access flags 0x1
  // signature <A:Ljava/util/Calendar;>(Ljava/util/ArrayList<+Ljava/io/File;>;)V
  // declaration: void fn<A extends java.util.Calendar>(java.util.ArrayList<?extends java.io.File>)
public fn(Ljava/util/ArrayList;)V
  L0
    LINENUMBER 12 L0
    NEW java/lang/Object
    DUP
    INVOKESPECIAL java/lang/Object.<init> ()V
    CHECKCAST java/util/Calendar
    ASTORE 2
 L1
    LINENUMBER 13 L1
    RETURN
 L2
    LOCALVARIABLE this LMain; L0 L2 0
    LOCALVARIABLE abc Ljava/util/ArrayList; L0 L2 1
    // signature Ljava/util/ArrayList<+Ljava/io/File;>;
    // declaration: java.util.ArrayList<? extends java.io.File>
    LOCALVARIABLE a Ljava/util/Calendar; L1 L2 2
    // signature TA;
    // declaration: A
    MAXSTACK = 2
    MAXLOCALS = 3

看上面的第2行。 尽管已注释掉,但保留了具有适当范围的类型参数。 但是方法签名在编译后不包含任何类型参数(第4行)。 我们在第10行中再次看到保留的类型参数信息用于转换,它对应于原始代码的第12行。 因此得出的结论是类型参数并没有被其边界完全取代。 您的编译文件将保留有关类型参数及其范围的信息。 仅在编译器确定需要时才使用此保留的信息。 出于某种原因,编译器认为方法(或构造函数)不需要在编译文件中的声明中包含这些信息(这解释了“相同擦除”错误部分)。 当它不具有通用功能时,其原因与对Java版本的向后兼容性有关。 因此,仅更改/添加/删除类型参数和/或其边界不会使方法或构造函数过载。


我知道我的回答很粗略,但据我所知并非错误。 请提出我在评论中缺少的任何内容,或发表您自己的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM