Java type-casting -- Q2

G

grz01

Here another one... still Eclipse:


package bean;

import java.util.ArrayList;
import java.util.List;

public class Lib01 {

public static List<List<?>> createList() {

List<List<?>> result = new ArrayList<List<?>>();

List<String> sList = new ArrayList<String>();
sList.add("xx");

result.add(sList);

return result;
}

public static void consume() {
List<List<?>> l = createList();
List<String> sList = (List<String>) l.get(0); // *WARNING*
System.out.println(sList.get(0));
}
}


This example works when I call consume(), but the second to last stmt
gives me a warning:

Type safety: Unchecked cast from List<capture#1-of ?> to
List<String>

What means "unchecked cast"?
Where do I find this concept defined?

/ grz01
 
L

Lew

grz01 said:
Here another one... still Eclipse:

package bean;

import java.util.ArrayList;
import java.util.List;

public class Lib01 {
public static List<List<?>> createList() {

Please do not indent posts with TABs.
List<List<?>> result = new ArrayList<List<?>>();
List<String> sList = new ArrayList<String>();

Don't use the result inside the code that creates it.
sList.add("xx");

result.add(sList);
return result;
}

public static void consume() {
List<List<?>> l = createList();
List<String> sList = (List<String>) l.get(0); // *WARNING*
System.out.println(sList.get(0));
}
}

This example works when I call consume(), but the second to last stmt
gives me a warning:

Type safety: Unchecked cast from List<capture#1-of ?> to List<String>

You want to avoid wildcards in return types. Lists of lists are tricky, too.

In your case, 'createList()' promises to return a list of lists of something,
but not what that something is. This is the base type - by its nature, the
wildcard doesn't promise much about a base type, but it does promise that it
exists. So it has no way of knowing you want the base type to be 'String'.

Not knowing what the base type is, the compiler assigns it a capture number,
like a hotel room number for types. The return value can have a different
capture type, in fact must, with each call in different parts of the source.

At your cast to 'List<String>' the compiler sees that you're getting back a
'List<capture#1-of ?>' from 'l.get(0)' and casting it to 'List<String>'. It
cannot guarantee that that will work.

By its nature the wildcard throws away type specificity. The attempt to
regain type specificity is an attempt to recapture lost information. Hence
the warning.

Generics casts result in compiler warnings. Cast are run time; generics are
compile time.

The point of generics is to push type analysis to the compiler and to avoid
runtime exceptions like ClassCastException.

Don't think of generics syntax as command- or directive-based. That's what
leads folks into trouble. Generics is a theorem language. It's a declarative
syntax for type relationships and constraints.

Instead of a wildcard return use a generic one:

public <T> static List <List <T>> createListList( T ... values )
{
List <List <T>> result = new ArrayList <List <T>> ();
result.add( Arrays.asList( values ) );
return result;
}

public void test()
{
What means "unchecked cast"?

It means you're using generics in a runtime way. When you do that, you
sacrifice the type safety generics otherwise give. Once you get used to it,
you kinda like it. The concept is "erasure" - generics all but disappear at
runtime. This gives you all the type safety of the compiler (once you get
used to it) with none of the runtime cost. It obviates checking for certain
runtime exceptions like ClassCastException. It also leads to some really
weird code idioms.
Where do I find this concept defined?

In the Java Language Specification.
A cast from a type S to a parameterized type (§4.5) T is
unchecked unless at least one of the following conditions hold:

* S <: T. [S "is-a-subtype-of" T

- upcasts always allowed, though redundant
* All of the type arguments (§4.5.1) of T are unbounded wildcards.

* T <: S and S has no subtype X ["not-equal-to"] T,
such that the erasures (§4.6) of X and T are the same.

This is a koan of generics.
 
L

Lew

"Dave Searles" wrote ...

I should have phrased that "don't test the code inside the code under test".

The "use" in question was not a fundamental part of the method inside which it
appeared.
 
R

Roedy Green

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top