2015-03-04 3 views
1

У меня есть 2 конструктора для класса. Параметризованный конструктор и не параметризованный. Проблема в том, что я не могу вызвать параметризованный один из другого с помощью этого (...). Однако это работает, когда я пытаюсь тот же вызов из другого (скажем, основной метод)Generics - вызов параметризованного конструктора из другого с помощью этого

Вот код

package com.test.generics; 

    public class Key<T> { 

     private T t; 

     public Key(T t){ 
      this.t = t; 
     } 

     public T getKey(){ 
      return t; 
     } 
    } 

А потом

package com.test.generics; 

    public class KeyValueObject<T> { 
     private String value; 
     private Key<T> key; 

     public KeyValueObject(Key<T> k){ 
      key = k; 
      value = "-1"; 
     } 

     public KeyValueObject(String keyString){ 
      this(new Key<String>(keyString)); //Here is the problem, this says the Constructor KeyValueObject<T>(Key<String> k) is undefined 
     } 
     public static void main(String[] args) { 
      Key<String> keyStr = new Key<String>("x"); 
      KeyValueObject<String> keyValObj = new KeyValueObject<String>(keyStr); //I try the same thing from main method and it works. 
     } 
    } 

Почему говорят, что компилятор «Конструктор KeyValueObject (Ключ k) не определен ». У меня есть определенный конструктор KeyValueObject (Key k).

Также в основном методе, я в значительной степени делаю то же самое. Если работал перегруженный конструктор, я мог бы использовать new KeyValueObject("x")

+2

положить 'T' вместо' Строка "в вашем втором конструкторе' KeyValueObject'. В качестве альтернативы вы можете добавить фабричный метод: public public KeyValueObject make (String value) {return new KeyValueObject (значение); } ' –

ответ

1

Ошибка компилятора оправдана, поскольку код не является безопасным для типа. Чтобы понять, почему, допустим, Вы писали:

KeyValueObject<Integer> kv = new KeyValueObject("not an Integer"); 

выше будет производить попытку вызова KeyValueObject<Integer>(Key<Integer>) с Key<String> аргументом, который, очевидно, не может быть действительным.

+0

Спасибо. Это помогает. – ramp

3

Заявленная типа для KeyValueObject<T> атрибута:

private Key<T> key; 

отличается от типа аргумента в вашем вызове конструктора:

public KeyValueObject(String keyString){ 
    this(new Key<String>(keyString)); 
} 

универсальный тип аргумента конструктора должно совпадать с типом атрибута:

public KeyValueObject(T t){ 
    this(new Key<T>(t)); 
} 
+0

На самом деле это та часть, которую я не получаю. Является ли ключ , я могу заменить T на любой тип? Я имею в виду просто взглянуть на класс Key сам по себе. Он принимает тип param T и из основного метода, я мог бы сделать Key k = new Key <> ("str"); – ramp

+0

Спасибо. Я прочитал ответ Рожерио и теперь понимаю, что вы говорите. Это имеет смысл. Я пометил другой ответ как правильный и сохранил ваш. – ramp

1

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

public class Program { 
    public static void main(String[] args) { 
     KeyValueObject<String> $0 = new KeyValueObject<>(new Key<>("x")); //old school 
     KeyValueObject<String> $1 = new KeyValueObject<>("x"); //boxing constructor 
     KeyValueObject<String> $2 = KeyValueObject.make("x"); //factory method 
    } 
} 

class Key<T> { 
    T key; 

    public Key(T key){ 
     this.key = key; 
    } 

    public T getKey(){ 
     return key; 
    } 
} 

class KeyValueObject<T> { 
    //Solution 2: Create a factory method to handle the case `T` == `String` 
    static KeyValueObject<String> make(String value) { 
     return new KeyValueObject<>(value); 
    } 

    String value; 
    Key<T> key; 

    KeyValueObject(Key<T> key){ 
     this.key = key; 
     this.value = "-1"; 
    } 

    //Solution 1: Change `String` to `T` 
    KeyValueObject(T key){ 
     this(new Key<>(key)); 
    } 
} 
+0

Спасибо. Это действительно помогает. Я не могу использовать фабричный метод, потому что я переношу существующий код на использование дженериков.Я пойду с решением 1. Я правильно ответил на ответ Роджерио, потому что я лучше всего понял его пример того, что было не так с моим кодом. – ramp

1

Тип Key<String> не обязательно совпадает с Key<T> поэтому ошибка является допустимым. (Небезопасный напечатанный можно было бы мысль)

рассмотреть возможность реализации фабричного метода, как это:

public static KeyValueObject<String> createKeyValueObject(final String keyString) { 
    return new KeyValueObject<String>(new Key<String>(keyString)); 
} 

или для более эффективного использования общих возможностей:

public KeyValueObject(T k) { 
    this(new Key<T>(k)); 
} 
+0

Спасибо за помощь. – ramp

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