By convention, T is used to represent a type Parameter, or type parameter, used in declaring a generic class.
As already mentioned in Jean’s reply, there is a convention for more common cases, although you can use any letter in practice.
A classic example is the class statement List, which represents a list of elements. Therefore we have:
public interface List<E> extends Collection<E> { ... }
When using the list, we can then define the type E of the list, thus:
List<String> nomes = new ArrayList<>();
And now the compiler will let you know if we try to put anything other than a String on the list.
Only sometimes we want to explicitly leave a list without a defined type. This could be done only with List, but in that case the compiler will think you forgot to declare the type.
For that we use the wildcard ?, as in the example:
int contar(List<?> qualquerTipo) {
return qualquerTipo.size();
}
Note that I don’t need to know the type to count the list elements, so it’s a perfectly valid use.
There are other applications for this, but it is usually a type of generic meta-programming used in frameworks or utility routines where the actual type doesn’t matter.
This should not be used often in the day-to-day implementations of systems we do, as it is far more insecure.