Відповіді:
Ізольована від контексту - різниці немає. І на обидва, t
і obj
ви можете посилатися лише на методи Object
.
Але з контекстом - якщо у вас є загальний клас:
MyClass<Foo> my = new MyClass<Foo>();
Foo foo = new Foo();
Тоді:
Foo newFoo = my.doSomething(foo);
Той самий код з об'єктом
Foo newFoo = (Foo) my.doSomething(foo);
Дві переваги:
Object
версія, ви не будете впевнені, що метод завжди повертається Foo
. Якщо він повернеться Bar
, у вас буде ClassCastException
під час виконання.Різниця тут полягає в тому, що в першому ми вказуємо, що абонент повинен передати об'єкт Object (будь-якого класу), і він отримає ще один Об'єкт (будь-який клас, не обов'язково того ж типу).
По-друге, тип, що повертається, буде тим самим типом, що і той, що заданий, коли клас був визначений.
Example ex = new Example<Integer>();
Тут ми визначаємо, який тип буде T, що дозволяє нам застосувати більше обмежень для класу чи методу. Наприклад, ми можемо створити екземпляр a LinkedList<Integer>
або LinkedList<Example>
і знаємо, що коли викличемо один із цих методів, ми повернемо екземпляр Integer або Example.
Основна мета тут полягає в тому, щоб викличний код міг визначати, яким типом об'єктів буде працювати клас, замість того щоб покладатися на кастинг типів для його виконання.
Дивіться Java Generics * від Oracle.
* Оновлене посилання.
Різниця полягає в тому, що із загальними методами мені не потрібно робити передавання, і я отримую помилку компіляції, коли я роблю неправильно:
public class App {
public static void main(String[] args) {
String s = process("vv");
String b = process(new Object()); // Compilation error
}
public static <T> T process(T val) {
return val;
}
}
Використовуючи об'єкт, мені завжди потрібно подавати, і я не отримую помилок, коли я роблю неправильно:
public class App {
public static void main(String[] args) {
String s = (String)process("vv");
String b = (String)process(new Object());
}
public static Object process(Object val) {
return val;
}
}
Не потрібно робити додатковий кастинг класу. У першому випадку ви завжди отримаєте об'єкт класу java.lang.Object, який вам потрібно буде віддати до свого класу. У другому випадку T буде замінено класом, визначеним у загальній підписі, і ніяке введення класу не потрібно.
Під час виконання нічого. Але під час компіляції другий зробить перевірку типу, щоб переконатися, що тип параметра та тип повернутого значення відповідають (або є підтипами), з яким типом T вирішено (перший приклад також робить перевірку типу, але кожен об'єкт є підтип Об'єкта, тому кожен тип буде прийнятий).
Т - це родовий тип. Це означає, що він може бути заміщений будь-яким кваліфікованим об'єктом під час виконання. Ви можете застосувати такий спосіб наступним чином:
String response = doSomething("hello world");
АБО
MyObject response = doSomething(new MyObject());
АБО
Integer response = doSomething(31);
Як бачите, тут є поліморфізм.
Але якщо оголошено повернути Object, ви не можете цього зробити, якщо не введете кадри.
<T>
автобоксингом немає?
у першому випадку він приймає параметр будь-якого типу egstring та повертає foo типу. У другому випадку він бере параметр типу foo і повертає об'єкт типу foo.
Є кілька причин, з яких ви можете враховувати «Загальна версія над об’єктом» на Java: