Method chaining with generics

Discussion in 'Java' started by iksrazal@terra.com.br, Aug 30, 2005.

  1. Guest

    Hi all,

    Allow my code to explain:

    Bsc bsc = BscHelper.createBsc();
    SiteType siteType = BscHelper.createSiteType(id,name);
    bsc.getSite().add(siteType);

    getSite() returns List. It was written without generics in mind.
    However, I get a warning in eclipse:

    Type safety: The method add(Object) belongs to the raw type List.
    References to generic
    type List<E> should be parameterized

    What it wants is:

    List<SiteType> list = new ArrayList<SiteType>();

    How can I use method chaining with generics?

    iksrazal
    , Aug 30, 2005
    #1
    1. Advertising

  2. wrote:
    >
    > Bsc bsc = BscHelper.createBsc();
    > SiteType siteType = BscHelper.createSiteType(id,name);
    > bsc.getSite().add(siteType);
    >
    > getSite() returns List. It was written without generics in mind.
    > However, I get a warning in eclipse:
    >
    > Type safety: The method add(Object) belongs to the raw type List.
    > References to generic
    > type List<E> should be parameterized
    >
    > What it wants is:
    >
    > List<SiteType> list = new ArrayList<SiteType>();
    >
    > How can I use method chaining with generics?


    I don't think it's anything to do with chaining. You just need to return
    a generified List.

    interface Bsc {
    List<SiteType> getSite();
    }
    Thomas Hawtin, Aug 30, 2005
    #2
    1. Advertising

  3. Hemal Pandya Guest


    > Hi all,
    >
    > Allow my code to explain:
    >
    > Bsc bsc = BscHelper.createBsc();
    > SiteType siteType = BscHelper.createSiteType(id,name);
    > bsc.getSite().add(siteType);
    >
    > getSite() returns List. It was written without generics in mind.
    > However, I get a warning in eclipse:
    >
    > Type safety: The method add(Object) belongs to the raw type List.
    > References to generic
    > type List<E> should be parameterized
    >
    > What it wants is:
    >
    > List<SiteType> list = new ArrayList<SiteType>();


    Almost. javac accepts if getSite returns any compatible generic type:
    List<SiteType> or even List<Object>. So Bsc is open this is simple.

    Otherwise, you can replace with
    ((List<Object>)(bsc.getSites())).add(siteType);
    for which javac produces a different warnign that is IMHO less severe.

    Actually I don't quite understand why cast from List to List<Object> is
    a warning at all.
    >
    > How can I use method chaining with generics?
    >
    > iksrazal
    Hemal Pandya, Aug 30, 2005
    #3
  4. Guest

    Thanks for the response.

    The class is autogenerated via JAXB, so I can't really just do:

    interface Bsc {
    List<SiteType> getSite();

    However, as stated I do get a different warning now:

    ((List<Object>)(bsc.getSite())).add(siteType);

    Type safety: The cast from List to List<Object> is actually checking
    against the erased type List

    Hmm. I work in an environment where warnings are discouraged. Any idea
    on how to get this to work, ie no warnings, without changing the Bsc
    interface?

    Thanks,
    iksrazal
    , Aug 30, 2005
    #4
  5. Oliver Wong Guest

    "Hemal Pandya" <> wrote in message
    news:...
    > Actually I don't quite understand why cast from List to List<Object> is
    > a warning at all.


    The warning says that the runtime environment can't actually tell
    whether the cast succeeds or not (due to type erasure), so basically, the
    code that you wrote down is not actually hapenning. I think that warrants a
    warning.

    - Oliver
    Oliver Wong, Aug 30, 2005
    #5
  6. wrote:
    >
    > The class is autogenerated via JAXB, so I can't really just do:


    Is there not a more recent versions of JAXB that copes with generics?

    > Hmm. I work in an environment where warnings are discouraged. Any idea
    > on how to get this to work, ie no warnings, without changing the Bsc
    > interface?


    If you mix generics with old-style code you are going to get warnings.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Aug 30, 2005
    #6
  7. Oliver Wong wrote:
    > "Hemal Pandya" <> wrote in message
    > news:...
    >
    >>Actually I don't quite understand why cast from List to List<Object> is
    >>a warning at all.

    >
    >
    > The warning says that the runtime environment can't actually tell
    > whether the cast succeeds or not (due to type erasure), so basically, the
    > code that you wrote down is not actually hapenning. I think that warrants a
    > warning.
    >


    I think your point is valid when dealing with List and List<Foo>, but
    Hemal was specifically referring to List<Object>. Is there any case
    when casting a List to List<Object> would cause a problem?

    Ray

    --
    XML is the programmer's duct tape.
    Raymond DeCampo, Aug 30, 2005
    #7
  8. wrote:
    > Allow my code to explain:
    >
    > Bsc bsc = BscHelper.createBsc();
    > SiteType siteType = BscHelper.createSiteType(id,name);
    > bsc.getSite().add(siteType);
    >
    > getSite() returns List. It was written without generics in mind.


    The real error is an architectural design bug. You have a class Bsc
    which contains a list of sites, and you hand out that list to the public
    for manipulation. This seriously breaks encapsulation. Class Bsc should
    instead get a method addSite(), and do all the list handling internally.

    /Thomas

    --
    The comp.lang.java.gui FAQ:
    ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
    http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
    Thomas Weidenfeller, Aug 31, 2005
    #8
  9. Hemal Pandya Guest


    > Oliver Wong wrote:
    > > "Hemal Pandya" <> wrote in message
    > > news:...
    > >
    > >>Actually I don't quite understand why cast from List to List<Object> is
    > >>a warning at all.

    > >
    > >
    > > The warning says that the runtime environment can't actually tell
    > > whether the cast succeeds or not (due to type erasure), so basically, the
    > > code that you wrote down is not actually hapenning. I think that warrants a
    > > warning.
    > >

    >
    > I think your point is valid when dealing with List and List<Foo>, but
    > Hemal was specifically referring to List<Object>. Is there any case
    > when casting a List to List<Object> would cause a problem?


    Yes, precisely. I considered if auto-boxing could cause a problem but
    am unable to come up with an example.

    This makes incremental migration of code from 1.4 to 5 rife with
    warnings. Until I have migrated all my code and the third party code
    has migrated to using generics.

    The reason I like this warning better is that I can filter it out in
    javac using "grep -v".
    Hemal Pandya, Aug 31, 2005
    #9
  10. Chris Uppal Guest

    Raymond DeCampo wrote:

    > Is there any case
    > when casting a List to List<Object> would cause a problem?


    I haven't been following the thread, so this may be irrelevant. But if you
    start with a List that is intended to hold Strings (whether it's declared as a
    List or a List<String> doesn't matter provided it reaches your code as a List)
    and cast that to a List<Object>, then you'll be able to add a Rectangle to it,
    which would not be correct.

    -- chris
    Chris Uppal, Aug 31, 2005
    #10
  11. Guest

    Bsc was autogenerated via JAXB. don't think I can avoid it.

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0">
    <xs:element name="Bsc">
    <xs:complexType>
    <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="unbounded" name="site">
    <xs:complexType>
    <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1" name="id"
    type="xs:long" />
    <xs:element minOccurs="1" maxOccurs="1" name="name"
    type="xs:string" />
    <xs:element minOccurs="1" maxOccurs="unbounded"
    name="Celula">
    <xs:complexType>
    <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1" name="id"
    type="xs:long" />
    <xs:element minOccurs="1" maxOccurs="1"
    name="cell_id" type="xs:string" />
    <xs:element minOccurs="1" maxOccurs="unbounded"
    name="Trx">
    <xs:complexType>
    <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1"
    name="id" type="xs:long" />
    <xs:element minOccurs="1" maxOccurs="1"
    name="name" type="xs:string" />
    <xs:element minOccurs="1"
    maxOccurs="unbounded" name="Extra" >
    <xs:complexType>
    <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1"
    name="id" type="xs:long" />
    <xs:element minOccurs="1" maxOccurs="1"
    name="name" type="xs:string" />
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:schema>

    iksrazal
    , Aug 31, 2005
    #11
  12. Hemal Pandya Guest

    Chris Uppal wrote:
    > Raymond DeCampo wrote:
    >
    > > Is there any case
    > > when casting a List to List<Object> would cause a problem?

    >
    > I haven't been following the thread, so this may be irrelevant. But if you
    > start with a List that is intended to hold Strings (whether it's declared as a
    > List or a List<String> doesn't matter provided it reaches your code as a List)
    > and cast that to a List<Object>, then you'll be able to add a Rectangle to it,
    > which would not be correct.


    Very true. There are two different cases depending on how the List
    started. If it was intended to hold Strings but created as a List, not
    a List<String> then the error is at the point of creation. This issue
    exists in all java until 5.0. If it was created as a List<String> then
    the error is where it was converted to List.

    But given a List, which by definition is a list of Objects, is there a
    case where casting it to List<Object> is dangerous?
    Hemal Pandya, Aug 31, 2005
    #12
  13. Thomas Weidenfeller wrote:
    > wrote:
    >
    >> Allow my code to explain:
    >>
    >> Bsc bsc = BscHelper.createBsc();
    >> SiteType siteType = BscHelper.createSiteType(id,name);
    >> bsc.getSite().add(siteType);
    >>
    >> getSite() returns List. It was written without generics in mind.

    >
    >
    > The real error is an architectural design bug. You have a class Bsc
    > which contains a list of sites, and you hand out that list to the public
    > for manipulation. This seriously breaks encapsulation. Class Bsc should
    > instead get a method addSite(), and do all the list handling internally.


    Not necessarily. If assuming that the implementation of the list
    returned keeps bsc in sync, it's fine. List doesn't have to imply
    ArrayList/LinkedList.

    Law of Demeter, perhaps.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Aug 31, 2005
    #13
  14. Oliver Wong Guest

    "Hemal Pandya" <> wrote in message
    news:...
    >
    > Chris Uppal wrote:
    >> Raymond DeCampo wrote:
    >>
    >> > Is there any case
    >> > when casting a List to List<Object> would cause a problem?

    >>
    >> I haven't been following the thread, so this may be irrelevant. But if
    >> you
    >> start with a List that is intended to hold Strings (whether it's declared
    >> as a
    >> List or a List<String> doesn't matter provided it reaches your code as a
    >> List)
    >> and cast that to a List<Object>, then you'll be able to add a Rectangle
    >> to it,
    >> which would not be correct.

    >
    > Very true. There are two different cases depending on how the List
    > started. If it was intended to hold Strings but created as a List, not
    > a List<String> then the error is at the point of creation. This issue
    > exists in all java until 5.0. If it was created as a List<String> then
    > the error is where it was converted to List.
    >
    > But given a List, which by definition is a list of Objects, is there a
    > case where casting it to List<Object> is dangerous?


    This is exactly the issue that the compiler is warning about: Due to
    type erasure, there's no way for the runtime to ensure that something which
    is a "List" is actually a "List<Object>" and not, for example, a
    "List<String>".

    public static test(List someList) {
    List<Object> listOfObjects = (List<Object>)someList;
    }

    public static void main(String args[]) {
    test(new List<String>());
    }

    In the above sample code, the runtime will NOT throw a class cast
    exception, because it will not be able to detect that the list passed was
    actually a list of Strings and not a list of Objects.

    Hence the warning in the compiler.

    - Oliver
    Oliver Wong, Aug 31, 2005
    #14
  15. Oliver Wong wrote:
    > "Hemal Pandya" <> wrote in message
    > news:...
    >
    >>Chris Uppal wrote:
    >>
    >>>Raymond DeCampo wrote:
    >>>
    >>>
    >>>>Is there any case
    >>>>when casting a List to List<Object> would cause a problem?
    >>>
    >>>I haven't been following the thread, so this may be irrelevant. But if
    >>>you
    >>>start with a List that is intended to hold Strings (whether it's declared
    >>>as a
    >>>List or a List<String> doesn't matter provided it reaches your code as a
    >>>List)
    >>>and cast that to a List<Object>, then you'll be able to add a Rectangle
    >>>to it,
    >>>which would not be correct.

    >>
    >>Very true. There are two different cases depending on how the List
    >>started. If it was intended to hold Strings but created as a List, not
    >>a List<String> then the error is at the point of creation. This issue
    >>exists in all java until 5.0. If it was created as a List<String> then
    >>the error is where it was converted to List.
    >>
    >>But given a List, which by definition is a list of Objects, is there a
    >>case where casting it to List<Object> is dangerous?

    >
    >
    > This is exactly the issue that the compiler is warning about: Due to
    > type erasure, there's no way for the runtime to ensure that something which
    > is a "List" is actually a "List<Object>" and not, for example, a
    > "List<String>".
    >
    > public static test(List someList) {
    > List<Object> listOfObjects = (List<Object>)someList;
    > }
    >
    > public static void main(String args[]) {
    > test(new List<String>());
    > }
    >
    > In the above sample code, the runtime will NOT throw a class cast
    > exception, because it will not be able to detect that the list passed was
    > actually a list of Strings and not a list of Objects.
    >
    > Hence the warning in the compiler.
    >


    The point we are trying to make is that it makes more sense (IMHO) to
    emit a warning when casting a List<String> or such to a List. Then the
    warning on a cast from List to List<Object> could be eliminated and your
    scenario is still covered by a warning.

    Ray

    --
    XML is the programmer's duct tape.
    Raymond DeCampo, Aug 31, 2005
    #15
  16. Oliver Wong Guest

    "Raymond DeCampo" <> wrote in message
    news:dxjRe.47664$...
    > The point we are trying to make is that it makes more sense (IMHO) to emit
    > a warning when casting a List<String> or such to a List. Then the warning
    > on a cast from List to List<Object> could be eliminated and your scenario
    > is still covered by a warning.


    I disagree that that would make more sense: Casting a "List<String>" to
    a "List" in itself cannot cause any error to occur (a conceptual error may
    occur later on if you try to add an arbitrary object to that list, but if
    the compiler could detect this, then the warning should appear where the add
    occurs, and not where the casting occurs). However, when you cast a "List"
    to a "List<Object>", this IS an error prone operation in the sense that the
    runtime can't actually check that your assumption is correct.

    I think the problem here is that you think that "List" means "List of
    objects", whereas I think that "List" means "List, but I don't know of
    what". Under my understanding, if you say "I have a List of String, and I
    want to convert it to a List of something unknown", then that should be
    fine. But if you say "I have a List of something Unknown, and I want to
    convert it to a List of Objects", then that might not be legal, as it might
    actually be a list of Strings.

    Sort of like casting an object of type String to be of type Object is
    always safe (information is lost), but casting an object of type Object to
    String is not safe (the programmer is making an assumption here which may or
    may not be true).

    - Oliver
    Oliver Wong, Aug 31, 2005
    #16
  17. Oliver Wong wrote:
    > "Raymond DeCampo" <> wrote in message
    > news:dxjRe.47664$...
    >
    >>The point we are trying to make is that it makes more sense (IMHO) to emit
    >>a warning when casting a List<String> or such to a List. Then the warning
    >>on a cast from List to List<Object> could be eliminated and your scenario
    >>is still covered by a warning.

    >
    >
    > I disagree that that would make more sense: Casting a "List<String>" to
    > a "List" in itself cannot cause any error to occur (a conceptual error may
    > occur later on if you try to add an arbitrary object to that list, but if
    > the compiler could detect this, then the warning should appear where the add
    > occurs, and not where the casting occurs).


    So should the compiler issue a warning whenever List.add() is called?
    After all, the List may have come from a cast from List<String> (for
    example, if a public method accepts a List parameter).

    The whole danger starts when you throw away information by casting
    List<String> to List. There is no ambiguity as to when that happens, so
    it is a very good place to issue a warning.

    You say that you do not a warning when List<String> is cast to List
    because "it cannot cause any error to occur". But in fact it is the
    cause; just because it is not in the stack trace at runtime doesn't make
    it any less so.

    > However, when you cast a "List"
    > to a "List<Object>", this IS an error prone operation in the sense that the
    > runtime can't actually check that your assumption is correct.


    What assumption? I'm "assuming" that I can put Objects in a List. What
    is the difference at compile time between a List and a List<Object>
    (aside from warnings, which is the crux of the issue here)? How is it
    any different from not being able to check that List.add() vs.
    List<Object>.add() is being used correctly?

    >
    > I think the problem here is that you think that "List" means "List of
    > objects", whereas I think that "List" means "List, but I don't know of
    > what". Under my understanding, if you say "I have a List of String, and I
    > want to convert it to a List of something unknown", then that should be
    > fine. But if you say "I have a List of something Unknown, and I want to
    > convert it to a List of Objects", then that might not be legal, as it might
    > actually be a list of Strings.


    Aren't there specific notations for things like "List of something
    unknown"? I think it is something like List<?>. My understanding is
    that List in 1.5 is equivalent to List in 1.4. As far as I can see, I
    do not see a difference between List in 1.4 and List<Object> in 1.5.

    >
    > Sort of like casting an object of type String to be of type Object is
    > always safe (information is lost), but casting an object of type Object to
    > String is not safe (the programmer is making an assumption here which may or
    > may not be true).


    And this generates no warnings. I do not see how it supports either
    position.

    Ray

    --
    XML is the programmer's duct tape.
    Raymond DeCampo, Sep 1, 2005
    #17
  18. Oliver Wong Guest

    "Raymond DeCampo" <> wrote in message
    news:CPsRe.23269$...
    > Oliver Wong wrote:
    >> "Raymond DeCampo" <> wrote in message
    >> news:dxjRe.47664$...
    >>
    >>>The point we are trying to make is that it makes more sense (IMHO) to
    >>>emit a warning when casting a List<String> or such to a List. Then the
    >>>warning on a cast from List to List<Object> could be eliminated and your
    >>>scenario is still covered by a warning.

    >>
    >>
    >> I disagree that that would make more sense: Casting a "List<String>"
    >> to a "List" in itself cannot cause any error to occur (a conceptual error
    >> may occur later on if you try to add an arbitrary object to that list,
    >> but if the compiler could detect this, then the warning should appear
    >> where the add occurs, and not where the casting occurs).

    >
    > So should the compiler issue a warning whenever List.add() is called?
    > After all, the List may have come from a cast from List<String> (for
    > example, if a public method accepts a List parameter).


    Yes, and in fact, I believe it does:

    "Type safety: The method add(int, Object) belongs to the raw type
    LinkedList. References to generic type LinkedList<E> should be
    parameterized"

    > The whole danger starts when you throw away information by casting
    > List<String> to List. There is no ambiguity as to when that happens, so
    > it is a very good place to issue a warning.
    >
    > You say that you do not a warning when List<String> is cast to List
    > because "it cannot cause any error to occur". But in fact it is the
    > cause; just because it is not in the stack trace at runtime doesn't make
    > it any less so.


    I guess we disagree on what the cause of the error is, and I think this
    is mainly a conceptual (rather than concrete) issue, so I doubt there's any
    way to resolve this disagreement.

    >
    >> However, when you cast a "List" to a "List<Object>", this IS an error
    >> prone operation in the sense that the runtime can't actually check that
    >> your assumption is correct.

    >
    > What assumption? I'm "assuming" that I can put Objects in a List. What
    > is the difference at compile time between a List and a List<Object> (aside
    > from warnings, which is the crux of the issue here)? How is it any
    > different from not being able to check that List.add() vs.
    > List<Object>.add() is being used correctly?


    The difference between a List and a List<Object> is that you don't know
    what you can put in a List, while you know that you can put objects in
    List<Object>. I see now that the big problem here is that Java 1.5, while
    syntactically backwards compatible with 1.4, is not nescessarily
    "conceptually" backwards compatible as illustrated by this misunderstanding.
    This is addressed in the next paragraph.


    >> I think the problem here is that you think that "List" means "List of
    >> objects", whereas I think that "List" means "List, but I don't know of
    >> what". Under my understanding, if you say "I have a List of String, and I
    >> want to convert it to a List of something unknown", then that should be
    >> fine. But if you say "I have a List of something Unknown, and I want to
    >> convert it to a List of Objects", then that might not be legal, as it
    >> might actually be a list of Strings.

    >
    > Aren't there specific notations for things like "List of something
    > unknown"? I think it is something like List<?>. My understanding is that
    > List in 1.5 is equivalent to List in 1.4. As far as I can see, I do not
    > see a difference between List in 1.4 and List<Object> in 1.5.


    Yes, there does exists what are called "wildcard types", such as List<?>
    or even List<? extends Collection>, but there are restrictions on their use,
    and they serve a different purpose. You cannot, for example, actually
    instantiate an ArrayList<?> (e.g. "new ArrayList<?>") whereas you CAN
    instantiate an ArrayList (e.g. "new ArrayList()").

    I hadn't thought about it earlier, but now that you've brought it to my
    attention, I would say that a List in 1.4 is not equivalent ot a List in
    1.5. Rather, a List in 1.4 is equivalent ot a List<Object> in 1.5. And a
    List in 1.5 has no equivalent in 1.4, (nor for that matter does a List<Foo>
    in 1.5 have an equivalent in 1.4).


    >> Sort of like casting an object of type String to be of type Object is
    >> always safe (information is lost), but casting an object of type Object
    >> to String is not safe (the programmer is making an assumption here which
    >> may or may not be true).

    >
    > And this generates no warnings. I do not see how it supports either
    > position.


    The above example was to show why the operation is unsafe in the first
    place. The reason why no warnign is generated in this case is that when the
    programmer performs a downward cast (e.g. from Object to String), if the
    assumption the programmer made turns out to be incorrect, a runtime
    exception will be thrown pointing precisely at this line.

    However, in the case of generics, the type of the generic is erased at
    runtime, and so no checks can be performed. That means if the assumption the
    programmer made turns out to be incorrect, no exception will be thrown at
    all, and the program will simply behave in an undefined manner. This
    certainly warrants a warning IMO.

    Look at this program, for example. Obviously "bad things", conceptually,
    are happening there, but if you run the program, no exceptions get thrown or
    anything. Obviously, the compiler places warnings here, and for good reason
    I think.

    import java.util.ArrayList;
    import java.util.Date;

    public class Test {
    public static void main(String args[]) {
    ArrayList<String> listOfStrings = new ArrayList<String>();
    listOfStrings.add("This is a String");
    ArrayList plainList = listOfStrings;
    plainList.add(new Object());
    ArrayList<Date> listOfDates = plainList;
    listOfDates.add(new Date());
    System.out.println("If you see this, it means the program ran
    successfully with no cast errors.");
    }
    }


    - Oliver
    Oliver Wong, Sep 1, 2005
    #18
  19. Oliver Wong wrote:
    > "Raymond DeCampo" <> wrote in message
    > news:CPsRe.23269$...


    [...]

    >>What assumption? I'm "assuming" that I can put Objects in a List. What
    >>is the difference at compile time between a List and a List<Object> (aside
    >>from warnings, which is the crux of the issue here)? How is it any
    >>different from not being able to check that List.add() vs.
    >>List<Object>.add() is being used correctly?

    >
    >
    > The difference between a List and a List<Object> is that you don't know
    > what you can put in a List, while you know that you can put objects in
    > List<Object>.


    A little more precision might help. You know that in principle you can
    _safely_ put *some kind* of object in a raw List, but you don't a priori
    know *which* kind. You therefore do indeed make an assumption when you
    put any kind of object in such a list. On the other hand, you know that
    you can put Objects in a List<Object>.

    > I see now that the big problem here is that Java 1.5, while
    > syntactically backwards compatible with 1.4, is not nescessarily
    > "conceptually" backwards compatible as illustrated by this misunderstanding.


    I disagree. I think the issue is more that the type safety problem was
    so pervasive before 1.5 that many people formed incorrect
    conceptualizations. If I create a List that I intend to hold only
    Strings, then it should be regarded as a List<String> whether or not I
    have generics available with which to express the concept. It is
    certainly NOT a List<Object>, even though the compiler will not prevent
    me from accidentally treating it as one. Careful programmers writing
    without generics will document this sort of thing very clearly, which
    has many of the effects of generic declarations with regard to other
    humans reading the code. From a code analysis point of view, however,
    you cannot tell from the declaration what type an instance may contain,
    nor what types it is safe to add. This is precisely the situation that
    generics are intended to clear up.

    [Oliver wrote:]
    >>> I think the problem here is that you think that "List" means "List of
    >>>objects", whereas I think that "List" means "List, but I don't know of
    >>>what". Under my understanding, if you say "I have a List of String, and I
    >>>want to convert it to a List of something unknown", then that should be
    >>>fine. But if you say "I have a List of something Unknown, and I want to
    >>>convert it to a List of Objects", then that might not be legal, as it
    >>>might actually be a list of Strings.


    Quite right. And if I take your List of Strings and treat it as a List
    of Objects, then I might add an Integer to it. Or a plain Object. When
    you come back to check the length() of each member your program will bomb.

    >>Aren't there specific notations for things like "List of something
    >>unknown"? I think it is something like List<?>. My understanding is that
    >>List in 1.5 is equivalent to List in 1.4. As far as I can see, I do not
    >>see a difference between List in 1.4 and List<Object> in 1.5.


    Yes, a raw List is the same thing in 1.4 and 1.5. It is the only kind
    available before 1.5. Because it wouldn't have made any sense for the
    compiler to issue type safety warnings before 1.5, a raw List in 1.4 may
    seem as if it should correspond to a List<Object>, but that's not the
    case. When you write List<Object> you are asserting that it is safe to
    add any object the list, but this is in fact rarely the case, whether in
    1.4 or in 1.5, and indeed it was not the case in the OP's example. The
    raw List type corresponds most closely to List<?>, the main difference
    being that in the latter case you are explicitly stating that you don't
    know what type you can safely add to or expect to remove from the List,
    whereas in the former case that's implicit.

    > I hadn't thought about it earlier, but now that you've brought it to my
    > attention, I would say that a List in 1.4 is not equivalent ot a List in
    > 1.5. Rather, a List in 1.4 is equivalent ot a List<Object> in 1.5. And a
    > List in 1.5 has no equivalent in 1.4, (nor for that matter does a List<Foo>
    > in 1.5 have an equivalent in 1.4).


    Nope. You were going strong up to there, Oliver, but you just jumped
    the track. Raw Lists are equivalent between 1.4 and 1.5 from a class
    file standpoint, for one thing, but overall it amounts to what you can
    prove about types. In that sense, as I described above, the raw List
    type is most like List<?>.

    [...]

    > when the
    > programmer performs a downward cast (e.g. from Object to String), if the
    > assumption the programmer made turns out to be incorrect, a runtime
    > exception will be thrown pointing precisely at this line.
    >
    > However, in the case of generics, the type of the generic is erased at
    > runtime, and so no checks can be performed.


    That's perhaps a bit misleading. Type parameters are indeed subject to
    erasure, but an object always has a known, well-defined class, and
    downcasts can always be checked. It's just that the type system in Java
    1.5 has a dimension (type parameters) that the runtime ignores.

    > That means if the assumption the
    > programmer made turns out to be incorrect, no exception will be thrown at
    > all, and the program will simply behave in an undefined manner. This
    > certainly warrants a warning IMO.


    You make it sound as if there were a security problem with 1.5 JVMs
    here, and that simply is not the case. Yes, a cast from List<Object> to
    List<String> cannot by typechecked at runtime (in fact, as you say,
    there isn't actually a runtime cast at all), but when I take an object
    out and try to assign it to a String variable or invoke a String method
    on it then you can be sure that a ClassCastException will be thrown.

    I agree that the warning is merited, given that one of the stated goals
    for generics was to enable programmers to assure type safety, but
    nothing catastrophic will happen if the warning is ignored and some
    particular cast happens to be incorrect.

    --
    John Bollinger
    John C. Bollinger, Sep 3, 2005
    #19
  20. [snipped a whole bunch of things about List, List<?>, List<Object>, etc.]

    Let's boil this argument down a bit. The crux of the matter seems to be
    how we are viewing a List. My viewpoint is that a List is equivalent to
    List<Object>. They are both "lists of Objects". A List<?> is a "list
    of a specific unknown thing."

    The viewpoint of Oliver and John appears to be that a List is not
    necessarily the same as List<Object>; a List is a "list of a specific
    unknown thing" and List<Object> is a "list of objects". List<?> is a
    "list of a specific unknown thing."

    Hopefully I have the above right. As an aside, let me say that I am
    approaching this in a purely academic manner, as I have not actually
    done any real-world generics programming at this point. So I am very
    interested in the perspective of others who have done so.

    First, let us agree that these are conceptual, not practical
    differences. However, conceptual differences are important, especially
    in a case like this where information from the source code is discarded
    by the compiler.

    Here is the reasoning behind my viewpoint:
    1) List is conceptually the same between 1.4 and 1.5. This
    obviously eases the transition from 1.4 to 1.5.
    2) When dealing with a generic list like List<String>, I would
    endeavor never to cast it to a List, but always to a List<?>, List<?
    extends Foo> or List<? super Foo>. (Note that we agree on the
    conceptual definition of List<?>.) Casting it to a List throws away the
    fact that it is a generic list.

    Finally, let me say that this whole discussion really shows how Sun
    screwed up generics from an OO perspective. It is reminiscent of the
    modifiable/unmodifiable collections disaster.

    Ray

    --
    XML is the programmer's duct tape.
    Raymond DeCampo, Sep 3, 2005
    #20
    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. Dmytro Sheyko
    Replies:
    3
    Views:
    1,980
    Dmytro Sheyko
    Jan 19, 2006
  2. Ashwin Nanjappa

    Retaining *this in method chaining

    Ashwin Nanjappa, Jan 19, 2007, in forum: C++
    Replies:
    6
    Views:
    323
    Ashwin Nanjappa
    Feb 1, 2007
  3. Makoto Kuwata
    Replies:
    0
    Views:
    228
    Makoto Kuwata
    Feb 16, 2011
  4. aartist

    Method Chaining Issues

    aartist, Jun 1, 2005, in forum: Ruby
    Replies:
    25
    Views:
    276
    Hal Fulton
    Jun 3, 2005
  5. snacktime

    method chaining via symbols

    snacktime, Sep 5, 2008, in forum: Ruby
    Replies:
    2
    Views:
    108
    James Coglan
    Sep 5, 2008
Loading...

Share This Page