繁体   English   中英

返回类型通用

[英]Return type generic

我正在学习在Java中使用泛型,并且我需要以下函数(在具有泛型属性的类中才能工作:

public T evaluate() {
    if (arg.getValue() instanceof Boolean) {
        return !arg.getValue();
    } else if (arg.getValue() instanceof Integer) {
        return -arg.getValue();
    }
}

该类具有类型为Expression的属性arg。 arg.getValue返回类型T的变量。如果T是布尔值,则函数评估应返回arg.getValue的逻辑取反,如果T是整数则返回-arg.getValue的逻辑取反。 它不会编译,因为-和! 运算符“不能应用于T”。

另一个选择是实现以下想法:

public T evaluate() {
    if (arg.getValue() instanceof Boolean) {
        Boolean b = (Boolean) arg.getValue();
        Boolean r = new Boolean(!b);
        return r;
    } else if (arg.getValue() instanceof Integer) {
        Integer i = (Integer) arg.getValue();
        Integer r = -i;
        return r;
    }
}

但是这样返回就不起作用:“必需的不兼容类型:T找到:java.lang.Boolean / Integer”

有任何想法吗?

那不是它的工作原理。 泛型类型并不意味着“我不知道我将返回什么,我们将根据所得到的来查看,这可能是依赖于实现的列表中的任何内容”。 T类型可能是变量,但是仅在实现时-运行时,它是固定的,可以是BooleanInteger

所以你可以做的是

public interface Inverter<T> {
    // variable return type, depending on argument
    T invert(T toInvert);
}

与实施

class IntegerInverter implements Inverter<Integer> {
    // return type is fixed to integer
    Integer invert(Integer toInvert) {
        return -toInvert.intValue();
    }
}

class BooleanInverter implements Inverter<Boolean> {
    // return type is fixed to boolean
    Boolean invert(Boolean toInvert) {
        return !toInvert.booleanValue();
    }
}

注意,最好重用现有接口,例如

UnaryOperator<Integer> intInverter = i -> -i.intValue();
UnaryOperator<Boolean> boolInverter = b -> !b.booleanValue();

编辑:@Twometer的建议将导致类似

class Inverters {
    public static UnaryOperator<Integer> integerInverter() {
        return i -> -i.intValue();
    }
    public static UnaryOperator<Boolean> boolInverter() {
        return b -> !b.booleanValue();
    }

    // and maybe even this, but this will still require a cast
    // at the client
    public static <T> UnaryOperator<?> inverter(Class<T> clazz) {
        if (clazz == Integer.class) {
            return integerInverter();
        } else if (clazz == Boolean.class) {
            return boolInverter();
        }
        throw new IllegalArgumentException(String.format("Cannot create inverter for class %s", clazz));
    }
}

这样,您就可以集中获得所需的逆变器。 这样,您确定它们将被重用。 此外,您可以缓存创建的lambda,而不必更改客户端代码。

仅当要区分的两个类具有(有用的)公共超类时,泛型才有帮助。 但是, BooleanInteger的第一个通用超类是Object ,它没有用。

如果您的目标是学习泛型,我建议使用例如 IntegerDouble两者,它们确实具有共同的子类Number ,因此您可以将T定义为T extends Number

如果您的目标与您的示例完全相同,则可以按照@daniu的回答进行操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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