1

I have this following interface :

    public interface FruitDetails {
            public String getFruitName(); 
    }

And few Classes that implements the above interface :

    public class Banana implements FruitDetails{

        private int index;
            public Banana(int i) {
                index = i;
        }

        @Override
        public String getFruitName() {
            return "Banana Fruit " + index;
        }

    }

and

    public class Apple implements FruitDetails{

        private int index;
            public Apple(int i) {
                index = i;
        }

        @Override
        public String getFruitName() {
            return "AppleFruit " + index;
        }

    }

I have a function that prints the details of the fruits :

    static void getFruitDetails(List<FruitDetails> fruits) {
            for (FruitDetails fruitDetails : fruits) {
                    System.out.println(fruitDetails.getFruitName());
            }
    }

Now i will create a list of Bananas :

  List<Banana> bananaList = new ArrayList<Banana>();
  bananaList.add(new Banana(0));
  bananaList.add(new Banana(1));

Now i want to print Details of bananas in the above list using getFruitDetails.

Issue is if try to call

  getFruitDetails(bananaList);

I am getting compile time error :

The method getFruitDetails(List<FruitDetails>) in the type MainClass is not applicable for the arguments (List<Banana>)

How I can resolve this.

And also need to define getFruitDetails such that i should be able to print details of banana list or apple list

1
  • Maybe it's my OCD but it would be great if the interface was called Fruit instead of FruitDetails :-) Commented Jan 20, 2012 at 7:49

2 Answers 2

5

To accept all implementing classes of FruitDetails as the argument for getFruitDetails, you need to use the type List<? extends FruitDetails>:

static void getFruitDetails(List<? extends FruitDetails> fruits) {
        for (FruitDetails fruitDetails : fruits) {
                System.out.println(fruitDetails.getFruitName());
        }
}

As a side effect this makes the List fruits in getFruitDetails effectively read only for the reason that JB Nizet describes in the comments.

Sign up to request clarification or add additional context in comments.

4 Comments

Just to explain (once again): If a List<Banana> was a List<Fruit>, you could add an Apple to the list, and it would thus break the type-safety of the list.
But I have FruitDetails as an interface.
this is correct. Sorry i was under the impression that as FruitDetails was a interface, expression "? extends FruitDetails" should be "? implements FruitDetails" which was giving error. Also can i know how this works.
@Pavan: in generics, type bounds are expressed using extends and super regardless of whether the type happens to be a class or interface (or, even a type variable, in which case we don't know whether it is a class or interface)
1

This is because you can not assign List<Banana> to List<FruitDetails>. Try changing the code to

static void getFruitDetails(List<? extends FruitDetails> fruits) {
        for (FruitDetails fruitDetails : fruits) {
                System.out.println(fruitDetails.getFruitName());
        }
}

you should read about generics subtyping to understand this.

1 Comment

Again FruitDetails is not a Baseclass. Its an interface

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.