简体   繁体   中英

Returning a generic object on Java from abstract class

I have a class that should accept different datatypes as the second constructor parameter:

public abstract class QueryMatch {
String key;
Object input;

public <T> QueryMatch(String key, T o) {
    this.key = key;
    input = o;
}

public String getKey() {
    return key;
}

public Object getValue() {
    return input;
}
}

I don't want to use type parameters, like

public abstract class QueryMatch<T>{
String key;
T input;
...

As this way I'm getting raw types warnings when declaring retrieving QueryMatch as a generic (as I don't know the datatype it contains). But the problem is that I need to return the value and I'm not totally comfortable by returning an Object (is that just me, but it doesn't seem like a good practice?).

Additionally, another class inherits from it:

public class QueryMatchOr extends QueryMatch {
public QueryMatchOr() {
    super("title", new ArrayList<String>());
}

public void addMatch(String match) {
    ((ArrayList<String>) input).add(match);
}

}

And of course I'm getting a Unchecked cast warning (which I can avoid with @SuppressWarnings(“unchecked”)).

So, my question is... is there a better way to achieve what I'm trying to do? An abstract class that contains an object (which could be bounded), and returning the datatype it contains (instead of an Object) without using a type parameter in the class declaration?

So first, I think the best answer is to make your class generic. But if you really don't want to do this you could do something like this:

public <T> T getValue(Class<T> type) {
    return (T)input;
}

In some way you need to provide the expected type for the return value to the class. This can either be done my making that class generic or the method generic.

What you are doing is not a good design. You are using an Object type field from the superclass while you only can know it's actual (needed) type in the subclass. If you only know that in the subclass, declare that variable in the subclass. Not even to mention that your fields are not private.

How about:

public abstract class QueryMatch {

    private String key;

    public QueryMatch(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public abstract void addMatch(String match);
}


public class QueryMatchOr extends QueryMatch {

    private ArrayList<String> input;

    public QueryMatchOr() {
        super("title");
        input = new ArrayList<String>();
    }

    public void addMatch(String match) {
        input.add(match);
    }
}

If you need the getValue() method in the superclass, you really should make it generic:

public abstract class QueryMatch<T> {

    private String key;

    public QueryMatch(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public abstract void addMatch(String match);

    public abstract T getValue();
}


public class QueryMatchOr extends QueryMatch<ArrayList<String>> {

    private ArrayList<String> input;

    public QueryMatchOr() {
        super("title");
        input = new ArrayList<String>();
    }

    public void addMatch(String match) {
        input.add(match);
    }

    public ArrayList<String> getValue(String match) {
        input;
    }
}

So, my question is... is there a better way to achieve what I'm trying to do?

No, there isn't.

I think you should use generics instead of @SuppressWarnings(“unchecked”))

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