0

I'm having a weird issue here it seems. I have an interface, known as Sortable. I then have another class, like so:

public class LeftSort {

    private List<Sortable> list;

    public <T extends Sortable> LeftSort(List<T> list) {
        this.list = list;
    }

}

However when I go to make another class, called Foo, like so:

public class Foo implements Sortable {}

When doing the following in a JUnit test:

List<Foo> list = new ArrayList<Foo>();
// Initialise... blah blah.

LeftSort sorter = new LeftSort(list);

I receive the following error:

The constructor LeftSort(List<Foo>) is undefined.

I swear you're able to use interfaces in generics like I have done so. Is there anything I've done wrong here?

I've also messed around with doing private List<? extends Sortable> list; too but to no avail.

Edit: Please make note in the future to check which class your actually importing prior to complaining like me. I simply had the wrong class imported (Foo is just the name I gave it online, it was actually Test that I so smartly decided to use...)

3 Answers3

2

Note that your constructor doesn't compile actually:

public <T extends Sortable> LeftSort(List<T> list) {
    this.list = list;
}

To accept any subclass of Sortable, use the Upper Bounded Wildcard<? extends Sortable> :

public class LeftSort {

    private List<? extends Sortable> list;

    public LeftSort(List<? extends Sortable> list) {
        this.list = list;
    }

}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Hmm... This still seems to give me the same error. –  Jan 19 '18 at 13:53
  • I think that you have another issue so.Try to post all relevant code to understand the problem. – davidxxx Jan 19 '18 at 13:55
  • No, no, I just realised. Such an idiot... I had the wrong class imported because it's a JUnit test file and my real class was "Test", which has the same name.... Thankyou for your time. –  Jan 19 '18 at 13:56
  • 1
    It was an issue finally :) Great for you. You are welcome :) – davidxxx Jan 19 '18 at 14:33
1

Usually the generic type is defined for the whole class as shown below:

public class LeftSort<T extends Sortable> {
    private List<T> list;
    public LeftSort(List<T> list) {
        this.list = list;
    }
}

This way you can instantiate LeftSort with new ListSort<>(list) (assuming you're using Java 7+).

C-Otto
  • 5,615
  • 3
  • 29
  • 62
1

That's not the error I get when I try to compile it:

Main.java:13: error: incompatible types: List<T> cannot be converted to List<Sortable>
        this.list = list;
                    ^
  where T is a type-variable:
    T extends Sortable declared in constructor <T>LeftSort(List<T>)
1 error

Which is what I'd expect, because a List<? extends Sortable> isn't a List<Sortable>.

You'd have to take a defensive copy of the list:

this.list = new ArrayList<>(list);

Or make the list field of a bounded type:

private List<? extends Sortable> list;
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Ah pardon, my Eclipse isn't immediately telling me the error and I've done it wrong. However the other class still throws me the error when trying to instantiate... –  Jan 19 '18 at 13:53
  • OH MY GOD! I HAD THE WRONG CLASS IMPORTED –  Jan 19 '18 at 13:55
  • I thankyou for your help nonetheless Andy and for time wasted. I've checked the question to be closed because while your answers still very much answer a failure in my question, the whole thing shouldn't of been posed in the first place. –  Jan 19 '18 at 13:59