【问题标题】:Java Generics Creating Array from ClassJava泛型从类创建数组
【发布时间】:2011-10-27 12:17:23
【问题描述】:

我有一个层次结构,其中 Square、Triangle 和 Circle 都从 Shape 延伸。我有一个工作方法:

public void someMethod() {
   File file = new File("File_with_squares");
   ThirdPartyClass foo = new ThirdPartyClass();
   Square[] squares = foo.someMajicMethod(Square[].class,file);
   for (Square square: squares) 
      square.draw();

}

现在我想让这个方法通用,以便它可以接受任何形状。我希望能够将其称为someMethod(Triangle.class,new File("File_with_triangles") 或someMethod(Circle.class, new File("File_with_circles")。我正在尝试这样:

public void someMethod(Class<? extends Shape> type, File shapeFile) {
   ThirdPartyClass foo = new ThirdPartyClass();
   #### What goes here??? ####
   for (Shape shape: shapes)
       shape.draw();
}

#### 应该有什么?这里有什么? #### ???

【问题讨论】:

  • 答案几乎完全取决于ThirdPartyClass 和someMajicMethod 是什么

标签: java arrays generics


【解决方案1】:

假设 ThirdPartClass.someMajicMethod 有这样的签名:

public <T> T someMajicMethod(Class<T> class1, File file);

那么你应该可以做这样的事情:

public void someMethod(Class<? extends Shape> type, File shapeFile) {
    ThirdPartyClass foo = new ThirdPartyClass();

    @SuppressWarnings("unchecked")
    Class<? extends Shape[]> arrayType = 
        (Class<? extends Shape[]>) Array.newInstance(type, 0).getClass();
    assert Shape[].class.isAssignableFrom(arrayType);

    Shape[] shapes = foo.someMajicMethod(arrayType, shapeFile);

    for (Shape shape: shapes)
        shape.draw();
}

因此,如果您调用someMethod(Triangle.class, file),那么arrayType 在对someMajicMethod 的调用中将是Triangle[].class。

虽然您可能会发现让 someMethod 将数组类型作为参数而不是元素类型更简单,但您可以避免该步骤。

【讨论】:

  • 简单的assert Shape.class.isAssignableFrom(type)怎么样?
  • type 的类型已由编译器强制执行。我断言arrayType 的类型是因为我们刚刚进行了未经检查的强制转换(泛型类型信息将在编译时被删除)。此外,除非您在 VM 中显式启用它们,否则 Java 中的断言将不会执行。断言更好地用作文档而不是执行。在这种情况下,我可以保证该断言将始终通过,除非 Array.newInstance 被破坏。
【解决方案2】:

也许你对Array.newInstance(..) 感兴趣

【讨论】:

  • 他没有在这个方法的任何地方创建一个数组
  • @newacct 不,他不是,但在他的绝妙方法的某一时刻,他可能想要这样做。如果您取消对象序列化,则没有那么多可能性。在我看来,通过他的泛型类型参数创建这个数组的兴趣点。还是您认为我的假设有误?
【解决方案3】:
Shape[] shapes = foo.someMajicMethod(type, file);

如果foo 是第三方类,我假设你不控制它的API。我认为它具有适当的方法签名来处理我编写的行,但如果没有关于该类的更多信息,我无法确定。

如果这不起作用,是什么问题?

【讨论】:

  • someMajicMethod返回一个数组是好事,如果是List就复杂了。 Square[] 可以转换为 Shape[],但不能将 List 转换为 List。
  • 我对这个问题的解读是,如果你将Triangle.class 传递给 someMajicMethod,那么它将返回一个三角形,而不是一个三角形[]
  • @Aaron 也许 Mohamed 应该将方法更改为 someMethod(Class&lt;? extends Shape[]&gt; type,...)。
  • 是的。我通过使 someMethod 采用数组类型来使其工作。所以它是这样的: someMethod(Class extends Shape[]> arrayType, File shapeFile) { Shape[] shapes = foo.someMajicMethod(arrayType,shapeFile) }
  • @Mohamed - 很高兴它对你有用!如果您解决了问题,请不要忘记接受答案。
猜你喜欢
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
  • 1970-01-01
相关资源
最近更新 更多