My Eclipse IDE does not compile any of your code examples as is. But they do compile when given additional type hints. In the second example, with or without the type parameter useless_t, the following line does not compile for me:
List<Duck> l = list();
But the following does compile for me:
List<Duck> l = this.<Sound, Quack, Duck> list();
With the useless_t factored out, the following compiles, too:
List<Duck> l = this.<Quack, Duck> list();
So it is basically a matter of the compiler not getting the type parameters right, and you need to give the types explicitly.
UPDATE : If you really came across a program where adding the useless_t made a difference, you are on unsafe terrain, and rely on unspecified compiler behaviour.
You ran into an issue where different compilers behave differently, namely Type Inference. The JLS is not entirely clear on where a compiler must infer types, and where it must refuse to infer, so there is wiggle room here. Different versions of the Eclipse compiler and different versions of javac differ in where they do infer types. For javac, this is true even when comparing different 1.5.0_x versions, and the Eclipse compiler usually can infer more than javac.
You should only rely on type inference where all common compilers succeed, and otherwise give type hints. Sometimes, that is as easy as introducing a temporary variable, but sometimes (as in your example) you must use the var.<Types>method() syntax.
Regarding the comment: what if i want method Duck.getSound() to return Quack, not Sound using generics?
Assume the Bird interface had the following method:
public interface Bird<T extends Sound> {
T getSound();
}
Then you could implement it like so:
private static class Duck implements Bird<Quack> {
public Quack getSound() { return new Quack(); }
}
This is one use case for generics - allow implementations to specify concrete types, so that even the superclass can use that type. (The Bird interface could have a setSound(T), or do other stuff with T, without knowing the concrete type of T.)
If a caller only knew that an instance was of type Bird<? extends Sound>, he would have to call getSound like so:
Sound birdSound = bird.getSound();
If the caller knew about Quack, he could perform an instanceof test. But if the caller knew that the bird was really a Bird<Quack>, or even that is was a Duck, then he can write this and it compiles as desired:
Quack birdSound = bird.getSound();
But beware: Generifying too many types used in the interface or superclass brings the risk of overcomplicating the system. As Slanec wrote, Rethink your real design to see whether it's really needed to have so many generics.
I once went too far, and ended up with a interface hierarchy and two implementation hierarchies, based on interfaces like this:
interface Tree<N extends Node<N>,
T extends Tree<N, T>> { ... }
interface SearchableTree<N extends SearchableNode<N>,
S extends Searcher<N>,
T extends SearchableTree<N, S, T>>
extends Tree<N, T> { ... }
I do not recommend to follow that example. ;-)