2013-03-21 112 views
3

假设下面的类定义:T类型参数

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

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

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

Java编译器取代了T,带形状:

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

我的问题是,如果我们直接定义// 3,那么我们仍然可以t通过ShapeCircleRectangle参考方法在// 3。那么为什么我们需要编写// 2类型参数为<T extends Shape>的泛型方法,它与// 3非常相似?

您可以参考该链接,以同样的例子:http://docs.oracle.com/javase/tutorial/java/generics/genMethods.html

+3

你很可能没有。这基本上是一个坏榜样。 – 2013-03-21 14:15:06

+0

你不需要做方法// 2。实际上,最好做方法// 3,因为继承的目的之一是传递许多继承对象的“形状”。所以在这种情况下// 3更有意义。 – 2013-03-21 14:16:36

回答

6

您可能需要也可能不需要它。你需要它,如果你的方法来处理类型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就足够了。

2

在这种特殊情况下,你并不需要一个通用的方法。

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

例如,您可能有一个接受并返回T元素集合的泛型方法。通过类型参数化它可以让你在多个集合类型上使用它。

通用方法有用的其他示例在此Java tutorial

1

主要的兴趣在于,您可以将代码的不同部分的方法用于特定类型的形状。

在某些时候,你可能要参数化只Rectangle并在另一个地方只Circle,这将在编译时检查得出,即使在运行时,你会通过类型Shape

2

的东西在你例如,// 3确实与// 2相同。但在其他usecases,泛型类型可能是有用的:

  • 你想从方法作为参数返回相同类型的值,

  • 你有2个或多个参数,并要设置限制他们必须是相同的类型

1

不同之处在于你正在使用的多态性的种类。

在您使用参数多态性而在第二个使用的是多态性的亚型的一般情况。其实你第一个案例使用这两种多态性。

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

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

你可以看到,在第一种情况下,没有一个类型参数,我不能管理形状的特定亚型的名单,我只能管理形状的eterogeneous列表,但我无法强制任何特定的一个。所以我没有任何编译时间,禁止我将TriangleRectangle添加到shapes

class ShapeDecorator { 
    private Shape shape; 

    .. 

    Shape get() { return shape; } 
} 

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

    T get() { return shape; } 
} 

下面是另一个例子,在这种情况下,你可以写一个通用的装饰,它能够无需任何演员返回一个类型T。这在许多将共同的祖先作为子类型是不够的情况下是有用的。

相关问题