2013-04-05 2 views
0

В следующем примере кода есть ли способ избежать уродливых аннотаций SuppressWarnings?Java generics: захватить общий тип при копировании экземпляров подклассов

Кодовые испытания, если параметр т является экземпляром A и возвращает другой экземпляр А если да. Это удовлетворяет общему договору createCopy(), чтобы вернуть объект того же типа, что и его параметр, поэтому это безопасная операция. То же самое касается теста для B.

Я знаю о Wildcard Capture and Helper Methods, но я не уверен, что и как это помогает в этой ситуации, хотя проблема, похоже, очень похожа.

abstract class Base { 
    public static <T extends Base> T createCopy(T t) { 
     if (t instanceof A) { 
      @SuppressWarnings("unchecked") 
      T copy = (T) new A((A) t); 
      return copy; 
     } 

     if (t instanceof B) { 
      @SuppressWarnings("unchecked") 
      T copy = (T) new B((B) t); 
      return copy; 
     } 

     throw new IllegalStateException(); 
    } 
} 

class A extends Base { 
    public A() { } 
    public A(A a) { } 
} 

class B extends Base { 
    public B() { } 
    public B(B b) { } 
} 
+1

Если вы считаете аннотации «уродливыми», просто удалите их. они являются необязательными. –

+0

Затем я получаю предупреждение о безопасности типа. Я хочу знать, есть ли способ избежать этого предупреждения, поскольку код _is_ type-safe. Если бы я мог сообщить компилятору. – devconsole

+0

, которую вы предоставили компилятору, используя аннотацию. –

ответ

1

Вы можете передать класс методу, но это все равно некрасиво:

abstract class Base { 
    public static <T extends Base> T createCopy(final T t, 
      final Class<T> klass) { 
     if (t instanceof A) { 
      final T copy = klass.cast(new A((A) t)); 
      return copy; 
     } 

     if (t instanceof B) { 
      final T copy = klass.cast(new B((B) t)); 
      return copy; 
     } 

     throw new IllegalStateException(); 
    } 
} 

class A extends Base { 
    public A() { 
    } 

    public A(final A a) { 
    } 
} 

class B extends Base { 
    public B() { 
    } 

    public B(final B b) { 
    } 
} 

Calling t.getClass() не работает. Причина в том, что T может быть подтипом A или B (поэтому код не является действительно безопасным для типов).

EDIT: Почему ваш код не является действительно типобезопасным: представьте себе класс, который расширяет AAA. Если вы вызовете свой метод с экземпляром этого класса, он создаст объект типа A и попытается передать его AA.

+0

Интересный ответ, но почему, по-вашему, мой код не очень безопасен? Он возвращает A для A и a B для B, не так ли? – devconsole

+0

@devconsole, да, но это не удастся для подтипов A или B (см. Мое редактирование) – WilQu

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