繁体   English   中英

Java:在此设计中使用泛型的替代方法是什么?

[英]Java: What is an alternative to using generics in this design?

我正在开发一个开放源Java库,该库将允许人们计算具有一定数量值的属性的某些数量,例如Gini索引。 (从形式上讲,它计算与属性A关联的离散分布的基尼系数,但这与此处无关。)

例如,一个人将能够执行以下操作

String[] namesArray = {"primary_school", "high_school", "university"};
Calculator<String> calc =new Calculator<String>(namesArray);

// p.getEducationLevel() returns `"primary_school"`, `"high_school"`, or `"university"`.
for (Person p : peopleCollection) {
    calc.increment(p.getEducationLevel());
}

// e.g. the Gini index of the distribution
double currentStat = calc.getCurrentValue();

这个想法是允许库的用户使用他们自己的类型来引用属性值。 在这种情况下,我正在使用字符串(例如"primary_school" )。 但是我可能要使用整数,甚至是我自己的AttributeValue类型。

我通过定义解决

public class Calculator<T> {
    /* ... */
}

但是,使用泛型会在实现过程中引起一些问题:例如,如果我想维护类型对(T, double)的集合,则必须进行讨厌的类型转换:

public class Calculator<T>
        /* ... */
        private Queue<StreamElement<T>> slidingWindow;
        /* ... */
        class StreamElement<T> {
                private T label;
                private double value;

                StreamElement(T label, double value) {
                        this.label = label;
                        this.value = value;
                }

                public T getLabel() {
                        return label;
                }
                public double getValue() {
                        return value;
                }
        }
        /* ... */
            slidingWindow.add(new StreamElement<T>(label, value));
            if (slidingWindow.size() > windowSize) {
                    StreamElement lastElement = slidingWindow.remove();
                    // XXX: Nasty type cast
                    decrement((T)lastElement.getLabel(), lastElement.getValue());
            }
        /* ... */
}

这是javac产生的警告:

Calculator.java:163: warning: [unchecked] unchecked cast
            decrement((T)lastElement.getLabel(), lastElement.getValue());
                                             ^
  required: T
  found:    Object
  where T is a type-variable:
    T extends Object declared in class Calculator
1 warning

更新。 如果我不进行类型转换,我会得到

Calculator.java:163: error: no suitable method found for decrement(Object,double)
            decrement(lastElement.getLabel(), lastElement.getValue());
            ^
    method Calculator.decrement(T) is not applicable
      (actual and formal argument lists differ in length)
    method Calculator.decrement(T,double) is not applicable
      (actual argument Object cannot be converted to T by method invocation conversion)
  where T is a type-variable:
    T extends Object declared in class Calculator
1 error

问题:

  • 进行类型转换的正确,干净的方法是什么?
  • 在这里使用泛型的替代方法是什么?
  • 更具体地说,最好是定义一个可以将用户扩展到MyLabel然后使用MyLabel作为属性值的Label类吗? 这意味着Calculator将不再是通用类型; 在实现中,我们将使用class StreamElement { Label label; /* ... */ } class StreamElement { Label label; /* ... */ }等。

我认为您刚刚犯了一些错误。

这是正确的实现:

        /* ... */
            slidingWindow.add(new StreamElement<T>(label, value));
            if (slidingWindow.size() > windowSize) {
                    // Don't forget the generic argument at StreamElement
                    StreamElement<T> lastElement = slidingWindow.remove();
                    decrement(lastElement.getLabel(), lastElement.getValue());
            }
        /* ... */

暂无
暂无

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

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