El mejor ejemplo que se me ocurre para ilustrar la gran utilidad que tienen las interfaces en java es la interfaz Comparable.
Esta interfaz solo tiene un metodo que se llama compareTo. Por otro lado, cuando tu haces una lista de objetos (Por ejemplo, List<Integer> lista = new ArrayList<>()) y la llenas, puedes usar un metodo estatico de la clase Collections que se llama sort (Se utiliza asi: Collections.sort(lista); y cuando imprimes los elementos de la lista veras que estan ordenados). Esto lo que hace es ordenar la lista de menor a mayor, pero... ¿Como sabe ese metodo cuando un objeto es mayor que otro? Porque del mismo modo que he dicho List<Integer> lista = new ArrayList<>() (En cuyo caso solo habria que restar los 2 Integers) tambien podria haber dicho List<String> lista = new ArrayList<>()(En cuyo caso te lño ordenaria alfabeticamente) o List<CualquierClase> lista = new ArrayList<>().
Bueno pues lo que hace el metodo sort es utilizar, de la clase que va entre signo de mayor y menor, el metodo compareTo para saber si es mayor o menor que otro. Sin embargo yo podria haber hecho la clase CualquierClase sin sobreescribir el compareTo y sin implementar Comparable. Para eso no hace falta implementar Comparable, ya que podria crear un metodo compareTo directamente, pero tambien podria NO haberlo hecho. Entonces, ¿Como sabe el metodo sort si una clase tiene dentro un metodo que se llama compareTo de forma segura? Por las interfaces.
Lo que realmente hace es comprobar si esa clase implementa Comparable(lo que garantiza que tenga un compareTo), y entonces usa compareTo para saber si uno es mayor o menor que otro.
PD: Para comprobar que una clase implementa Comparable simplemente intenta darle a una variable declarada del tipo de la Interface un objeto de la lista. Si da error no implementa. Un ejemplo:
class ClaseQueImplementaInterface implements InterfaceCualquiera{
}
class ClaseQueNoImplementa{
}
public void funcionQueHaceAlgo(InterfaceCualquiera i){
//codigo
}
ClaseQueImplementaInterface obj = new ClaseQueImplementaInterface();
funcionQueHaceAlgo(obj)//Esto no da error de compilación
ClaseQueNoImplementa obj2 = new ClaseQueNoImplementa();
funcionQueHaceAlgo(obj2)//Esto, sin embargo, si da error de compilación
//Tambien se pueden crear objetos de la siguiente forma:
InterfaceCualquiera obj3 = new ClaseQueImplementaInterface();
//Esto provoca que, si la clase tiene metodos que no estan declarados en la interface, no se puedan usar
Cuando estudiando por mi cuenta me topé con las iterfaces, me encontré con que tenía la misma duda que tú, asi que te comprendo perfectamente. Como habrás podido notar hay muchas cosas raras en java que se ven un poco innecesarias (Por ejemplo, para declarar e implementar un constructor éste debe tener el mismo nombrte que la clase, lo que suena un poco redundante porque ya se sabe, al estar dentro de esa clase, que el constructor es de esa clase) pero al final lo agradeceras que sea asi porque el codigo queda mucho mas claro y es mas facil organizarse, aunque parezca una tonteria.