Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Generic Trouble (http://www.velocityreviews.com/forums/t737887-generic-trouble.html)

Stefan Ram 11-13-2010 12:25 AM

Generic Trouble
 
I have defined a signature in an interface:

void addrac
( java.lang.Comparable< ? >container,
int position );

. I implemented this as follows in a class:

public void addrac
( final java.lang.Comparable< ? >container,
final int position )...

. This worked fine, until I needed to refer to the type »?«
within the body of the method. I tried to give it a name:

public< T >void addrac
( final java.lang.Comparable< T >container,
final int position )...

. But now Java tells me that this does *not* override the
method of the interface.

One step back in time: Actually, I started from this interface:

void addrac
( java.lang.Comparable container,
int position );

I inserted the »< ? >« only to get rid of a »rawtype« warning.

So what would be a good way to get rid of such »rawtype«
warnings, but also allow implementations to refer to the
type name in their body, when they need this? (Or how can
I get such a reference while still implementing the
signature of the interface?)



Arne Vajhøj 11-13-2010 12:28 AM

Re: Generic Trouble
 
On 12-11-2010 19:25, Stefan Ram wrote:
> I have defined a signature in an interface:
>
> void addrac
> ( java.lang.Comparable< ?>container,
> int position );
>
> . I implemented this as follows in a class:
>
> public void addrac
> ( final java.lang.Comparable< ?>container,
> final int position )...
>
> . This worked fine, until I needed to refer to the type »?«
> within the body of the method. I tried to give it a name:
>
> public< T>void addrac
> ( final java.lang.Comparable< T>container,
> final int position )...
>
> . But now Java tells me that this does *not* override the
> method of the interface.
>
> One step back in time: Actually, I started from this interface:
>
> void addrac
> ( java.lang.Comparable container,
> int position );
>
> I inserted the »< ?>« only to get rid of a »rawtype« warning.
>
> So what would be a good way to get rid of such »rawtype«
> warnings, but also allow implementations to refer to the
> type name in their body, when they need this? (Or how can
> I get such a reference while still implementing the
> signature of the interface?)


Why not use <T> in the interface?

Arne

Stefan Ram 11-13-2010 12:34 AM

Re: Generic Trouble
 
Arne Vajhøj <arne@vajhoej.dk> writes:
>Why not use <T> in the interface?


If this is the recommended way to deal with a »rawtype«
warning, when one does not want to restrict the type
parameter to anything more special than »java.lang.Object«,
ok, I will do it.

I just had read advice before to use »< ? >« in such cases,
so I already have edited this into dozens of places. Ok,
so now I may go back and change it to »< T >«. I just want
a general and final solution, so that I will not have to
change this even more often.


Andreas Leitgeb 11-13-2010 02:30 AM

Re: Generic Trouble
 
Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> Arne Vajhøj <arne@vajhoej.dk> writes:
>>Why not use <T> in the interface?


First of all, the generic class will *not* know the actual
type used. At most you can enforce it to be a subclass or
superclasses of some given class.

So let's assume that in your method you're going to deal with
type Number (which subclasses Object and is subclassed e.g. by
Integer):

Now, it depends on what you want to do with the Collection that
you're going to pass to that method:

- access elements *FROM* it:
use <T extends Number>, as that will allow
Collection<Number> but also Collection<Integer>
instances to be used.
- add (or overwrite) elements *TO* it:
use <T super Number>, as it is perfectly legal to write
objects that are known to be at least Numbers either to
a Collection<Object> as well as to a Collection<Number>
- do both of these above:
use Collection<Number>. Nothing else would allow for both
reading and writing Numbers.

And now, I guess, someone will come up and correct me in all those
points, where I decided to keep it simple to the point of omission
of some accuracy.


Lew 11-13-2010 02:54 AM

Re: Generic Trouble
 
On 11/12/2010 09:30 PM, Andreas Leitgeb wrote:
> Stefan Ram<ram@zedat.fu-berlin.de> wrote:
>> Arne Vajhøj<arne@vajhoej.dk> writes:
>>> Why not use<T> in the interface?

>
> First of all, the generic class will *not* know the actual
> type used. At most you can enforce it to be a subclass or
> superclasses of some given class.
>
> So let's assume that in your method you're going to deal with
> type Number (which subclasses Object and is subclassed e.g. by
> Integer):
>
> Now, it depends on what you want to do with the Collection that
> you're going to pass to that method:
>
> - access elements *FROM* it:
> use<T extends Number>, as that will allow
> Collection<Number> but also Collection<Integer>
> instances to be used.
> - add (or overwrite) elements *TO* it:
> use<T super Number>, as it is perfectly legal to write
> objects that are known to be at least Numbers either to
> a Collection<Object> as well as to a Collection<Number>
> - do both of these above:
> use Collection<Number>. Nothing else would allow for both
> reading and writing Numbers.
>
> And now, I guess, someone will come up and correct me in all those
> points, where I decided to keep it simple to the point of omission
> of some accuracy.


Looks correct from here.

Another point is that the <?> dodge works well for parameters to methods, but
not so well for returns from methods or member variable types.

The symptom the OP describes is a manifestation of incomplete type analysis.

The attempt to use a simplistic rule of thumb, like "always avoid raw types
with <?>", leads to such incomplete analysis. Unfortunately, to analyze types
down to where generics stop whing is to analyze them down to where you have
delineated all the type constraints completely. This is hard, especially when
you haven't yet gotten used to type analysis and type assertions, but it gets
a little better once you make the cognitive shift.

Don't think of generics as a way to eliminate warnings. If that's all you
need, just use raw types and '@SuppressWarnings("unchecked")'. Who needs all
that high-falutin' type safety anyway?

If you do need type safety, the good news is that a complete type analysis
reflects quite neatly as generics assertions in your Java code, and you will
have locked the door against all kinds of sneaky and
hard-to-diagnose-at-runtime bugs. I assess that the difficulty of generics is
precisely the difficulty of a complete type analysis. Thank goodness the
source records and the compiler enforces the results of that analysis.

--
Lew

John B. Matthews 11-13-2010 03:13 PM

Re: Generic Trouble
 
In article <slrnidru1o.5dh.avl@gamma.logic.tuwien.ac.at>,
Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> wrote:

> Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> > Arne Vajhøj <arne@vajhoej.dk> writes:
> >>Why not use <T> in the interface?

>
> First of all, the generic class will *not* know the actual
> type used. At most you can enforce it to be a subclass or
> superclasses of some given class.
>
> So let's assume that in your method you're going to deal with
> type Number (which subclasses Object and is subclassed e.g. by
> Integer):
>
> Now, it depends on what you want to do with the Collection that
> you're going to pass to that method:
>
> - access elements *FROM* it:
> use <T extends Number>, as that will allow
> Collection<Number> but also Collection<Integer>
> instances to be used.
> - add (or overwrite) elements *TO* it:
> use <T super Number>, as it is perfectly legal to write
> objects that are known to be at least Numbers either to
> a Collection<Object> as well as to a Collection<Number>
> - do both of these above:
> use Collection<Number>. Nothing else would allow for both
> reading and writing Numbers.
>
> And now, I guess, someone will come up and correct me in all those
> points, where I decided to keep it simple to the point of omission
> of some accuracy.


This is an informative explication of Joshua Bloch's maxim, PECS, an
acronym for producer-extends, consumer-super.

For reference, Effective Java Second Edition, Chapter 5, Item 28, Page 3
<http://java.sun.com/docs/books/effective/>

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>

Roedy Green 11-14-2010 02:38 AM

Re: Generic Trouble
 
On 13 Nov 2010 02:30:16 GMT, Andreas Leitgeb
<avl@gamma.logic.tuwien.ac.at> wrote, quoted or indirectly quoted
someone who said :

>
>First of all, the generic class will *not* know the actual
>type used. At most you can enforce it to be a subclass or
>superclasses of some given class.


If you to know the actual class, you will have to pass that as an
explicit class parameter somewhere, or find out the class dynamically
with getClass. Remember that all information about generics is washed
away by the compiler so at runtime, it is as if no generics were used.
All generics can really do is some additional cross-checks on how you
use combinations of classes, taking into consideration only
information that can be gleaned from types known at compile time.
--
Roedy Green Canadian Mind Products
http://mindprod.com

Finding a bug is a sign you were asleep a the switch when coding. Stop debugging, and go back over your code line by line.

Lew 11-14-2010 06:41 PM

Re: Generic Trouble
 
Andreas Leitgeb wrote, quoted or indirectly quoted someone who said :
>> First of all, the generic class will *not* know the actual
>> type used. At most you can enforce it to be a subclass or
>> superclasses of some given class.


Roedy Green wrote:
> If you to know the actual class, you will have to pass that as an
> explicit class parameter somewhere, or find out the class dynamically
> with getClass. Remember that all information about generics is washed
> away by the compiler so at runtime, it is as if no generics were used.
> All generics can really do is some additional cross-checks on how you
> use combinations of classes, taking into consideration only
> information that can be gleaned from types known at compile time.


Exactly so.

Let us not disparage "all [that] generic can really do", though. It is
significant. Once you get your type assertions right for the compiler, it is
impossible to have class-cast problems at run time. Also, the need to know
run=time type information is much rarer than one might think, if all the type
assertions are correct at compile time. Properly used, generics lock down a
program to a significantly more stable state.

When you do need type information at run time, one standard idiom is that
class parameter Roedy mentioned, a runtime type token (RTTT) similar to
(appropriate imports and static imports assumed):

/**
* Foo illustrates a run-time type token (RTTT).
* @param <T> base type of class.
*/
public class Foo <T>
{
private final Logger logger = getLogger( getClass() );

private final Class <T> rttt;
/**
* Constructor with run-time type token.
* @param tok Class {@code <T>} type token.
*/
public Foo( Class <T> tok )
{
if ( tok == null )
{
final String msg = "Run-time type token must not be null";
IllegalArgumentException fubar = new IllegalArgumentException( msg );
logger.error( msg, fubar );
throw fubar;
}
this.rttt = tok;
assert this.rttt != null;
}
// ... rest of the class
}

You can use the methods of 'rttt' to cast, check compatibility and do other
run-timey type thingies.

--
Lew

Daniel Pitts 11-14-2010 06:52 PM

Re: Generic Trouble
 
On 11/12/2010 4:34 PM, Stefan Ram wrote:
> Arne Vajhøj<arne@vajhoej.dk> writes:
>> Why not use<T> in the interface?

>
> If this is the recommended way to deal with a »rawtype«
> warning, when one does not want to restrict the type
> parameter to anything more special than »java.lang.Object«,
> ok, I will do it.
>
> I just had read advice before to use »< ?>« in such cases,
> so I already have edited this into dozens of places. Ok,
> so now I may go back and change it to »< T>«. I just want
> a general and final solution, so that I will not have to
> change this even more often.
>

I think maybe you misinterpreted Arne's suggestion, or I did.

I take his suggestion as:

interface MyInterface<T> {
void addrac(Comparable<T> container, int position);
}

class MyClassForFoo implements MyInterface<Foo> {
void addrac(Comparable<Foo> container, int position) {}
}


Another alternative, which may work equally well, depending on your
situation, but I doubt it will because of the method signature and lack
of other context in the parameters.


interface MyInterface {
<T>void addrac(Comparable<T> container, int position);
}

class MyClass implements MyInterface {
<T> void addrac(Comparable<T> container, int position) {
T t = container;
}
}



--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Ian 11-15-2010 10:45 AM

Re: Generic Trouble
 
On 13/11/10 15:13, John B. Matthews wrote:
>
> This is an informative explication of Joshua Bloch's maxim, PECS, an
> acronym for producer-extends, consumer-super.


As a newbie, I found his choice of acronym absolutely hideous and
totally non-mnemonic.

I eventually settled on:

extract <-> extends
supply <-> super

tells you what to do & everything ;)

Ian.


All times are GMT. The time now is 05:53 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.