Generic Trouble

Discussion in 'Java' started by Stefan Ram, Nov 13, 2010.

  1. Stefan Ram

    Stefan Ram Guest

    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?)
    Stefan Ram, Nov 13, 2010
    #1
    1. Advertising

  2. Stefan Ram

    Arne Vajhøj Guest

    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
    Arne Vajhøj, Nov 13, 2010
    #2
    1. Advertising

  3. Stefan Ram

    Stefan Ram Guest

    Arne Vajhøj <> 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.
    Stefan Ram, Nov 13, 2010
    #3
  4. Stefan Ram <-berlin.de> wrote:
    > Arne Vajhøj <> 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.
    Andreas Leitgeb, Nov 13, 2010
    #4
  5. Stefan Ram

    Lew Guest

    On 11/12/2010 09:30 PM, Andreas Leitgeb wrote:
    > Stefan Ram<-berlin.de> wrote:
    >> Arne Vajhøj<> 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
    Lew, Nov 13, 2010
    #5
  6. In article <>,
    Andreas Leitgeb <> wrote:

    > Stefan Ram <-berlin.de> wrote:
    > > Arne Vajhøj <> 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>
    John B. Matthews, Nov 13, 2010
    #6
  7. Stefan Ram

    Roedy Green Guest

    On 13 Nov 2010 02:30:16 GMT, 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.


    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.
    Roedy Green, Nov 14, 2010
    #7
  8. Stefan Ram

    Lew Guest

    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
    Lew, Nov 14, 2010
    #8
  9. Stefan Ram

    Daniel Pitts Guest

    On 11/12/2010 4:34 PM, Stefan Ram wrote:
    > Arne Vajhøj<> 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/>
    Daniel Pitts, Nov 14, 2010
    #9
  10. Stefan Ram

    Ian Guest

    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.
    Ian, Nov 15, 2010
    #10
  11. Stefan Ram

    markspace Guest

    On 11/15/2010 2:45 AM, Ian wrote:
    > 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



    Except that producer and consumer are much more standard computer
    science terms. (Type "producer consumer" into Google and see what you get.)
    markspace, Nov 15, 2010
    #11
  12. Stefan Ram

    Ian Guest

    On 15/11/10 20:48, markspace wrote:
    > Except that producer and consumer are much more standard computer
    > science terms. (Type "producer consumer" into Google and see what you get.)


    OK so you've outed a newbie (I studied engineering, not computer science) ;)

    Ian.
    Ian, Nov 16, 2010
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marek Ponca

    FC II & Generic

    Marek Ponca, Nov 21, 2003, in forum: VHDL
    Replies:
    1
    Views:
    476
    Marcin
    Nov 22, 2003
  2. Hypo
    Replies:
    6
    Views:
    407
  3. Murat Tasan
    Replies:
    1
    Views:
    8,040
    Chaitanya
    Feb 3, 2009
  4. Replies:
    2
    Views:
    434
  5. minlearn
    Replies:
    2
    Views:
    454
    red floyd
    Mar 13, 2009
Loading...

Share This Page