A small correction: allowing downcasting doesn't generate a warning
about unchecked casting.

Here's a small test case in case you want to play with this:

package generics;

import java.util.List;

public class TestG {

  class Box<T> {  // version returning down-castable thing
    <U extends T> U get() {return null;}
    <U extends T> List<U> getL() {return null;}
  }
 
  class StrictBox<T> {  // version returning just type T
    T get() {return null;}
    List<T> getL() {return null;}
  }

  Box<Number> box = new Box<Number>(); 
  StrictBox<Number> sbox = new StrictBox<Number>();
 
  void test() {
    // returning elements
    Number n = box.get();   // OK
    Integer n2 = box.get(); // OK
   
    Number sn = sbox.get();   // OK
    Integer sn2 = sbox.get(); // fails
    Integer sn3 = (Integer) sbox.get(); // OK
   
    // returning lists
    List<Number> ln = box.getL();   // OK
    List<Integer> ln2 = box.getL(); // OK
   
    List<Number> sln = sbox.getL(); // OK
    List<Integer> sln2 = sbox.getL(): // fails, no fix available  
  }
}

-Marshall

Marshall Schor wrote:
> Here's a new thread to discuss just one particular issue - a generics
> tradeoff.
>
> In other posts, people have expressed misgivings about letting users
> "downcast" List<someType> to List<someSubType>, if it cannot be
> *guaranteed* at compile time that this is valid.
>
> Here's a simple example, for instance, using two built-in Java classes:
>   Number
>     Integer (a subtype of Number)
>
> If we have a method which returns a List<Number>, and you happen to know
> it only contains Integers, and you want to use a for-each on it with a
> method that only exists in the Integer class, you have to do manual
> casting within the loop.
>
> An alternative might have been to do:
>   List<Number> numbers = ...;
>   List<Integer> int_version = numbers;  // not allowed, gives compile error
>
> So once we're given the "numbers" object, as far as I can see, we're
> stuck with its typing.  (Please tell me if I'm wrong here).
>
> I see that there is a trade-off between specifying return types as
> specific types, and specifying them as T extends X, and letting the user
> specify a possibly incorrect downcast.  The tradeoff on the plus side is
> that the user gets to write the new style for-each loops, and have code
> without casts inside loops, etc., and on the minus side, the user when
> doing this gets that warning about the possibility that at runtime a
> casting error could be thrown.  But of course, that same casting error
> could be thrown in restricted style, too, at the point of the explicit
> user cast.
>
> I'll probably stop trying to convince others if they continue to feel
> that the tradeoffs here should be in the direction of returning only
> specific types (disallowing users from specifying downcasting in that
> manner), versus using types of the form T extends X,
> which allows users to specify downcasting.
>
> I'd be interested in any literature pointers discussing this trade-off
> issue, if anyone has good ones :-)
>
> -Marshall
>
>
>   

Reply via email to