2013-10-14 2 views
1

я наткнулся на Java код, подобный следующему:Java общий интерфейс с ограничением по типу против C# дженериков

public interface ITest<T1 extends IOne,T2 extends ITwo> { 
    boolean handle(T1 value1); 
    boolean handle(T2 value2); 
} 
public interface IOne {} 
public interface ITwo {} 

а затем реализация ITEST:

public class Test implements ITest { 
@Override 
public boolean handle(IOne value1) { 
    return false; 
} 

@Override 
public boolean handle(ITwo value2) { 
    return false; 
    } 
} 

Обратите внимание на отсутствие декларации типа в «Тест реализует ITest». Исходя из мира C#, это удивило меня, поскольку вы не можете сделать это в C#. Вы должны написать что-то вроде:

public class Test : ITest<IOne, ITwo> 

Я понимаю, что Java дженериков очень отличается от C# дженериков, но я хотел бы, чтобы лучше понять, что происходит в коде Java, что позволяет выше код для компиляции? Является ли это вывод типа компилятором? Является ли исходный тип IOne и ITwo для класса Test? http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

Спасибо.

+1

Это должно дать вам предупреждение о компиляторе на Java. – SLaks

+0

@Servy: Это незаконно на Java. (из-за стирания типа) – SLaks

+2

'Я понимаю, что генерические приемы Java сильно отличаются от C# generics' - Правильно. java - смешная шутка, а C# - серьезный язык программирования. java generics являются уродливыми, смешными и бесполезными, потому что фактическая информация о типе «стирается» во время компиляции, что просто странно. В то время как C# имеет истинную поддержку дженериков, а дженерики скомпилированы в информацию о типах данных, хранящихся в двоичных файлах, на всех этапах. –

ответ

1

Когда Java компилирует

T1 extends IOne

он заменяет все экземпляры T1 с Ione

так

public boolean handle(T1 value1) { 
    return false; 
} 

становится

public boolean handle(IOne value1) { 
    return false; 
} 

поэтому фактический интерфейс ITEST является

public interface ITest { 
    boolean handle(IOne value1); 
    boolean handle(ITwo value2); 
} 

Он может сделать это, потому что экземпляр T1 всегда будет иметь возможность быть отнесены к Ионе и экземпляр T2 всегда будет иметь возможность быть назначены ITWO.

При компиляции Test ищет методы, которые соответствуют конкретным методам в интерфейсе и не жалуются, потому что он находит методы, которые удовлетворяют тем, что он ищет.

+1

Расширение ответа после дальнейшего чтения. Как вы сказали, все экземпляры T1 заменены на IOne. Тип Eraser делает это « Замените все параметры типа в родовых типах своими границами или объектом, если параметры типа неограничены». Http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html. Поскольку тип T1 связан с IOne, все экземпляры T1 заменяются на IOne, а не на Object. Это тип Raw (http://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html), и он вызывает предупреждение о компиляторе, как упоминалось в SlakS. – Domc

+0

Предупреждения компилятора могут быть специфичными для компилятора. Ни javac, ни intellij не генерируют предупреждение. – BevynQ

+0

Чтобы добавить к этому, стирание означает, что у вас не может быть одного метода, который принимает «Список » и определяет, что 'T' находится во время выполнения через отражение. – Basic

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