Java合作通用类:我们可以避免未经检查的强制转换吗? [英] Java cooperating generic classes: can we avoid unchecked cast?

查看:73
本文介绍了Java合作通用类:我们可以避免未经检查的强制转换吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起;急于给您一个最小的例子,我在此问题的第一个版本中没有提供有关要求的足够信息.

Sorry; eager to give you a minimal example, I didn’t provide enough information about the requirements in my first version of this question.

我有两个抽象的泛型类.他们合作,因此彼此依赖.有时,一个需要将 this 传递给另一个.我正在尝试找到一种类型安全的方法来实现此目的.

I have two abstract generic classes. They cooperate and hence depend on each other. Occasionally one needs to pass this to the other. I am trying to find a type safe way to do this.

public abstract class AbstractA<T extends AbstractB<? extends AbstractA<T>>> {

    protected void foo() {
        T aB = createB();
        aB.setA(this);
    }

    /** factory method */
    abstract public T createB();

}

public abstract class AbstractB<T extends AbstractA<? extends AbstractB<T>>> {

    private T theA;

    @SuppressWarnings("unchecked")
    public void setA(AbstractA<? extends AbstractB<?>> theA) { // dreamed of parameter list (T theA)
        // Unchecked cast from AbstractA<capture#1-of ? extends AbstractB<?>> to T
        this.theA = (T) theA;
    }

    protected T getA() {
        return theA;
    }

}

我的问题是我是否可以找到一种更简洁的方法,以便避免在 AbstractB.setA()中进行未经检查的强制转换.我曾希望将其声明为 setA(T theA),但是对其的调用将无法编译:setA(capture#1-of?方法扩展了AbstractA< T>)的类型为AbstractB<; capture#1-of?将AbstractA T扩展为不适用于自变量(AbstractA< T>).我仍在努力了解编译器是否应该了解足够的信息以允许这样做.

My question is whether I can find a cleaner way so I avoid the unchecked cast in AbstractB.setA(). I had hoped to declare it setA(T theA), but then the call to it won’t compile: The method setA(capture#1-of ? extends AbstractA<T>) in the type AbstractB<capture#1-of ? extends AbstractA<T>> is not applicable for the arguments (AbstractA<T>). I am still struggling to understand whether the compiler should know enough to allow it or not.

我当时想我的问题可能与

I was thinking my problem may be related to the one discussed in Java generics compilation error - The method method(Class<capture#1-of ? extends Interface>) in the type <type> is not applicable for the arguments. My unchecked cast was inspired from there. I liked the reply by Tom Hawtin - tackling, but I have not found a way to apply it to my situation.

我的用户将声明具体的子类,并实例化一个 ConcreteA 和任意数量的 ConcreteB s:

My user will declare concrete subclasses and instantiate one ConcreteA and any number of ConcreteBs:

public class ConcreteA extends AbstractA<ConcreteB> {

    @Override
    public ConcreteB createB() {
        return new ConcreteB();
    }

    public void concreteAMethod() {
        // ...
    }

}

public class ConcreteB extends AbstractB<ConcreteA> {

    public void bar() {
        ConcreteA a = getA();
        a.concreteAMethod();
    }

}

( class AbstractA< T扩展AbstractB< ;?扩展AbstractA< T>>> 看起来有点复杂;我认为我需要具体子类来了解彼此的确切类型,但显然它没有给我那个.)

(class AbstractA<T extends AbstractB<? extends AbstractA<T>>> looks a bit complicated; I thought I needed it for concrete subclasses to know each other’s exact types, but apparently it doesn’t give me that.)

推荐答案

我已经意识到我的问题确实出在将两个不属于一起的AbstractA/ConcreteA层次结构中.尽管对于很多人来说可能并不有趣,但我发布此见解的原因有两个:(1)我觉得我欠克里斯·沃勒特(Chris Wohlert)的答案是我自己找到的(2)更重要的是,我很想启发其他面临类似难题的人泛型问题可以从更高层次上审查您的设计,而不仅仅是解决泛型和/或类强制转换问题.它肯定对我有帮助.演员表/泛型问题表明,更基本的东西是不正确的.

I have come to realize that my problem really came out of stuffing two concepts into the AbstractA/ConcreteA hierarchy that didn’t belong together. Though maybe not interesting to very many, I am posting this insight for two reasons: (1) I feel I owe Chris Wohlert the answer I have found myself (2) more importantly, I’d love to inspire anyone else facing a similar tricky generics issue to review your design from a higher level than just solving the generics and/or class cast issue. It certainly helped me. The cast/generics problem was a sign that something more fundamental was not quite right.

public abstract class AbstractA {

    public void foo() {
        AbstractB aB = createB();
        aB.setA(this);
    }

    /** factory method */
    abstract public AbstractB createB();

}

public abstract class AbstractB {

    private AbstractA theA;

    public void setA(AbstractA theA) {
        this.theA = theA;
    }

    // methods that use theA

}

没有泛型,也没有类强制转换.将不属于A类层次结构的内容取出到ConcreteC(没有AbstractC)中:

No generics and no class cast. Taking out the stuff that didn’t belong in the A class hierarchy into ConcreteC (with no AbstractC):

public class Client {

    public void putTheActTogether() {
        ConcreteC theC = new ConcreteC();

        // the concrete A
        AbstractA theA = new AbstractA() {
            @Override
            public AbstractB createB() {
                return new ConcreteB(theC);
            }
        };
        // call methods in theA
    }

}

public class ConcreteB extends AbstractB {

    private final ConcreteC c;

    public ConcreteB(ConcreteC c) {
        super();
        this.c = c;
    }

    public void bar() {
        c.concreteCMethod();
    }

}

public class ConcreteC {

    public void concreteCMethod() { // was concreteAMethod(); moved and renamed
        // ...
    }

}

客户端需要的行数比以前多.在我的真实代码中,我需要在AbstractA和ConcreteC中复制一个最后的字段,但是这样做很有意义.总而言之,我认为对于纯净而简单的设计来说,这是一个低廉的价格.

The client needs a few more lines than before. In my real-world code I needed to duplicate one final field in AbstractA and ConcreteC, but it made sense to do. All in all I consider it a low price for a design that is otherwise pure and simple.

这篇关于Java合作通用类:我们可以避免未经检查的强制转换吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆