简体   繁体   中英

How to return different types in a method using generics?

I want to return different class types in java using generics, But there is a mistake.

These return values have their unique filed, so i don't want to use their parent class as a return type.

Here is the code:

public class Client {
    public static void main(String[] args) {
        Client c = new Client();
        A a = c.gets(1);
        System.out.println(a.aFiled);
        B b = c.gets(2);
        System.out.println(b.bFiled);
    }


    public <T extends Root> T gets(int type) {
        switch (type) {
            case 1:
                return new A();
            case 2:
                return new B();
            default:
                throw new RuntimeException();
        }
    }


    class Root {
        String name;
    }

    class A extends Root {
        int aFiled;
    }

    class B extends Root {
        int bFiled;
    }
}


The error occurs inside switch

"incompatible types"
Required: T
Found: Client.A

I mean to return someclass extends Root , I don't know why it is wrong.
I'd appreciate it if someone could explain it to me.

In generic methods, the type is inferred by the compiler using the actual arguments. But your argument doesn't have any type T. You can send another parameter Class<T> to tell the type of the return value:

public <T extends Root> T gets(int type, Class<T> c) {
    switch (type) {
        case 1:
            return c.cast(new A());
        case 2:
            return c.cast(new B());
        default:
            throw new RuntimeException();
    }
}

But in your case you don't know the type before you call this method.

So all you can do is make this method non-generic and change return type to just Root . Then you can do instanceof check to identify the class, perform casting, and then get the relevant fields.

It doesn't make sense to make this method generic anyway, because generic methods can work with different type of supplied data. But in your case it's always an int . So I would say your method is not really generic .

The method indicates that there is a T that extends Root which is the return type. However, until the method is used somewhere, you don't know which class that is. You don't know if T will be A, or B, or something else. Each time it is used it will be exactly one subclass of Root.

But here your code is assuming it will be both A and B at the same time. In fact, T might be neither. If T is A, you cannot return an instance of B. If T is B, you cannot return an instance of A. If T is neither A nor B, you cannot return either an instance of A or B.

You have to return an instance of T.

One thing you can do is not use generics and just return Root.

You can modify your method as below by casting to T.

    public <T extends Root> T gets(int type) {
        switch (type) {
            case 1:
                return (T) new A();
            case 2:
                return (T) new B();
            default:
                throw new RuntimeException();
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM