Java-дженерики T vs Object


127

Мені було цікаво, в чому різниця між наступними двома заявами методу:

public Object doSomething(Object obj) {....}

public <T> T doSomething(T t) {....}

Чи є щось, що ви можете / зробили б з одним, а не з іншим? Я не міг знайти це питання в іншому місці на цьому веб-сайті.

Відповіді:


112

Ізольована від контексту - різниці немає. І на обидва, 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під час виконання.

14

Різниця тут полягає в тому, що в першому ми вказуємо, що абонент повинен передати об'єкт Object (будь-якого класу), і він отримає ще один Об'єкт (будь-який клас, не обов'язково того ж типу).

По-друге, тип, що повертається, буде тим самим типом, що і той, що заданий, коли клас був визначений.

Example ex = new Example<Integer>();

Тут ми визначаємо, який тип буде T, що дозволяє нам застосувати більше обмежень для класу чи методу. Наприклад, ми можемо створити екземпляр a LinkedList<Integer>або LinkedList<Example>і знаємо, що коли викличемо один із цих методів, ми повернемо екземпляр Integer або Example.

Основна мета тут полягає в тому, щоб викличний код міг визначати, яким типом об'єктів буде працювати клас, замість того щоб покладатися на кастинг типів для його виконання.

Дивіться Java Generics * від Oracle.

* Оновлене посилання.


13

Різниця полягає в тому, що із загальними методами мені не потрібно робити передавання, і я отримую помилку компіляції, коли я роблю неправильно:

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;
    }
}

просто хотілося б згадати, що вам більше не доведеться кидати об’єкти, як на Android 6.
Джон Лорд

2

Не потрібно робити додатковий кастинг класу. У першому випадку ви завжди отримаєте об'єкт класу java.lang.Object, який вам потрібно буде віддати до свого класу. У другому випадку T буде замінено класом, визначеним у загальній підписі, і ніяке введення класу не потрібно.


2

Під час виконання нічого. Але під час компіляції другий зробить перевірку типу, щоб переконатися, що тип параметра та тип повернутого значення відповідають (або є підтипами), з яким типом T вирішено (перший приклад також робить перевірку типу, але кожен об'єкт є підтип Об'єкта, тому кожен тип буде прийнятий).


2

Т - це родовий тип. Це означає, що він може бути заміщений будь-яким кваліфікованим об'єктом під час виконання. Ви можете застосувати такий спосіб наступним чином:

String response = doSomething("hello world");

АБО

MyObject response = doSomething(new MyObject());

АБО

Integer response = doSomething(31);

Як бачите, тут є поліморфізм.

Але якщо оголошено повернути Object, ви не можете цього зробити, якщо не введете кадри.


Чи можемо ми сказати, що з <T>автобоксингом немає?
SMUsamaShah

0

у першому випадку він приймає параметр будь-якого типу egstring та повертає foo типу. У другому випадку він бере параметр типу foo і повертає об'єкт типу foo.


0

Є кілька причин, з яких ви можете враховувати «Загальна версія над об’єктом» на Java:

  1. Generics є гнучким та безпечним. У той же час, робота з об'єктом, який вимагає кастингу типу, є схильною до помилок
  2. Кастинг типів у Java є повільним: [1]: https://www.infoworld.com/article/2076555/java-performance-programming--part-2--the-cost-of-casting.html
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.