Объяснение пользовательских Generics - PullRequest
1 голос
/ 17 января 2011

Пожалуйста, объясните пользовательский 'T' в интерфейсе Java. Здесь используются дженерики и типа «Т», я полагаю. Тогда где же определен тип 'T'?

  public interface TemplateBuilder<T extends TemplateBuilder>  

Ответы [ 4 ]

8 голосов
/ 17 января 2011

T не фактический класс. Это определяется во время компиляции в зависимости от использования вашего класса TemplateBuilder. Просто подумайте об этом как о заполнителе для различных возможных типов, один из которых выбирается в зависимости от ваших обстоятельств.

Для более простого примера посмотрите на следующее (адаптировано из учебника Java):

Представьте, что вы хотите объявить класс Box, который может принимать определенный тип (объекта для хранения внутри блока), но вы хотите использовать его в различных обстоятельствах для хранения различных типов.

Таким образом, вместо того, чтобы фиксировать фактический тип, который может принимать Box, вы объявляете его следующим образом:

public class Box<T> {

    private T t; // T stands for "Type"          

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

Когда вы используете его, вы делаете что-то вроде:

Box<Integer> integerBox = new Box<Integer>();

Какой смысл вы можете спросить? Почему бы не заставить Box взять объект?

Фактически до Java 1.5 это было невозможно. Это было введено для обеспечения дополнительной безопасности типов в этих ситуациях и было принято в рамках коллекций.

Весь смысл в том, что без этого механизма, если вместо этого он использовал Object, вы не можете заставить конкретный экземпляр вашего Box содержать только целые числа. С другой стороны, если вы сделали так, чтобы в нем использовались только целые числа, вы не можете повторно использовать свой Box для String или другие объекты, и вам потребуется создать другой тип класса Box.

До Java 1.5 такие объекты, как ArrayList, принимали обычные объекты, однако во время выполнения часто возникали случаи нарушения безопасности типов, поскольку программа принимает список объектов Integer и по ошибке где-то вставляет строку. Дженерики (через эту магическую Т) заставляют типы, не ограничивая, какими они могут быть.

В вашем случае T extends TemplateBuilder делает еще один шаг и заявляет, что независимо от того, что это за T, это должен быть класс, расширяющий TemplateBuilder. Если бы этого не было, это был бы любой класс, расширяющий Object (универсальный базовый класс Java).

1 голос
/ 17 января 2011

Этот тип определяется при реализации интерфейса, т.е.

class StringBuilder implements TemplateBuilder<StringBuilder> {}

Кстати, см. Класс Enum (базовый класс всех перечислений).

1 голос
/ 17 января 2011

T - это любое Object, которое простирается от TemplateBuilder

T означает любой объект. например

List<T> list = new ArrayList<T>();

здесь T может быть Integer, String ...

и <T extends A> означает, что любой Object T простирается от A

0 голосов
/ 29 апреля 2017

Объяснение моих пользовательских обобщений

Backgorund:

  1. Пользовательские дженерики неизменно используются со структурами данных, например, при управлении (хранении / извлечении) списков "вещей"
  2. Вы не должны выполнять свою собственную проверку типов , чтобы код компилировался, поскольку пользовательские обобщенные элементы включают принципы полиморфизма.
  3. Однако, в отличие от «традиционных» ОО-принципов полиморфизма, класс может хранить список вещей, без , имеющих какие-либо отношения с «вещами», которые он хранение (Фундаментальный принцип ОО, где А - суперкласс класса В, не требуется)
  4. Вы не создаете отдельные подклассы для всех возможных классов «вещей», которые хотите хранить.

Пример 1

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

/**
 *
 * Class A is a Custom Generic class that can be 'typed'
 * to any kind of class using diamond 'T' syntax. 
 * 
 */

class A<T> 
{   
  // The instance variable of the object type 'T' known at run time
  T theI;

  // The constructor passing the object type 'T' 
  A(T anI)
  {
    this.theI = anI;
  }

  // Method to return the object 'T'
  T getT()
  {
    return theI;
  }
}  

Ниже приведен класс B, который не связан с классом A, т. Е. B не расширяет A:

/**
*
* Simple class which overrides the toString()
* method from Object's class toString() method 
* 
*/
class B 
{

  @Override
  public String toString()
  {
    return "B Object";
  }

  public static void main(String[] args)
  {
    A<B> a = new A<>(new B());

    System.out.println(a.getT());        
  }
}

В методе Main класса B выше:

a.getT () возвращает объект 'T', который в этом примере имеет тип 'B' (это пример полиморфизма).

a.getT () возвращает объект 'T', метод toString () экземпляра объекта C вызывается НЕЗАКОННО, так как он переопределяет метод toString () объекта и печатает «B Object».

Интересный аспект, который следует отметить относительно пользовательских обобщений и полиморфизма:

В контексте пользовательских обобщений нет ограничений для отношения между классами для выполнения полиморфизма

например. Класс B не имеет отношения к A выше, т.е. класс B НЕ расширяется A.

В "1055 * традиционных " принципах объектно-ориентированного полиморфизма неизменно существует ограничение требования для классов, которые должны быть связаны каким-либо образом. Однако это не требуется в пользовательских шаблонах.

Пример 2

public interface TemplateBuilder<T extends TemplateBuilder>

Вышеуказанное означает, что интерфейс TemplateBuilder может быть напечатан для любого класса, который расширяет TemplateBuilder.

Давайте предположим, что SomeClass расширяет TemplateBuilder, тогда все в порядке:

TemplateBuilder<SomeClass> tbRef = ... 
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */ 

или

TemplateBuilder<SomeClass> tbRef = .... /*  Referencing a concrete class 
that implements TemplateBuilder */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...