2013-05-20 2 views
5

Я пытаюсь понять общие методы в Java. Учитывая следующий код:Понимание общих методов Java

public class GenericTest { 

    interface Shape { 
     public long area(); 
    } 

    public static class Triangle implements Shape 
    { 
     private long base, height; 
     public long area() { return (base * height)/2; } 
    } 

    public static class Rectangle implements Shape 
    { 
     private long width, height; 
     public long area() { return width * height; } 
    } 

    public <T extends Shape> long area1(T shape) 
    { 
     return shape.area(); 
    } 

    public long area2(Shape shape) 
    { 
     return shape.area(); 
    } 

} 

Я не могу увидеть/понять, почему я должен использовать/реализовать Area1 вместо Area2 (или наоборот). Я что-то упускаю? Разве оба метода не делают то же самое?

Он оставил меня немного смущен относительно дженериков в Java

+1

Нет смысла использовать дженерики в этом случае. Случаи, в которых он имеет смысл, имеют смысл, когда вы не знаете, какие типы вы должны ** хранить **. –

+1

В этом случае, как @LukasKnuth сказал, что вам не нужно создавать общую версию области area2(), приемлемо; Однако текущая документация оракула показывает отличные примеры для дженериков. Примеры шаблонов подстановочных знаков также могут помочь в выяснении путаницы. Посмотрите на http://docs.oracle.com/javase/tutorial/extra/generics/methods.html –

+0

Я рассматривал дженерики как приблизительный эквивалент C++ шаблоны. Ключевая вещь, которую вы указали здесь, которая отсутствует в других ответах (и, вполне возможно, то, что мне не хватает, является понятием, что они используются », когда вы не знаете, какой тип ** хранит **.» Что именно что я искал в ответ :-) – Xaq

ответ

4

Там нет никаких оснований для создания метода area1. Предпочтительным является способ area2. Дженерики должны использоваться, когда есть связь с определенным, но неизвестным типом. Здесь нет ничего особенного в параметре shape. Интерфейс Shape уже позволяет использовать метод area, поэтому нам не важно, какая конкретная реализация Shape передается как shape. Поэтому дженерики здесь не нужны.

Использование

public long area2(Shape shape) 
13

В вашем примере, так как параметр T типа не используется в каких-либо возвращаемых значений, нет никакой разницы.

Однако, представьте, что вы имели следующие методы:

public <T extends Shape> T movedShape1(T shape) { 
    return shape.move(); 
} 

public Shape movedShape2(Shape shape) { 
    return shape.move(); 
} 

Здесь вы можете увидеть явное преимущество в использовании movedShape1(). Вы получаете более конкретный тип для возвращаемого значения, не теряя при этом никакой безопасности.

+0

Разве это не то же самое? Я не вижу дополнительной безопасности типа, они оба возвращают форму, не так ли? – Xaq

+2

@Xaq: Если у вас есть класс 'Circle реализует Shape', то вызов' moveShape1() 'с параметром' Circle' будет возвращать 'Circle', а не' Shape'. Вызов 'moveShape2()' с тем же параметром 'Circle' приведет к' Shape'. – Keppil

+0

@ Xaq, Keppil прав, и это очень полезно, когда вы вызываете метод, подобный этому. – dantuch

0

I Этот случай - Shape не является (абстрактным) классом, а интерфейсом, поэтому он должен быть реализован (расширен в форме мышления), я бы сказал, что они делают exaccty одинаково, и добавление дженериков есть только затенение того, что действительно происходит

Смежные вопросы