奇怪的类型行为

时间:2016-03-20 09:19:34

标签: java types overloading

我正在尝试在Java中实现类似CAS的东西,但我正在努力选择类型和方法。

当我添加两个子类型时,一切都很好。 当我添加具有超类型的子类型时,会发生无限递归。 当超类型再次被罚款时,当我向子类型添加超类型时,再次发生相同的递归。

有人可以解释这里发生的事情以及我做错了吗?

public class MathMain{
    public static void main(String[] args){
        Constant constant = new Constant(1);
        constant.add(constant);
        MathObject mathObject = (MathObject)constant;
        constant.add(mathObject);
        constant.add((Constant)mathObject);
        mathObject.add(constant);
    }
}


public abstract class MathObject{
    public abstract MathObject add(MathObject addend);
    public abstract MathObject substract(MathObject subtrahend);
}


public class Constant extends MathObject{
    public final double c;

    public Constant(double c){
        this.c = c;
    }

    public MathObject add(MathObject that){
        return that.add((Constant)this);
    }

    public MathObject substract(MathObject that){
        return that.substract((Constant)this);
    }

    public Constant add(Constant addend){
        return new Constant(c + addend.c);
    }

    public Constant substract(Constant subtrahend){
        return new Constant(c - subtrahend.c);
    }
}

1 个答案:

答案 0 :(得分:2)

要记住的重要一点是,方法重载是在编译时确定的,而方法重写是在运行时确定的。

mathObject.add(constant)

选择MathObject add(MathObject addend)方法,这是add唯一可用的MathObject方法。

在运行时,由于mathObject的运行时类型为ConstantMathObject add(MathObject that)的{​​{1}}被执行,并且它调用Constant。由于that.add((Constant)this)的类型为that,因此再次选择MathObject,这意味着您的方法在无限递归中调用自身。

MathObject add(MathObject addend)表达式调用Constant add(Constant addend)的唯一方法是that.add((Constant)this)的编译时类型是that,因为Constant没有' t有MathObject方法接受add参数。

现在,对于有效的案例:

Constant

直接调用constant.add(constant) constant.add((Constant)mathObject) ,因为Constant add(Constant addend)的编译类型是constant,并且选择了具有更具体参数类型的方法。

我不知道这是否是一个很好的解决方案,但是克服无限递归的一种方法是检查参数的类型:

Constant