13

假设定义了以下类:

class Shape { }
class Circle extends Shape {  }
class Rectangle extends Shape { }  //  1

您可以编写一个通用方法来绘制不同的形状:

public static <T extends Shape> void draw(T shape) { }   // 2

Java 编译器将 T 替换为 Shape:

public static void draw(Shape shape) {  } // 3

我的问题是,如果我们在类中直接定义 // 3 那么我们仍然可以传递Shape,CircleRectangle引用 //3 处的方法。那么为什么我们需要编写 // 2 泛型方法,其类型参数<T extends Shape>与 //3 不合时宜?

您可以使用相同的示例参考此链接:http: //docs.oracle.com/javase/tutorial/java/generics/genMethods.html

4

5 回答 5

12

您可能需要也可能不需要它。如果您的方法必须处理T必须与类型T extends Shape完全匹配的其他类型的对象,则需要它,例如:

public static <T extends Shape> void drawWithShadow(T shape, Class<T> shapeClass) {
    // The shadow must be the same shape as what's passed in
    T shadow = shapeClass.newInstance();
    // Set the shadow's properties to from the shape...
    shadow.draw(); // First, draw the shadow
    shape.draw();  // Now draw the shape on top of it
}

上面,通过Shape是不够的,因为我们无法制作完全相同类型的阴影。

如果没有这样的要求,一个简单的Shape就足够了。

于 2013-03-21T14:17:22.193 回答
2

在这种特殊情况下,您不需要通用方法。

但是您可以在泛型方法中做更多的事情,而不是在其参数上调用动态链接的方法。

例如,您可能有一个接受并返回 T 元素集合的泛型方法。按类型参数化它允许您在多种集合类型上使用它。

本Java 教程中提供了其他有用的泛型方法示例。

于 2013-03-21T14:16:37.260 回答
2

在您的示例中,//3 确实与//2 相同。但在其他用例中,泛型类型可能有用:

  • 您想从方法中返回与参数相同类型的值

  • 您有 2 个或更多参数并希望设置它们必须为同一类型的限制

于 2013-03-21T14:22:55.980 回答
2

不同之处在于您使用的多态性类型。

在一般情况下,您使用的是参数多态性 ,而在第二种情况下,您使用的是 subtype 的多态性。实际上,您的第一个案例使用了两种多态性。

现在,它们在某些方面可能相似,但它们并不相同。一个实际的例子:

List<Shape> shapes;
List<T extends Shape> specificShapes;

您可以看到,在第一种情况下,没有类型参数,我无法管理 Shape 的特定子类型的列表,我只能管理一个固定的形状列表,但我无法强制使用任何特定的形状. 所以我没有任何编译时果汁禁止我将 aTriangle和 a添加Rectangleshapes.

class ShapeDecorator {
  private Shape shape;

  ..

  Shape get() { return shape; }
}

class ShapeDecorator<T extends Shape> {
  private T shape;

  T get() { return shape; }
}

这是另一个示例,在这种情况下,您可以编写一个通用装饰器,它能够在不需要任何强制转换的情况下返回类型 T。这在许多将共同祖先作为子类型还不够的情况下很有用。

于 2013-03-21T14:24:22.203 回答
1

主要的兴趣是您可以在代码的不同部分将方法的使用限制为特定类型的形状。

在某些时候,您可能希望将其参数化为仅Rectangle在另一个地方绘制Circle,这将在编译时进行检查,即使在运行时,您将传递一些类型的东西Shape

于 2013-03-21T14:17:31.203 回答