2017-01-12 4 views
3

В Android Studio У меня есть следующее сообщение об ошибке:Java общие типы наследования ошибки

java: incompatible types: java.lang.Object cannot be converted to java.lang.String

Я думаю, b1 и b2 следует ведет себя то же самое, но они не являются.

Есть ли способ заставить их вести себя одинаково (без изменения их типа курса)?

Вот код набран:

public class Test 
{ 
    class A<T> 
    { 
     T t; 
     T getT() 
     { 
      return t; 
     } 
    } 
    class AS extends A<String> 
    { 

    } 
    class B<T> extends AS 
    { 

    } 

    B<Object> b1; 
    B b2; 

    public void test() 
    { 
     String t3 = b1.getT(); 
     String t4 = b2.getT(); 
    } 
} 
+0

Можете скопировать и вставить код, чтобы я мог взять образцы кода для моего ответа? –

+0

Я отредактировал свой ответ, поэтому код можно копировать. :) –

+0

Коррекция, может воспроизводиться с помощью 'javac', но не с' eclipsec'. Логика остается прежней; вы используете стертую версию 'B', вы используете стертую версию' A', поэтому он возвращает объект в соответствии с [JLS] (https://docs.oracle.com/javase/specs/jls/se7/html/jls -4.html # ПСБ-4.8). В конце концов, это обман http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it. –

ответ

1

Проблема заключается в том, что B является параметризованным типом, но b2 объявляется иметь сырыеB в качестве своего типа.

Вы демонстрируете с b1 что B 'параметр типа s отличный от A-й лет, несмотря на то, что они имеют такое же имя, так что параметр типа B не имеет ничего общего с типом возвращаемого getT() метода, унаследованного от A<String>. Однако, когда вы используете сырой тип, вы получаете полное стирание этого типа, в том числе его супертипов.

Поскольку параметр типа A 0 неограничен, его стирание производит тип Object, и поэтому это тип b2.getT(). Конечно, Object не может быть присвоен String.

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

  1. Не используйте необработанного типа для b2. Если вам не нужен его параметр типа, используйте B<?>. Или,

  2. Удалить параметр класса B. Он не используется ни для чего в вашем примере, так что это будет самая чистая вещь.Просто потому, что его суперкласс является общим, не означает, что должно быть B.

+0

Собственно, это не вызовет ошибку, которую описывает OP, хотя это может вызвать ошибку после того, как OP исправляет текущую ошибку. – PMARINA

+0

Я не следую за вами, @PMARINA. Вы не согласны с тем, что в коде OP возвращаемый тип 'b2.getT()' является 'Object'? Тогда вам будет сложно объяснить ошибку компилятора. Или вы не согласны с моим объяснением, почему это так? В этом случае, пожалуйста, поделитесь. Убедитесь, что вы можете объяснить, почему 'b1.getT()' возвращает 'String', хотя, когда' b1' имеет тип 'B '. –

+0

Я не согласен с вашим ответом, в котором говорится, что текущая ошибка вызвана параметрами. Проблема заключается в том, что вызов getT() должен возвращать объект типа T. Это не должно решаться, всегда имея ввод типа строки. Вместо этого OP должен добавить метод toString() и вызвать это, а не getT(). Ваше решение всегда использовать String является глупым, потому что OP не будет нуждаться в дополнительном классе для выполнения действий исключительно со строками и не будет называть его T(), если он/она не планировал использовать другие типы данных. – PMARINA

-1

Проблема здесь в том, что getT() возвращает объект. Что вам нужно сделать, это реализовать метод toString(), который дает значение T объекта через а String (или просто изменить типы для t3 и t4 к T поэтому заявление выходит T t3 = b1.getT(); и T t4 = b2.getT();).

Кроме того, вы должны сделать следующее вместо кода у вас есть для B.

B<T> b1; 
B<T> b2; 

Заметим, что вам нужно инициализировать B к чему-то, прежде чем вы можете позвонить b1.anyMethod() или иначе вы получите NullPointer Exception ,

+1

Я думаю, вы пропустили точку. Основной вопрос здесь: почему * 'getT()' возвращает 'Object' при вызове на' b2' (типа 'B'), даже если он возвращает' String', как ожидалось, при вызове на 'b1' (типа' B '). Предложение переопределить 'toString()' является * не-sequitur *; нет оснований думать, что это строковое представление объекта какого-либо другого типа, который нужен. –

0

Я думаю, что B без объекта шаблона является неполным классом, а не B<Object>. Вот почему, когда вы вызываете его getT(), вы на самом деле звоните A.getT().

Это почему в приведенном ниже коде String t3 = b2.getT(); не удается скомпилировать.

static class A<T> 
{ 
    T t; 
    T getT() 
    { 
     return t; 
    } 
} 

static class AS extends A<String> {} 

static class B<T> extends AS {} 

static class C extends B<Object> {} 

static A a; 
static B<Object> b1 = null; 
static B b2 = new B(); 
static C c = new C(); 

static void test() 
{ 
    Object tt = a.getT(); 
    String t2 = b1.getT(); 
    String t3 = b2.getT(); 
    String t4 = c.getT(); 
} 
Смежные вопросы