Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
扩展方法返回类型的Java泛型_Java_Generics_Methods_Return Type - Fatal编程技术网

扩展方法返回类型的Java泛型

扩展方法返回类型的Java泛型,java,generics,methods,return-type,Java,Generics,Methods,Return Type,看看这三门课。 Minatchi允许自己进行扩展,以便其方法的返回类型也可以扩展。为了说明这一点,我使用了静态方法 public class Minatchi<T extends Minatchi<?>>{ static public <T extends Minatchi<?>> List<T> listAll(){ return (List<T>) query(); } }

看看这三门课。 Minatchi允许自己进行扩展,以便其方法的返回类型也可以扩展。为了说明这一点,我使用了静态方法

public class Minatchi<T extends Minatchi<?>>{

  static public <T extends Minatchi<?>>
    List<T> listAll(){
      return
        (List<T>) query();
  }
}
公共类Minatchi>
List listAll(){
返回
(列表)查询();
}
}
所以我把米纳奇归类为女士

public class Lady
extends Minatchi<Lady>{

}
public-class-Lady
米纳奇酒店{
}
这就是可疑行为发生的地方

public class HelloMinatchi{

  private void listA(){
    List<Lady> uvs = Lady.listAll();
    for (Lady uv: uvs){
      logger.info(uv.getName() );
    }
  }

  private void listB(){
    for (Lady uv: Lady.listAll()){
      logger.info(uv.getName() );
    }
  }
}
公共类HelloMinatchi{
私有无效列表a(){
List uvs=Lady.listAll();
适用于(女士uv:uv){
logger.info(uv.getName());
}
}
私有无效列表b(){
for(Lady uv:Lady.listAll()){
logger.info(uv.getName());
}
}
}
方法listA和listB本质上是相同的。 listA将列表放入中间变量uvs中, 而listB直接将listAll放入for循环头中

然而,对于listB,编译器抱怨无法将Minatchi转换为Lady

所以这个问题是关于Java泛型的设计完整性的。还有一种仿制药抱怨

这是一个故意的设计特性还是Java泛型设计人员不知道如何解决的无意设计缺陷。如果是故意的,他们为什么这样做?如果是bug,他们是否计划解决它

或者这是我个人的问题,我不知道更好的方法来声明泛型?如果是,告诉我怎么做


(我使用了一个泛型Minatchi类,因为我也有非静态方法要暴露于类扩展,我在问题中忽略了这一点。)

您的问题是让编译器推断listAll方法的泛型参数,在第一种情况下,它推断出您想要的参数,因为您将结果存储在一个变量中,它可以只查看变量的类型。在第二种情况下,它无法自动推断“正确”类型,因此您需要自己指定:

for (Lady uv: Lady.<Lady>listAll()){
    logger.info(uv.getName() );
}
for(Lady-uv:Lady.listAll()){
logger.info(uv.getName());
}
请注意,在这个示例中,Minatchi类没有理由是泛型的,因为它根本不会影响静态方法


还请注意,调用Lady.listAll与调用minachi.listAll完全相同(即,它不影响编译器可以或将推断为泛型参数的类型)。

静态方法不从类中获取泛型类型定义。i、 e.
listAll()
方法不知道
Lady
(在
中)

其返回类型由表达式的左侧推断:

  • listA()
    中,左侧定义了它需要
    List
  • listB()
    中,forEach循环看起来也应该是一个
    Lady
    ,但编译器似乎没有正确指示forEach循环
使
listB()
工作的方法是告诉它要使用的泛型类型:

for (Lady uv : Lady.<Lady>listAll()) {..}
for(Lady-uv:Lady.listAll()){..}

不幸的是,正如我在另一个问题中提到的:,Java中的隐式类型推断只在赋值中起作用


我还是不知道原因。不过,这对我来说仍然很愚蠢。

这是因为类型擦除

在实例化泛型类型时, 编译器通过 一种称为类型擦除的技术-a 编译器删除所有 与类型参数相关的信息 和类或类中的类型参数 方法

因为调用Lady.ListAll是在原始类型Minatchi上执行的,所以编译器无法知道特定类型是Minatchi


泛型使用类型擦除,以便泛型类型与泛型添加到库之前编译的Java库兼容。已经做了一些努力,但它不在Java7的路线图上。

Lady.listAll(),而不是Lady.listAll();)(为您更正)如果编译器可以从变量推断,那么从for循环头中的变量推断类型肯定不会有问题。对于(Lady uv:Lady.listAll()),这个问题不是关于是否应该使用中间变量。相反,这是关于为什么语言设计者忘记了适应for循环?为什么他们没有/不能使用for循环变量?瞧,他们在抽什么?谢谢。我应该在发布前测试一下。真的吗?我认为类型擦除只发生在运行时。此错误发生在编译时。@nanda:类型擦除发生在编译时-如果在运行时知道类型,则不需要擦除它。我的意思是,是的擦除发生在编译时,因此运行时不知道泛型类型,但在编译类之前会进行错误检查。如果它有错误怎么能编译呢?谢谢bozho。我抽的是什么?我使用了一个通用的Minatchi类,因为我也有非静态的方法暴露于类扩展中,我在问题中忽略了这一点。