Q:

¿Qué significa esa especie de parámetro <> al definir una clase?

He visto este tipo de definición de clase pero no se cual es su utilidad.
public class UnaClaseCualquiera<String> {
}

Quien dice <String> dice <integer> o incluso <T>.

A:

public class UnaClaseCualquiera <String> {
}

Los símbolos <> después del nombre de la clase representan en Java lo que se llama genéricos (generics).
Fueron introducidos en la versión 5 de Java en 2004 junto con otras muchas novedades y constituyen una de las mayores modificaciones de este lenguaje.
Los generics son importantes ya que permiten al compilador informar de muchos errores de compilación que hasta el momento solo se descubrirían en tiempo de ejecución, al mismo tiempo permiten eliminar los cast simplificando, reduciendo la repetición y aumentando la legibilidad en el código. Los errores por cast inválido son especialmente problemáticos de debuggear ya que el error se suele producir en un sitio alejado del de la causa.
Los generics permiten usar tipos para parametrizar las clases, interfaces y métodos al definirlas. Los beneficios son:

Comprobación de tipos más fuerte en tiempo de compilación.
Eliminación de casts aumentando la legibilidad del código.
Posibilidad de implementar algoritmos genéricos, con tipado seguro.

Un tipo usando generics tiene el siguiente aspecto, por ejemplo usando una clase Caja contenedor de una referencia a un tipo no determinado en la definición de la clase pero que lo será en su uso. Una clase genérica puede tener múltiples argumentos de tipos y los argumentos pueden ser a su vez tipos genéricos. Después del nombre de la clase se puede indicar la lista de parámetros de tipos con el formato <T1, T2, T3, …>.
public class Caja<T> {

  private T t;

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

public interface Par<K, V> {
  public K getKey();
  public V getValue();
}

public class ParOrdenado<K, V> implements Par<K, V> {

  private K key;
  private V value;

  public ParOrdenado(K key, V value) {
    this.key = key;
    this.value = value;
  }

  public K getKey() { return key; }
  public V getValue() { return value; }
}

Según la convención de nombres, los parámetros de tipo usados comúnmente son los siguientes:

E: elemento de una colección.
K: clave.
N: número.
T: tipo.
V: valor.
S, U, V etc: para segundos, terceros y cuartos tipos.

En el momento de la instanciación de un tipo genérico indicaremos el argumento para el tipo, en este caso Caja contendrá una referencia a un tipo Integer. Con Java 7 se puede usar el operador diamond y el compilador inferirá el tipo según su definición para mayor claridad en el código. Podemos usar cualquiera de esta dos maneras prefiriendo usar el operador diamond por ser más clara.
Caja<Integer> integerBox1 = new Caja<Integer>();
Caja<Integer> integerBox2 = new Caja<>();
ParOrdenado<String, Integer> p1 = new ParOrdenado <>("UnPar", 22);

Para mantener la compatibilidad con versiones anteriores a Java 5 los tipos genéricos que al usarse no indican argumentos de tipo se denominan raw. El compilador indicará una advertencia como un uso potencialmente peligroso ya que no podrá validar los tipos.
Caja rawCaja = new Caja();

Además de las clases los métodos también pueden tener su propia definición de tipos genéricos.
public static <K, V> boolean comparar(Par<K, V> p1, Par<K, V> p2) {
  return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());
}

La sintaxis completa de uso sería:
Par<Integer, String> p1 = new ParOrdenado <>(1, "apple");
Par<Integer, String> p2 = new ParOrdenado <>(2, "pear");
boolean igual = Util.<Integer, String>comparar(p1, p2);

Aunque puede abreviarse ya que el compilador puede inferir los tipos:
boolean igual = Util.comparar(p1, p2);

A veces necesitaremos limitar los tipos que pueden ser usados empleando lo que se denomina bounded type. Con  el tipo U debe extender la clase Number.
public class CajaBounds<T> {

  private T t;

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

  public T get() {
    return t;
  }

  public <U extends Number> void inspect(U u){
    System.out.println("T: " + t.getClass().getName());
    System.out.println("U: " + u.getClass().getName());
  }

  public static void main(String[] args) {
    Caja<Integer> integerCaja = new Caja<Integer>();
    integerCaja.set(new Integer(10));
    integerCaja.inspect("some text"); // error: this is still String!
  }
}

Una clase puede tener múltiples limitaciones, si una es una clase debe ser la primera y el resto de argumentos interfaces.
<T extends B1 & B2 & B3>

Class A { /* ... */ }
interface B { /* ... */ }
interface C { /* ... */ }

class D <T extends A & B & C> { /* ... */ }

En Java un tipo puede ser asignado a otro mientras el primero sea compatible con el segundo, es decir tengan una «relación es un». Una referencia de Object puede referenciar una instancia de Integer (un Integer es un Object).
Object object = new Object();
Integer integer = new Integer(10);
object = integer;

Sin embargo, en el caso de los generics, ¿una referencia de Caja puede aceptar una instancia Caja or Caja aun siendo Integer y Double subtipos de Number?. La respuesta es no, ya que Caja y Caja en Java no son subtipos de Caja. La jerarquía de tipos es la siguiente:
Los tipos genéricos pueden extenderse o implementarse y mientras no se cambie el tipo del argumento la «relación es un» se preserva. De modo que ArrayList es un subtipo de List que a su vez es un subtipo de Collection.
interface PayloadList<E,P> extends List<E> {
  void setPayload(int index, P val);
  ...
}

PayloadList<String,String>
PayloadList<String,Integer>
PayloadList<String,Exception>

En los generics un parámetro para un tipo ? se denomina wildcard siendo este un tipo desconocido. Son usados para reducir las restricciones de un tipo de modo que un método pueda funcionar con una lista de List, List y List. El término List es más restrictivo que List porque el primero solo acepta una lista de Number y el segundo una lista de Number o de sus subtipos. List es un upper bounded wildcard.
public static void process(List<? extends Number> list) { /* ... */ }

Se puede definir una lista de un tipo desconocido, List, en casos en los que:
La funcionalidad se puede implementar usando un tipo Object.
Cuando el código usa métodos que no dependen del tipo de parámetro. Por ejemplo, List.size o List.clear.
Digamos que queremos definir un método que inserte objetos Integer en un List. Para mayor flexibilidad queremos que ese método pueda trabajar con cualquier tipo de lista que permita contener Integer, ya sea List<Integer>, List<Number> y List<Object>. Lo podemos conseguir definiendo List<? super Integer> que se conoce como Lower Bounded Wildcard.
Las clases genéricas no tienen relación alguna aunque sus tipos los tengan, pero usando wildcads podemos crearlas.
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;

Uno de las mayores confusiones al usar generics es cuando usar upper bounded wildcards o cuando usar lower bounded wildcards. Podemos usar las siguientes reglas:
Una variable generic que se usa como fuente de datos (in), por ejemplo src en  copy(List src, List dest) se define usando upper bounded wildcard con la palabra clave extends. De modo que la lista del parámetro src pueda ser una lista de un tipo U o de un subtipo de U.
Un variable generic que se usa como destino de datos (out), por ejemplo dest en  copy(List src, List dest) se define usando lower bounded wildcard con la palabra clave super. De modo que la lista del parámetro dest pueda ser una lista de un tipo U o de un supertipo de U.
En caso de que la variable pueda ser usando mediante métodos definidos en la clase Object se recomienda usar un unbounded wildcard (?).
En caso de que la variable se necesite usar como fuente de datos y como destino (in y out) no usar wildcard.
Los generics son un mecanismo para proporcionar comprobaciones en tiempo de compilación, sin embargo, el compilador aplica type erasure que implica:
Reemplazar todos los tipos con sus bounds o por Object si son unbounded.
Insertar casts para preservar el tipado seguro.
Generar métodos puente para preservar el polimorfismo en generics en los que son extendidos.
Un tipo non reifiable son aquellos cuya información de tipo ha sido eliminada en tiempo de compilación por el type erasure, para la JVM no hay ninguna diferencia en tiempo de ejecución entre List y List. No se crean nuevas clases para los tipos parametrizados de modo que no hay ninguna penalización en tiempo de ejecución. Una clase genérica al compilarla se transforma aplicando type erasure:
// TypeErasure to Object
public class Node<T> {

  private T data;
  private Node<T> next;

  public Node(T data, Node<T> next) }
    this.data = data;
    this.next = next;
  }

  public T getData() { return data; }
  // ...
}

// Node type erased
public class Node {

  private Object data;
  private Node next;

  public Node(Object data, Node next) {
    this.data = data;
    this.next = next;
  }

  public Object getData() { return data; }
  // ...
}

// TypeErasure to Comparable
public class Node<T extends Comparable<T>> {

  private T data;
  private Node<T> next;

  public Node(T data, Node<T> next) {
    this.data = data;
    this.next = next;
  }

  public T getData() { return data; }
  // ...
}

// Node type erased
public class Node {

  private Comparable data;
  private Node next;

  public Node(Comparable data, Node next) {
    this.data = data;
    this.next = next;
  }

  public Comparable getData() { return data; }
  // ...
}

Los generics tiene algunas restricciones:

No se pueden instanciar tipos genéricos con tipos primitivos.
No se pueden crear instancias de los parámetros de tipo.
No se pueden declarar campos static cuyos tipos son parámetros de tipo.
No se pueden usar casts o instanceof con tipos parametrizados.
No se pueden crear arrays de tipos parametrizados.
No se pueden crear, capturar o lanzar tipos parametrizados que extiendan de Throwable.
No se puede sobrecargar un método que tengan la misma firma que otro después del type erasure.

Fuente: Documentación de Java sobre genéricos (en inglés)

