sirve settitle que para name how java generics syntax static factory

settitle - Genéricos de Java y métodos de fábrica estáticos-Sintaxis



set name to jframe (5)

Esta es la única forma de parametrizar un método estático, ya que la T original en la declaración del nodo está vinculada a los campos y métodos de instancia del nodo. Para que pudieras escribir:

public static <T1> Node<T1> newNode(){ return new Node<T1>(); }

La T original está vinculada a una instancia de la clase Node y no se puede hacer referencia en un contexto estático. Esto daría lugar a un error de compilación:

// ERROR public static Node<T> newNode(){ return new Node<T>(); }

Esto es lo que tengo:

public class Node<T> { // instance variables private Node<T> next; private T data; // construct with data private Node(T data){ next = null; this.data = data; } // construct without data private Node(){ next = null; this.data = null; } // static factory method public static <T> Node<T> newNodeWithData(T data){ return new Node<T>(data); } // static factory method public static <T> Node<T> newNode(){ return new Node<T>(); } ... }

Mi pregunta realmente es solo acerca de la sintaxis de los genéricos junto con la de un método de fábrica estático. Realmente no entiendo por qué colocamos la <T> antes del tipo de retorno en la declaración de método. ¿Es algo así como encasillado? Cualquier ayuda sería muy apreciada!


La <T> es solo la señal de que este método utiliza T como variable de tipo. Sin él, el compilador pensaría que T es una class , interface o enum que se declara en algún lugar y genera un error. No es la misma T que se usa en tu primera línea. Puede reemplazar la T en este método con cualquier otra letra, tal vez eso ayude a comprender.


La razón por la que debe decorar el método estático con tal azúcar es porque, como método estático, no hereda la T de la declaración de la clase.

Podrías hacer:

// static factory methods public static <Q> Node<Q> newNode(){ return new Node<Q>(); } public static Node<String> newStringNode(String s){ return new Node<String>(s); }

Una narrativa simple a la declaración puede ayudar:

// This static method would have a <T> parameter to the class if it was not static public static <T> // It returns an object of type `Node` with generic parameter T Node<T> newNode(){ // And here it is doing it''s business. return new Node<T>(); }


Lo que estás preguntando es sobre tipo inferrence .

Como es un método estático, tiene que inferir el tipo Genérico de algún lugar; No tienes una instancia de la clase. Eso es lo que significa <T> .

En el caso de su método que no toma argumentos, en realidad lo está inferiendo del objetivo de la tarea. Por ejemplo, digamos que su método se veía así:

public static <T> List<T> getNewList() { return new ArrayList<T>(); }

Cuando se usa este método, T se infiere del objetivo (en este caso, String ):

List<String> myList = MyClass.getNewList();

En su otro método estático donde tiene un argumento genérico, se está deduciendo T del tipo que se pasa:

public static <T> List<T> getNewListWithElement(T element) { List<T> list = new ArrayList<T>(); list.add(element); return list; }

Aquí, si intentaste hacer:

List<String> myList = MyClass.getNewListWithElement(new Integer(4));

Le diría que su tipo de destino era incorrecto y que necesitaba una List<Integer>

Específicamente esto se trata en las secciones 15.12.2.7 y 15.12.2.8 del JLS.


T inferido de parámetro

public static <T> List<T> getNewListWithElement(T element)

¿Cómo puede el compilador hacer la diferencia entre T como clase y T como argumento genérico? La solución que se debe utilizar para especificar el elemento T es un genérico y no una clase / interfaz.

T inferido de uso

public static <T1> Node<T1> newNode(){ return new Node<T1>(); }

¿Quién será T1 dentro del cuerpo del método si no se realizara una declaración?