Esa E es lo que se llama un "tipo genérico", una especie de comodín para cuando no se sabe que tipo se va a utilizar.
Es decir, cuando declaramos un método en una clase, hay que indicar que tipo de dato va a retornar: un Integer, un String, un Persona, un Alumno....
Pero, si lo que estamos creando es una clase pensada para trabajar con CUALQUIER tipo de clase existente y por existir...., ¿cómo vamos a indicar lo que sus métodos retornan si hay, literalmente, infinitas posibilidades?
Eso es lo que pasa con las clases de las Collections de Java. Las List, las Map, las Set...., son interfaces/clases pensadas para coleccionar objetos de cualquier otra clase.
Así que al escribir estas clases, para indicar los tipos de retorno se usa un "tipo genérico", que en si mismo no es nada.
El código del método pop() de la clase Stack, es este:
public synchronized E pop()
{
if (elementCount == 0)
throw new EmptyStackException();
modCount++;
E obj = elementData[--elementCount];
// Set topmost element to null to assist the gc in cleanup.
elementData[elementCount] = null;
return obj;
}
Con lo que remarco en azul, vemos que se retorna un objeto de tipo E.
¿Qué es tipo E? Pues un genérico.
En realidad
no es nada, es una forma de decir que se va a retornar "algo", pero no sabemos que será, porque depende del tipo que escoja el programador cuando declare su propio Stack.
Así, cuando yo quiera usar un Stack y lo declare así:
Stack<String> miPila = new Stack<String>();
El método pop() retornará objetos String.
Y si lo declaro así:
Stack<Integer> miPila = new Stack<Integer>();
Pues ahora pop() retornará Integer.
Para eso se usan los genéricos, para hacer que una clase pueda adaptarse a trabajar con objetos de cualquier otra clase.
Por eso el tipo E no es un tipo real, no existe la clase E. Es solo para decirle a Java que ahí puede ir cualquier tipo de clase, no una en concreto.
En ese caso se usa la E, porque es la primera letra de "Element" y suele usarse en las Collections de Java.
Pero se pueden usar otras letras, de hecho, la que más verás frecuentemente es la T de "Type".
Pero da lo mismo usar una que otra, en todos los casos la utilidad es indicar que el código ha de prepararse para usar cualquier tipo de clase.
Hay unas convenciones para elegir letras que describan lo mejor posible la naturaleza de los elementos que, previsiblemente (ya que en realidad puede ser cualquier cosa), se usará en la clase que estemos desarrollando con "tipos genéricos"
E – Element (usado bastante por Java Collections Framework)
K – Key (Llave, usado en Map)
N – Number (para números)
T – Type (Representa un tipo, es decir, una clase)
V – Value (representa el valor, también se usa en mapas)
S,U, etc. – usado para representar otros tipos.