0

这是一种类似于您可能见过的其他 JPA BaseEntity 模式的设计:

@MappedSuperclass()
public abstract class Entity<X extends Entity<X>>
    implements
        Comparable<X>,
        Serializable
{
    private static final long serialVersionUID = 1L;
    private Long id;
    private Date timeStamp;

...

    //  Simply compare fields in subclass until difference is discovered
    private int compareSubclassFields(X that)
    {
        int result = 0;
        for(Comparator<X> comparator : getComparators())
        {
            result = comparator.compare(this,that); <<=== compilation error
            if(result != 0) { break; }
        }
        return result;
    }

    /**
     *  Entity subclasses provide a list of their own special
     *  comparators that can contribute to the comparison.
     */
    protected abstract List<Comparator<X>> getComparators();
}

下面是一个扩展 Entity 的类的例子:

public class User extends Entity<User>
{
    private static final long serialVersionUID = 1L;
    private String firstName;
    private String lastName;
    private String email;

...

    @Override
    public List<Comparator<User>> getComparators()
    {
        List<Comparator<User>> result =
            new ArrayList<Comparator<User>>();

        result.add(getLastNameComparator()); //  Sort first on last name
        result.add(getFirstNameComparator());//  Next, by first name
        result.add(getEmailComparator());    //  Finally, by email (unique)
        return result;
    }
}

当我编译时,我收到以下错误:

error: method compare in interface Comparator<T> cannot be 
       applied to given types;

        result = comparator.compare(this,that);
                                    ^
required: X,X
found: Entity<X>,X
reason: actual argument Entity<X> cannot be converted to
        X by method invocation conversion

where X,T are type-variables:
  X extends Entity<X> declared in class Entity
  T extends Object declared in interface Comparator

阅读Java Enum Definition,特别是它所说的部分,

public class StatusCode extends Enum<StatusCode>

现在,如果您检查约束,我们得到了 Enum - 所以 E=StatusCode。让我们检查一下:E 是否扩展了 Enum?是的!我们没事。

我假设在我的示例中,其中X extends Entity<X>'this' 将是Userand not的一个实例Entity<User>。此外,由于 Entity 是一个抽象类,它必须被扩展,因此compareNonIdFields只能由 X 的实例调用——在它自身上。当然,当我施放时,我会收到未经检查的警告:

warning: [unchecked] unchecked cast
        result = comparator.compare(((X)this),that);
                                        ^
required: X
found:    Entity<X>
where X is a type-variable:
  X extends Entity<X> declared in class Entity
1 warning

关于为什么这种递归通用用法会导致编译错误以及使未经检查的强制转换警告消失的解决方案的想法将不胜感激。

4

3 回答 3

2

您正在课堂this内编写关键字。Entity<X>所以,

这 = 实体<X>

另一方面,您提供ComparatorX,而不是Entity<X>

您可以保留一个字段来存储X对象内部的相关Entity<X>对象并以这种方式编写:

结果=比较器.比较(this.getX(),那个);

于 2012-01-31T08:57:27.883 回答
1

想象以下两个类。

class Foo extends Entity<Bar> {}
class Bar extends Entity<Foo> {}

显然,不仅可以在X: 的实例上调用比较,如果在Foothen的实例上调用它,X = Bar反之亦然。

编辑:为了清楚起见,虽然您打算始终将继承类型本身替换为 X,但这不是由语言和/或编译器强制执行的。这就是你问题的根源。

于 2012-01-31T08:12:15.447 回答
0

奇怪的!如果你真的很高兴

result = comparator.compare((X)this, that);

那么,在任何情况下“this”可能不是 X 吗?子类化的一些奇怪排列并使参数未绑定?或者进一步使用绑定参数对子类进行子类化?

啊哈!如果您在 X 已经绑定时对类进行子类化,则可能会发生这种情况!

……不,这是不对的。我得承认,我糊涂了。

于 2012-02-03T03:44:10.287 回答