3

I have this problem, I'd like to return a list of interface and implementation class only after the if block.

public interface Lotto { }

public class LottoImplSecond implements Lotto { }
public class LottoImplFirst implements Lotto { }

public class MyClass {
   public List<Lotto> getLotto(Integer number){
       if(number==1) List<Lotto> listaLotto=new ArrayList<LottoImplFirst>();
       else if(number==2) List<Lotto> listaLotto=new ArrayList<LottoImplSecond>();
   return listaLotto;
}
Shinigami
  • 1,015
  • 2
  • 15
  • 23

7 Answers7

12
public interface Lotto { }

public class LottoImplSecond implements Lotto { }
public class LottoImplFirst implements Lotto { }

public class MyClass {
   public List<? extends Lotto> getLotto(Integer number){
       List<? extends Lotto> listaLotto;
       if(number==1) listaLotto=new ArrayList<LottoImplFirst>();
       else if(numeber==1) listaLotto=new ArrayList<LottoImplSecond>();
       return listaLotto;
    }
}
pap
  • 27,064
  • 6
  • 41
  • 46
  • 5
    Please note that the wildcard type is resolved by the call site and not by the callee. This makes the whole construct completely useless, even if it compiles. The caller will just have to deal with the capturing of `?`, getting **zero** benefits in return. So I'd consider this bad advice for OP. – Marko Topolnik Aug 21 '12 at 08:56
  • 1
    In fact there may be a minor benefit to your signature (but only if that's what OP wants): the compiler will disallow calls to any `List` methods that involve an argument of the generic type, such as `add`. – Marko Topolnik Aug 21 '12 at 09:05
  • The question is: why do you want to return an `ArrayList` in one case and an `ArrayList` in the other case if the caller won't know which one he gets anyway. Are you sure you shouldn't just return a `new ArrayList()` in both cases? – herman Aug 21 '12 at 11:22
  • @herman Because each Lotto (first and second) has different mysql db path. Instead the behavior is the same – Shinigami Sep 01 '12 at 07:04
4

First List<Lotto> is not a supertype of List<LottoImplSecond> or List<LottoImplFirst> so you need to return a List<? extends Lotto>

The problem with the list List<? extends Lotto> is that you can only get from it and never add to it (safely, without a compiler warning)

dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
2

If you return List<Lotto>, it doesn't matter if inside you use a specific type or not, and actually, you can't do it, as ArrayList<LottoImplFirst> is NOT a subclass of List<Lotto>. You can actually do:

public List<Lotto> getLotto(Integer number){
   return new ArrayList<Lotto>();
}

(Also note that you declared the variables (listaLotto) inside the if-else statement, so the return statement is out of scope for them.

MByD
  • 135,866
  • 28
  • 264
  • 277
2

Your lines

if(number==1) List<Lotto> listaLotto=new ArrayList<LottoImplFirst>();
else if(numeber==1) List<Lotto> listaLotto=new ArrayList<LottoImplSecond>();

are achieving nothing as far as the code that calls your method is concerned. Those two lists are absolutely indistinguishable for your caller. I suggest you to just write

listaLotto = new ArrayList<Lotto>();

Adapt the return type accordingly and be done with it.

A side note: your code is not compilable Java, but it is a minor point.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • @AmitD If that's OP's real method, with no further code, then you are absolutely right. However, due to the compiler errors in that sample, it looks to me like simplified code for the sake of the question. – Marko Topolnik Aug 21 '12 at 09:09
0

Condition is same in both if and else. Generics inheritance is different than Java inheritance.

 public List<Lotto> getLotto(Integer number)
{
    return ((List<Lotto>)(number == 1 ? new ArrayList<LottoImplFirst>() : new ArrayList<LottoImplSecond>());
}
Amit Deshpande
  • 19,001
  • 4
  • 46
  • 72
0

There are a number of mistakes in your code, but I think what you want to do is change the getLotto method signature to:

public List<? extends Lotto> getLotto(Integer number);

You'll have to define listaLotto outside of the if statement too, so that it is still in scope when you try and return it.

Also note that there's a typo on the else if condition - I presume it should test if number == 1, although at present this will never execute as the original if condition tests if number == 1 also.

The complete solution (assuming the second value is 2) is something like the following:

public interface Lotto { }

public class LottoImplSecond implements Lotto { }
public class LottoImplFirst implements Lotto { }

public class MyClass {
   public List<? extends Lotto> getLotto(Integer number){
       List<? extends Lotto> listaLotto;
       if(number==1) {
            listaLotto=new ArrayList<LottoImplFirst>();
       }
       else if(number==2) {
            listaLotto=new ArrayList<LottoImplSecond>();
       }
       return listaLotto;
    }
}
Edd
  • 3,724
  • 3
  • 26
  • 33
0

Try this. I just compiled it:

class MyClass {
   public List<? extends Lotto> getLotto(Integer number){

       List<? extends Lotto> listaLotto = null; 

       if(number==1) {
           listaLotto= new ArrayList<LottoImplFirst>();
       }           
       else if(number ==1) {
           listaLotto=new ArrayList<LottoImplSecond>();
       }
   return listaLotto;
}
}
Santosh
  • 17,667
  • 4
  • 54
  • 79