The difference between using wildcards in Java and declaring generic types in abstract methods

I tried to understand generic types in Java, which seemed understandable in theory, but I encountered problems when I needed to apply it to real code I want to declare an abstract method that will return a generic type Let's assume that I have an empty interface called magic, which is implemented by two classes: magic and witch

/*1*/protected abstract <T extends Magicable> List<T> getMagicables();
/*2*/protected abstract List<? extends Magicable> getMagicables();
/*3*/protected abstract List<Magicable> getMagicables();

>In the first case, when I want to implement the body of this method in a class that extends an abstract class, I encounter a problem:

@Override
protected List<Magican> getMagicable() {..}

I have a warning message:

>In the second case, I don't have this warning, but I have a problem in the abstract class. I declare the abstract method above:

public void <T extends Magicable> T getOneFromList() {
      List<T> list = getMagicables();
      //.....
  }

In this case, I have a compilation error in the getmagicables() call:

>The third case causes compilation errors at the above two code locations In my case, I don't think it's solved correctly

Solution

Simply declare your method:

@Override
    protected <T extends Magicable> List<T> getMagicables() {
       List<T> list = ...
       return list
    }

If you really want this:

@Override
    protected List<Magican> getMagicable() {..}

You may have to declare the generic t as a class definition

public abstract class AbstractKlass<T extends Magicable> {
        protected abstract List<T> getMagicables();
     }

Then in your subclass:

public class MySubClass extends AbstractKlass<Magican> {

        @Override
        protected List<Magican> getMagicables() {
           ...
        }
     }

Compilation errors are normal because from the signature of a method means that you don't care about the contents of the list, from the moment you can treat these elements as magic On the phone

List<T> list = getMagicables();

You want to take care of type T without knowing it In other words, there are three use cases: t is magic (OK), t is a magician (error, because getmagic may return the witch list), and t is Witch (also wrong)

Because list < magician > is list & lt;? The subtype of extends magic > but is not a subtype of list < magic > This is useful for method parameters

public void doIt(List<? extends Magicable> list) {
         // you can't add a Magician here
    }

Can be used as

List<Witch> list = ...
    doIt(list);

But if you have

public void doIt(List<Magicable> list) {
         // you can add a Magician here
    }

You can't use it

List<Witch> list = ...
    doIt(list); // compile error
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>