Lets take the code below.
washington is red apple
fuji is red apple
apple is washington
apple is not washington
apple is not washington
apple is not washington
apple is not fuji
The questions are
1) In the above code declaration of class 'Washington' is
Washington<W extends Apple>
What does it mean ?? Is it mean class 'Washington' can hold only objects of type Apple (and not its subclasses example RedApple).
2)What if I replace it with
Washington<W extends Apple<W>>
then why the statement in main method
Washington<Apple<String>> wash = new Washington<Apple<String>>();
Dont work ??
3)Why I have to take 'Apple' as raw type ?? Is it mandatory to always use raw types in such cases when class type is used as bounded type ?
4) In the main method twice RedApple object 'redapple' has been passed to Washington class method CheckWashington() as in statements
Washington<RedApple<String>> wash2 = new Washington<RedApple<String>>();
Both the times the output is "apple is not washington". Why here subclass object 'redapple' has not been upcasted to superclass 'apple' ??? In non-generic classes in a method where superclass object is needed as an argument and subclass object has been sent then it will be upcasted to superclass.
4) How many classes can be used as bounded types ?? As shown in code above the declaration of class fuji is
class Fuji<Apple, F extends Apple>
and the statement in the main method
Fuji<Apple<String>,RedApple<String>> fuji = new Fuji<Apple<String>,RedApple<String>>();
as two objects 'app2' and 'redapple' belongs to Apple and RedApple classes respectively it was not possible to access their type <A> in case of Apple and <R> in case of RedApple. As shown in code below.
In the Washington class we have 'if' statement as
if(w1.a == "washington")
Same in the class Fuji we have if statement as
if(app1 == "fuji" || f1 == "fuji")
Why in the above if statement i cant access 'app1.a'. ??
5) Also the declaration of fuji class
class Fuji<Apple, F extends Apple> Whats the second type parameter actually means here ?? Does it mean that F could be objects of both Apple and its subclass ?
Thanks in advance for reading a long post and the reply.
Have you been through the Java tutorials? Use ctrl-F-“generics” and you will find two sections. Google for Angelika Langer Java Generics and yo ufind some really useful FAQ resources. Try those first.
I think using <? extends Foo> is intended for collections which you are going to read, not which you are going to write. So you may be using it inappropriately if you find you have to use a raw type. Remember raw_type ⇒ error_elsewhere.
Jayant Joshi wrote:Lets take the code below.
Is this code from a tutorial of some kind, or something you dreamt up to teach yourself about generics? Because it contains so many mistakes (starting with the Apple class itself) that it's difficult to sort out the answers to many of your questions.
Like Campbell, I think you really should read the tutorials again carefully; in particular, Gilad Bracha's lesson (he is one of the main authors of generics in Java).
However, I will try and sort out a couple of things for you:
1. class Apple<A>
This form is used only when the type (A) is truly arbitrary and, by convention, takes the form:
class Apple<T> (where 'T' stands for 'type')
and is why your
Apple<String> app1 = new Apple<String>(); line doesn't throw any compiler errors.
But you need to ask yourself: What on earth is an Apple<String>?
The mere fact that you've put 'A' suggests that you actually want it to be a type of Apple, in which case the definition should be:
class Apple<A extends Apple<A>>
class Apple<A extends Apple<?>>
2. class RedApple<R> extends Apple<R>
defines a subclass of Apple that, again, takes an arbitrary type, so you can write
RedApple<NullPointerException> ra = new RedApple<NullPointerException>();
if you want to.
The question is: Do you want to? The whole point of generics is to restict types; or define them in such a way that it enforces consistency at compile time.
For example, a Comparator (java.util.Comparator), can be created for any class, so it makes sense that the definition is:
public interface Comparator<T>
The enforcement comes with its compare() method, which is defined as:
public int compare(T o1, T o2);
which means that if I create (or implement) a Comparator<String>, the compiler will require that I supply Strings when I call this method.
So, going back to your RedApple class: R suggests that you want the type to be a type of RedApple, so the definition becomes:
class RedApple<R extends RedApple<R>>
Hopefully, the above will help you get started.
Its a red apple
its not a red apple
The major query I had was , if I replace the declaration of RedAppleContainer from
then it shows error at line 41 saying that AppleClass<String> is not a valid bound for RedAppleContainer<A>. In Java 2 reference by Herbert Schildt I read that for any
T can only be replaced by Superclass or subclass of the Superclass. Yes I am very new to Generics.
Jayant Joshi wrote:Thanks for your reply. The code I have put up could be contextually wrong but questions were more technical rather contextual. I have changed the code to fit it more contextually.
Yes, but unfortunately, it isn't really any better.still allows you to provide ANY type to a constructor, so you could write:
AppleClass<Error> = new AppleClass<Error>();
when what you presumably want is for C to be some type of colour (eg, a java.awt.Color ?) - although the way you're using it suggests to me that you don't yet grasp the basics.
Before you start using generics, you really need to understand why you use them:
And the simplest example I know of is the Comparable interface:
Before generics, the Comparable interface had a single method:
public int compareTo(Object o);
which meant that implementations had no alternative but to cast the supplied Object to the relevant type. And if that cast failed because an invalid object was passed to the method, it would result in an exception at execution time.
Since 1.5, the definition is now:which enforces proper type checking at compile time.
If I create a class that implements Comparable<String>, then I must pass a String to the method when I call it, otherwise the compiler will complain.
Furthermore, I don't need to cast the supplied value, since I already know that it's a String, so I can happily implement the method as:
Yes I am very new to Generics.
Then, as Campbell said, you really should read the tutorials and FAQ page he showed you.
And don't except to get it first time. I still run into annoying little 'gotchas' from time to time, and am forced to go back and re-read the relevant section, so you're not alone.
Also: generics is nice, but it's NOT a 100% solution. There are situations where it can't cover all eventualities, particularly when it comes to arrays; so don't beat your forehead bloody if you run into problems, especially with more involved situations. Furthermore, most of the times that I do run into problems, it's because there's a flaw in my design - usually because I'm overthinking things (a nasty habit of mine ).