unchecked conversion problem

Discussion in 'Java' started by rschmid-google@raptor.net, Oct 25, 2006.

  1. Guest

    I have finally been allowed to upgrade to Java5 and I just finished
    fixing some 1200 parameterization warnings which has really improved
    the code. I have one, ONE, left and I'm not sure it can be fixed.

    I have the following object heierarchy;

    SourceMatch
    CMatch extends SourceMatch
    DMatch extends SourceMatch

    SMatchService<T extends SourceMatch>
    CMatchService extends SMatchService<CMatch>
    DMatchService extends SMatchService<DMatch>

    in SMatchService is the following method

    public abstract List<T> getMatchingSources(args) {}

    which is implemented in the subclass services thus;

    public List<CMatch> getMatchingSources(args) {}

    and

    public List<DMatch> getMatchingSources(args) {}

    yet the following code throws an unchecked conversion warning;

    SMatchService sourceMatchService = null;
    if (c) sourceMatchService = new CMatchService();
    else if (d) sourceMatchService = new DMatchService();

    List<SourceMatch> sourceList = =
    sourceMatchService.getMatchingSources(args);

    I have tried using wildcard parameters but my understanding is
    imperfect at best.

    I suspect that the problem is really architectural but I wanted to find
    out if there is a way to make this work.

    Any help is appreciated.
    , Oct 25, 2006
    #1
    1. Advertising

  2. On 2006-10-25 19:05, wrote:
    :
    > yet the following code throws an unchecked conversion warning;
    >
    > SMatchService sourceMatchService = null;
    > if (c) sourceMatchService = new CMatchService();
    > else if (d) sourceMatchService = new DMatchService();
    >
    > List<SourceMatch> sourceList = =
    > sourceMatchService.getMatchingSources(args);


    Try this:

    SMatchService<?> sourceMatchService = null;
    if (c) sourceMatchService = new CMatchService();
    else if (d) sourceMatchService = new DMatchService();

    List<? extends SourceMatch> sourceList =
    sourceMatchService.getMatchingSources(args);

    -- Niklas Matthies
    Niklas Matthies, Oct 25, 2006
    #2
    1. Advertising

  3. "" <> writes:

    > yet the following code throws an unchecked conversion warning;
    >
    > SMatchService sourceMatchService = null;


    Here SMatchService lacks a type parameter. Try:
    SMatchService<? extends SourceMatch> sourceMatchService = null;

    > if (c) sourceMatchService = new CMatchService();
    > else if (d) sourceMatchService = new DMatchService();
    >
    > List<SourceMatch> sourceList = =
    > sourceMatchService.getMatchingSources(args);


    And here the list you get will be:
    List<? extends SourceMatch> sourceList =
    sourceMatchService.getMatchingSources(args);

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, Oct 25, 2006
    #3
  4. Guest

    Niklas Matthies wrote:
    > On 2006-10-25 19:05, wrote:
    > :
    > > yet the following code throws an unchecked conversion warning;
    > >
    > > SMatchService sourceMatchService = null;
    > > if (c) sourceMatchService = new CMatchService();
    > > else if (d) sourceMatchService = new DMatchService();
    > >
    > > List<SourceMatch> sourceList = =
    > > sourceMatchService.getMatchingSources(args);

    >
    > Try this:
    >
    > SMatchService<?> sourceMatchService = null;
    > if (c) sourceMatchService = new CMatchService();
    > else if (d) sourceMatchService = new DMatchService();
    >
    > List<? extends SourceMatch> sourceList =
    > sourceMatchService.getMatchingSources(args);
    >
    > -- Niklas Matthies


    Great! Except now;

    sourceList = new ArrayList<SourceMatch>();
    sourceList.add(new SourceMatch());

    throws an error.

    I can work around this by creating a new list and copying one into the
    other but that is wasteful. What's the right syntax?
    , Oct 25, 2006
    #4
  5. On 2006-10-25 21:18, wrote:
    > Niklas Matthies wrote:

    :
    >> List<? extends SourceMatch> sourceList =
    >> sourceMatchService.getMatchingSources(args);

    :
    > Great! Except now;
    >
    > sourceList = new ArrayList<SourceMatch>();
    > sourceList.add(new SourceMatch());
    >
    > throws an error.
    >
    > I can work around this by creating a new list and copying one into
    > the other but that is wasteful. What's the right syntax?


    You need to use a second variable declared with a different type:

    List<SourceMatch> sourceList2 = new ArrayList<SourceMatch>();
    sourceList2.add(new SourceMatch());

    List<SourceMatch> means that the list can contain _any_ instances
    of SourceMath. List<? extends SourceMatch> on the other hand means
    that the list can contain only instances of _some specific_ (but
    unspecified) subtype of SourceMatch. The '?' might actually be
    SourceMatch itself, but it also might be CMatch or DMatch. That's
    why the compiler doesn't allow you to add an arbitrary SourceMatch
    instance to such a list, because the list could for example really be
    a List<CMatch>, to which it's only permissible to add CMatch objects.
    Consider:

    List<CMatch> cList = new ArrayList<CMatch>();
    List<? extends SourceMatch> sourceList = cList; // fine
    sourceList.add(new SourceMatch()); // (*)
    // oops, now cList contains a SourceMatch object although
    // it is a List<CMatch>!
    CMatch cMatch = cList.get(i); // throws ClassCastException!

    That's why the line (*) is rejected by the typechecker.

    To get a better understanding of generics I suggest you take a look
    at http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html .

    -- Niklas Matthies
    Niklas Matthies, Oct 26, 2006
    #5
  6. "" <> writes:

    > Niklas Matthies wrote:
    >> List<? extends SourceMatch> sourceList =
    >> sourceMatchService.getMatchingSources(args);

    >
    > Great! Except now;
    >
    > sourceList = new ArrayList<SourceMatch>();
    > sourceList.add(new SourceMatch());
    >
    > throws an error.


    As it should. ArrayList<SourceMatch> is not assignable to
    List<? extends SourceMatch>.

    You can do
    sourceList = new ArrayList<? extends SourceMatch>();
    but you can't add a SourceMatch to that (or anything at all).

    Remember, a List<SourceMatch> and a List<CMatch> are not assignable
    to each other. The former allows you to put SourceMatch'es into it,
    the latter doesn't. And the latter guarantees that what you take
    out of it is a CMatch, the former doesn't.

    If you want a variable to hold both of the above list types, it
    needs to be something like List<? extends SourceMatch> (which is
    a supertype of both). However, you cannot add elements to that list,
    since it might be both a List<CMatch> or a List<DMatch>, which cannot
    contain the same elements.

    Instead, you could just let the getMatchingSources return a
    List<SourceMatch>.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, Oct 26, 2006
    #6
  7. Guest

    Lasse Reichstein Nielsen wrote:
    > "" <> writes:
    >
    > > Niklas Matthies wrote:
    > >> List<? extends SourceMatch> sourceList =
    > >> sourceMatchService.getMatchingSources(args);

    > >
    > > Great! Except now;
    > >
    > > sourceList = new ArrayList<SourceMatch>();
    > > sourceList.add(new SourceMatch());
    > >
    > > throws an error.

    >
    > As it should. ArrayList<SourceMatch> is not assignable to
    > List<? extends SourceMatch>.
    >
    > You can do
    > sourceList = new ArrayList<? extends SourceMatch>();
    > but you can't add a SourceMatch to that (or anything at all).
    >
    > Remember, a List<SourceMatch> and a List<CMatch> are not assignable
    > to each other. The former allows you to put SourceMatch'es into it,
    > the latter doesn't. And the latter guarantees that what you take
    > out of it is a CMatch, the former doesn't.
    >
    > If you want a variable to hold both of the above list types, it
    > needs to be something like List<? extends SourceMatch> (which is
    > a supertype of both). However, you cannot add elements to that list,
    > since it might be both a List<CMatch> or a List<DMatch>, which cannot
    > contain the same elements.
    >


    Ah, Thank you! That was the point I had forgotten. Once I understood
    it became obvious that I could move the actual code into a new
    parameterized method in SourceMatch.
    , Oct 26, 2006
    #7
    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. Claire
    Replies:
    3
    Views:
    4,806
    Wendy Smoak
    Mar 2, 2005
  2. Michel T.
    Replies:
    14
    Views:
    878
    John Ersatznom
    Jan 18, 2007
  3. RVic
    Replies:
    19
    Views:
    1,368
  4. Claire
    Replies:
    4
    Views:
    210
    Claire
    Mar 2, 2005
  5. Jens
    Replies:
    32
    Views:
    853
    Arne Vajhøj
    Jun 21, 2012
Loading...

Share This Page