2015-07-02 2 views
5

У меня есть класс с конструктором подписью следующим образом:Java Общих типов ошибок несовпадения

public class MyClass <U>{ 
    public <T> MyClass(Set<T> data, Function<T,U> func)... 
} 

Это нормально. Но я хочу перегрузить конструктор, в случае, если вы не предоставляете функцию func, она просто будет использовать (item)->{return item;}. Я написал еще один конструктор, который выглядит следующим образом:

public <T> MyClass(Set<T> data){ 
    this(
     data, 
     (item)->{return item;} 
    ); 
} 

Это вызывает ошибку несоответствия типов, так как функцию я обеспечиваю в качестве аргумента моего конструктора принимает значение типа T, и возвращает то же значение, которое должно быть U. Я не понимаю, почему система алгебраического типа не видит, что в этом случае U и T являются одинаковыми, и это нормально?

+0

Вам не нужно неуклюжий синтаксис, как '(п) -> {возвращение пункта;}', 'просто написать пункт -> пункт '. Или, ну, 'Function.identity()' ... – Holger

+0

Спасибо @Holger, я переключился на использование 'Function.identity()' –

ответ

7

Система должна предполагать, что T и U - два разных типа, поскольку вы дали им два разных имени. Но вы можете просто удалить дополнительный общий тип из вашего второго CTOR так:

public class MyClass <U>{ 
    public <T> MyClass(Set<T> data, Function<T,U> func) {...} 
    public MyClass(Set<U> data){ 
     this(
      data, 
      (item)->{return item;} 
     ); 
    } 
} 
+0

Ах да, я идиот. К сожалению. Я предположил, что несоответствие типа было между U и T, не понимая, что я фактически сделал два разных Ts в разных областях. Это очень понравилось, большое спасибо! :) –

3

Давайте попробуем создать экземпляр вашего класса, используя второй конструктор:

Set<Integer> ints = new HashSet<>(); 
MyClass<String> myobj = new <Integer> MyClass (ints); 

ваш первый конструктор будет ожидать Set<Integer> и Function<Integer,String>, но ваш второй конструктор попытается передать ему Function<Integer,Integer>. Вот почему ваш код не передает компиляцию.

Когда вы определяете общие классы и методы, они должны быть действительны для любой комбинации типов, которые могут заменить их параметры типа.

0

Поскольку вы объявили два разных типа T и U, компилятор разумно считает, что они разные. Если они одинаковы, не объявляйте T и использовать только U:

public MyClass(Set<U> data){ 
    this(
     data, 
     (item)->{return item;} 
    ); 
} 
Смежные вопросы