aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes generics Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "generics" Watch "generics" New topic
Author

generics

Shwetha Sharma
Ranch Hand

Joined: Jun 01, 2008
Posts: 34

Source : http://www.etattva.com/


The explaination says :
Does not compile at 2. List<T> is required. Can not convert ArrayList<String> to List<T>

Can someone explain


SCJP6:80%, OCWCD 88 %
Djonatah Stiegler
Ranch Hand

Joined: Oct 30, 2008
Posts: 32
You cannot use the wildcard ? when declaring collections.

K&B book says clearly that it is not legal.

think about, what would be if you have the following "for" loop inside the method.



I hope this helps you.
<><

[ December 29, 2008: Message edited by: Djonatah Stiegler ]
[ December 29, 2008: Message edited by: Djonatah Stiegler ]

From Brazil
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

Originally posted by Djonatah Stiegler:
You cannot use the wildcard ? when declaring collections.


He is not declaring a collection with a wildcard, he just declared a method that accepts list<?> as parameter.

Originally posted by Sharma Shweta:

The explaination says :
Does not compile at 2. List<T> is required. Can not convert ArrayList<String> to List<T>


You declare that the function returns a List of type T but you are trying to return a List of type String.

It should be something like this:


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." --- Martin Fowler
Please correct my English.
Djonatah Stiegler
Ranch Hand

Joined: Oct 30, 2008
Posts: 32
I'm sorry I was wrong,

I didn't see I was stupid.. you are right , you can receive a List<?>...

Sorry for that
Punit Singh
Ranch Hand

Joined: Oct 16, 2008
Posts: 952
Originally posted by Sharma Shweta:
Source : http://www.etattva.com/


The explaination says :
Does not compile at 2. List<T> is required. Can not convert ArrayList<String> to List<T>

Can someone explain


Your method return type is List<T>.
So you should think what are the valid options assignable to List<T> reference.

like:
1. List<T> list=new ArrayList<T>();//valid

2. List<T> list=new ArrayList();//valid

3. List<T> assignList=new ArrayList<T>();
List<T> list=assignList;//valid

4. List assignList1=new ArrayList<T>();
List<T> list=assignList1;//valid

5. List<T> assignList2=new ArrayList();
List<T> list=assignList2;//valid

6. List<T> list=new ArrayList<String>();//invalid, generics parameter should not differ

7. List<T> list=new ArrayList<Object>();//invalid, generics parameter should not differ

so your method could return any of above valid options.


public <T> List<T> meth(List<?> type)
{
System.out.println(type); // 1

return new ArrayList<T>();//ok 1

//return new ArrayList(); //ok 2

//List<T> assignList=new ArrayList<T>();
//return assignList;//ok 3


//List assignList1=new ArrayList<T>();
//return List<T> list=assignList1;//ok 4

//List<T> assignList2=new ArrayList();
//return assignList2;//ok 5

}


SCJP 6
Shwetha Sharma
Ranch Hand

Joined: Jun 01, 2008
Posts: 34

Thanks Punit for for the explaination
I am finding generics as the most difficult part of the exam.
Well one more question

It is giving compile time error saying that
found : java.Util.List<java.lang.Integer>
required : java.Util.List<T>

Why is this error coming as we have already defined T as T extends Number, so this method can return any List of object of a class which is subclass of Number
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9302
    
  17

T is supposed to be a sub-class of Number. But the method itself cannot decide what T actually is. This will be decided by the call to the method

If you call the method as

List<Integer> list = obj.meth(new ArrayList());

Then T will represent Integer. But if you call the method like this

List<Byte> list = obj.meth(new ArrayList());

Then T will represent Byte. So the call to the method will decide what T represents. You cannot decide this in the method itself...


SCJP 6 | SCWCD 5 | Javaranch SCJP FAQ | SCWCD Links
Harvinder Thakur
Ranch Hand

Joined: Jun 10, 2008
Posts: 231
Shweta the List<?> as argument to meth() does not really help you use the power of generics.
First of all you could send List<String> type object to the method.
Secondly, you won't know inside the method what you are getting in the argument.
Thirdly, you can't add anything to the List<T> list1 as list1.add() takes an argument of type T which is decided at compile time.

Moreover, Ankit i don't think that in the following statement

List<Byte> list = obj.meth(new ArrayList());

you are actually deciding what type <T> is. Actually you could do the following with misleading type info.




Please correct me if i am wrong.
[ January 02, 2009: Message edited by: Harvinder Thakur ]

thanks
Harvinder
Ankit Garg
Sheriff

Joined: Aug 03, 2008
Posts: 9302
    
  17

As far as I know, call to the method will decide the type of T. It is another matter that you can trick the generics mechanism like you gave the example. I didn't try to compile your program but I think it will give a warning at

List<T> list1 = new ArrayList();

So basically if you get a runtime exception, then the compiler is not responsible as it had warned you.

Moreover if the call would not decide the type of T, then the call would fail. If I call

List<Byte> list = obj.meth(new ArrayList());

and if you say that T would not represent Byte, then can you tell me what T would represent. Suppose T would represent Number, then the assignment would look like this

List<Byte> list = new List<Number>();

and this would fail to compile as you cannot assign a Number list to a Byte list. Not even Number, if the type of T is not Byte, then assignment would fail for any type other than Byte. I mean to say that List<Byte> can only be assigned a List of type Byte and nothing else.

So finally I would say that the call decides the type of T as T is only in the return clause. I may be wrong as I am not a Guru or something...
Punit Singh
Ranch Hand

Joined: Oct 16, 2008
Posts: 952

public <T extends Number> List<T> meth(List<?> type)
{
System.out.println(type); // 1
List<Integer> list1 = new ArrayList();
return list1;
}


You are doing this thing here:
List<T extends Number> list=new ArrayList<Integer>();

So compiler does not know here what could be T in <T extends Number>, it could be Byte, Short, Long, Float, Double. If this was allowed than there is no runtime checking or runtime generics info that will stop you from adding Double value in a Integer list.

If you know ArrayStoreException, and why ArrayStoreException happen? you will understand it quickly. ArrayStoreException is runtime checking with array that determines Integer[] cannot contain Double value, but for generics there is no such equivalent runtime checking, so compiler detects this type of situation and avoids you from doing these things.

If you think like compiler here, you can understand it more comprehensively.
John Grabowsky
Greenhorn

Joined: Dec 30, 2008
Posts: 26
Let us first discuss whether a List<Byte> IS-A List<Number>. The code

is correct if x is a List<Number>, but not if x is a List<Byte>. Thats why, List<Byte> not IS-A List<Number>.

For the moment, we ignore the implementation of meth by return null, which is always possible, but include T in the parameter definition:

meth compiles fine. When the compiler tries to compile one of the lines in main, it tries to map T to a type so that the arguments match and the bound T extends Number is satisfied. In line 5 this is impossible, so this line fails to compile, even without an assignment. In lines 1 and 3 T maps to Byte, in lines 2 and 4 T maps to Number. But since the return type of meth is List<T>, the right hand side in line 2 is now List<Number>, which cannot assigned to a List<Byte>. Similarly, line 3 fails. Lines 1 and 4 compile.

If we change the method definition to

the arguments do not restrict T, and the compiler map T to make the assignments possible: T maps to Byte in lines 1 and 2, T maps to Number in lines 3 and 4. All lines in main compile.

Anything we write instaed of line 0 must play with all possible mappings for T. At the time of compiling meth, only T extends Number is known. So

fails, since it not IS-A List<T> if T is mapped to Byte, and

fails, since it not IS-A List<T> if T is mapped to Number. Ok is

If we change the return type, things become interesting, the following compiles (but the lines in main must change too):

On my exam, there where no such weird questions on generics. It is more important to be completly clear with object orientation, leaving generics aside for a moment. What can a variable assigned to? What can a method return? (Hint: there are a lot of IS-A in the answers.) Combining this with what i said about IS-A above was enough.


John<br />SCJP 5, 97%
Shwetha Sharma
Ranch Hand

Joined: Jun 01, 2008
Posts: 34

Thanks John for the informative explaination.
patrick avery
Ranch Hand

Joined: Sep 12, 2008
Posts: 46
John...to clarify your final example....................



In this case we can specify:
2. return new ArrayList<Number>();

rather than
2. return new ArrayList<T>();

Is this because Number is the only class that satisfies both <T extends Number> and <? super T> so, there is no ambiguity at compile time as to what
T could be?. While in the prior examples (without the <T extends Number> and <? super T> combination), T could not be known at compile time so the return statement had to return List<T> rather than List<Number> ?


SCJA 96%
SCJP 6 88%
skipping SCJD to work on passing SCWCD
John Grabowsky
Greenhorn

Joined: Dec 30, 2008
Posts: 26
Dear Patrick,

It is not necessary that ONLY Number satisfies both <T extends Number> and <? super T>, btw the following compiles too:

The point is that for every T satisfying <T extends Number>, the generic type we try to return must satisfy <? super T>, which are Object, Number, and T.

T is not known at compile time here (can be Number, Byte, ...), the difference is that T is bounded. If the extends Number is removed, we can return only generic types that satisfy <? super T> for any T, that is Object and T. If, in addition, the ? super is removed (now we are back to Shweta's initial example), we return only generic types equal to T for any choice of T, so T itself is our only choice.
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
John Grabowsky wrote:
T is not known at compile time here (can be Number, Byte, ...), the difference is that T is bounded. If the extends Number is removed, we can return only generic types that satisfy <? super T> for any T, that is Object and T. If, in addition, the ? super is removed (now we are back to Shweta's initial example), we return only generic types equal to T for any choice of T, so T itself is our only choice.

EDIT: I saw the flaw in my reasoning, please disregard my question. The exact value of T is not known at compile time, so the only types that we can return when the return type is List<? super T> will be List<T> and List<Object>, since every type is of type Object. It's interesting that, because of the compile-time nature of generics, in this case adding more information results in more choices for possible return types.

Hi John,

Thanks for explaining all this in such detail. I have a question about your statement set to bold above. How can removing <T extends Number> make the return type more restrictive? I think it would actually make it less restrictive. For example, T is Byte, the return could still be Byte, Number or Object. And if it were any type with 3 ancestor classes instead of two, then you would have 4 possible return types. Am I missing something maybe?

Thanks in advance for your input.


All code in my posts, unless a source is explicitly mentioned, is my own.
John Grabowsky
Greenhorn

Joined: Dec 30, 2008
Posts: 26
Hi Ruben,

i see you analyse thoroughly, interesting discussion. Can you find any return statement that compiles when the signature is

but not when

? I think the point is: the return statement must work with any possible match of T. The more matches for T, the more restricted the legal return statements. Or, said the othe way around, restricting T makes more return statements possible.
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
John,

That's a very precise and insightful way to put it, thanks for explaining.
Pooja Desai
Greenhorn

Joined: Nov 26, 2008
Posts: 5
Hi all,
I am preparing for SCJP1.5 finding generics to be tough and a bit confusing.
Source: Kethy and Bates CD question.

import java.util.*;
public class BackLister{

//Insert code here

{
List<T> output= new linkedList<T>();
for (T t:input)
output.add(0,T);
return output;
}
}

Which of the following can be inserted at // Insert here.
1) public static <T> List <T>backwards ( List <T> input)
2) public static <T> List <T> backwards ( List <? extends T> input)
3) public static <T> List <T> backwards ( List <? super T> input)
4) public static <T> List <? extends T> backwards (List <T> input)
5) public static <T> List <? super T> backwards ( List <T> input)
6) public static <? extends T> List <T> backwards ( List <T> input)


Answer is : ABDE

not clear with the exact declaration syntax for Generics and how to use wildcards -extends and super in the above problem.

If anyone can help me , it will be great. Thanks in advance.
Ruben Soto
Ranch Hand

Joined: Dec 16, 2008
Posts: 1032
Edited
I see Pooja already started a new thread for this question.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: generics