2

I'm trying to define and then implement an abstract setter which takes a List of Objects as a parameter. Here's the gist of this simple idea:

public abstract class MyClass {
    public abstract void setThings(List<?> things);
}

public class Bar extends MyClass {
    private List<String> things;

    @Override
    public void setThings(List<String> things) {
        this.things = things;
    }
}

That doesn't work. I get Method does not override method from its superclass and both methods have the same erasure, but neither overrides the other. I understand the latter error relating to erasures, but even so I can't figure out the correct way to do this. I've tried some others like:

public abstract <T> void setThings(List<T> things);

...as well as a few others. And I've found other questions/answers on SO that come close to addressing this, but none that have provided a solid answer (at least not that was clear to me). I've read through the tutorials as well to no avail. What am I missing?

2 Answers 2

4

So Java is quite correctly telling you that you haven't implemented the abstract method setThings which takes a List<?> not a List<T> or List<String>. All of these are different things. See this question for a detailed explanation.

The simplest solution is to introduce a generic for your abstract class as well:

public abstract class MyClass<T> {
    public abstract void setThings(List<T> things);
}

public class SubClass extends MyClass<String> {
    private List<String> things;

    public void setThings(List<String> things) {
        this.things = things;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I went with your example and it's working nicely. I'll have to spend some more time studying generics, some of the subtleties are still a bit mysterious to me such as the difference between using ?, T, `E', etc. Nothing a little (more) reading can't remedy!
2

List<?> things is a list of unknown type.

List<T> things is a list of type T.

These two things aren't the same, which is why you're getting that compilation error.

There are a couple of sensible ways to eradicate the error:

  • Generify both classes

    abstract class MyClass<T> {
        public abstract void setThings(List<T> things);
    }
    
    class Bar<T> extends MyClass<T> {
        private List<T> things;
    
        @Override
        public void setThings(List<T> things) {
            this.things = things;
        }
    }
    
  • Make Bar accept a list of unknown type as well

    abstract class MyClass {
        public abstract void setThings(List<?> things);
    }
    
    class Bar extends MyClass {
        private List<?> things;
    
        @Override
        public void setThings(List<?> things) {
            this.things = things;
        }
    }
    

1 Comment

Oops, I just forgot the abstract class modifier in my example but I do have that in my actual code. I've updated the question to reflect this. However I need a concrete type in my subclass.

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.