通用OR代替AND <t extends =“”number =“”| =“”charsequence =“”> </t>

时间:2011-11-30 17:36:27

标签: java android generics types charsequence

是否可以对接受EEEER ClassA或InterfaceB的方法进行一般参数化?

由于|而无法编译伪代码

public <T extends Number | CharSequence> void orDoer(T someData){ // ... }

即。而不是编写多个方法签名,我希望这一个方法接受Number或CharSequence作为参数

应使用数字或CharSequence参数传递

orDoer(new Integer(6));
int somePrimitive = 4;
orDoer(somePrimitive);
orDoer("a string of chars");

3 个答案:

答案 0 :(得分:18)

如果真的想要这样做,您需要将自己接受的类包装在自己的自定义类中。在您的示例中,可能类似于:

public class OrDoerElement {
    private final Number numberValue;
    private final CharSequence charSequenceValue;

    private OrDoerElement(Number number, CharSequence charSequence) {
        this.numberValue = number;
        this.charSequenceValue = charSequence;
    }

    public static OrDoerElement fromCharSequence(CharSequence value) {
        return new OrDoerElement(null, value);
    }

    public static OrDoerElement fromNumber(Number value) {
        return new OrDoerElement(value, null);
    }
}

您的orDoer方法变为:

public void orDoer(OrDoerElement someData) { .... }

然后你可以使用以下任一方法构建其中一个并在你的方法中使用:

orDoer(OrDoerElement.fromCharSequence("a string of chars"));
orDoer(OrDoerElement.fromNumber(new Integer(6)));

但老实说,这听起来有点过于复杂,太多工作只是为了能够调用具有不同参数类型的方法。您确定使用两种方法无法实现相同的目标吗?第三种方法是通用逻辑吗?

答案 1 :(得分:1)

使用匿名抽象类是一个选项吗?当我需要类型安全参数或返回类型时,我使用下面代码的一些变体。话虽如此,我同意这里的其他评论,并且很好奇当你为一组没有那么多共同点的对象强制执行类型安全时,你真正获得了什么好处。

public abstract class Doer<T> {

  public void do(T obj) {
    // do some stuff. 
  }

}

// calling method

new Doer<Number>(){}.do(new Integer(5));

答案 2 :(得分:0)

对于原始问题:

public void orDoer(Object someData){
    assert someData instanceof Number || someData instanceof CharSequence;

    // ...
}

在您更具体的情况下,assert语句仅应使用内省来阐明对象是否具有所需的细节,即检查String中的构造函数,并探查从中创建对象的新实例。 toString()传入对象的结果,并比较两者是否相等:

public void orDoer(Object someData) {
    assert isUniconstructable(someData);
}

public static boolean isUniconstructable(Object object) {
    try {
        return object.equals(object.getClass().getConstructor(String.class)
            .newInstance(object.toString()));
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException
            | NoSuchMethodException| RuntimeException e) {
        return false;
    }
}

(由于可能会引发异常,因此我们需要将assert测试包装到其自己的函数中。)

请注意,由于Android的ProGuard代码压缩会重写类名,因此内省可能会中断,并且其中的类(即YourClass而不是Q会存储在其中数据库,并且当您想要使用具有更多类的更高版本的应用来还原数据库时,类Q则有所不同。有关更多信息,请访问ProGuard网站。我只是想通知您,在Android上使用内省时应该注意这一点。