2013-03-21 117 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。這在許多將共同的祖先作爲子類型是不夠的情況下是有用的。

相關問題