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?