I have a doubt with the following code snippet (TIJ by Bruce Eckel)
Why is it that the second call to writeExact() in the static f1 method marked as an error? I have tried this program out and it is be working fine.
As far as I know, the compiler should be able to figure out the type of parameter from the call 'writeExact(fruit, new Apple())' as Fruit and hence work properly.
Following is the explanation given, "The writeExact() method uses an exact parameter type (no wildcards). In f1() you cn see that this works fine - as long as you only put an Apple into a List<Apple>. However, writeExact() does not allow you to put an Apple into a List<Fruit>, even though you know that should be possible"
If you have a method signature, where one parameter is a container of T and the other parameter is T itself, then you can invoke it with a container with the generic supertype of T and T itself. So in your example:
the type of list can be the same type as item or a supertype.
And you also can get your apple out of the fruit list. When you change the code in the main method to
it compiles without warning and prints packagename.Apple@130c19b
Indeed, what Bruce was getting at is that you cannot pass a List<Fruit> as if it were a List<Apple>. Parameterized types are not covariant, a List<Fruit> is by definition not a List<Apple>. In your example my compiler is smart enough to infer the type as Fruit and not Apple so there is no warning. If a compiler were to infer the type is Apple then you'd have some problems.