Java泛型和加法算法的问题

时间:2014-03-31 20:07:04

标签: java generics arithmetic-expressions

有人知道我为什么会收到这个错误吗?

错误:找不到符号             return left.evaluate()+ right.evaluate();   符号:方法evaluate()   location:类型为T的左侧变量   其中T是一个类型变量:     T扩展在类Operation

中声明的Object
package expevaluator;

interface Expression<T> {

    T evaluate();
}

class Constant<T> implements Expression {

    private final T value;

    public Constant(T value) {
        this.value = value;
    }

    @Override
    public T evaluate() {
        return value;
    }

}

abstract class Operation<T> implements Expression {

    public T left;
    public T right;
}

class Addition<T> extends Operation {

    public Addition(T left, T right) {
        super.left = left;
        super.right = right;
    }

    @Override
    public T evaluate() {
        if(left instanceof Integer){
            if(right instanceof Integer){
                return super.left.evaluate() + right.evaluate();
            }else{
                return left.evaluate() + right.evaluate(); 
            }
        }else{
            return left.evaluate() + right.evaluate();
        }
    }
}

编辑:

package expevaluator;

import java.util.logging.Level;
import java.util.logging.Logger;

interface Expression<T extends Number> {

    T evaluate();
}

class Constant<T extends Number> implements Expression{

    private final T value;

    public Constant(T value) {
        this.value = value;
    }

    @Override
    public T evaluate() {
        return this.value;
    }

}

abstract class Operation<T> implements Expression {
    public T left;
    public T right;
}

class Addition extends Operation {

    public Addition(Constant left, Constant right) {
        super.left =  left.evaluate();
        super.right = right.evaluate();
    }

    @Override
    public Number evaluate() {
        String name = "expevaluator." + super.left.getClass().getSimpleName() + super.right.getClass().getSimpleName() + "Addition";
        try {
            Object instance;
            instance = Class.forName(name).newInstance();
            return (Number) instance;
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
            Logger.getLogger(Addition.class.getName()).log(Level.SEVERE, null, ex);
        }
        /*if (super.left instanceof Integer && super.right instanceof Integer) return new IntIntAddition().evaluate((Integer)super.left,(Integer)super.right);
        if (super.left instanceof Integer && super.right instanceof Double) return new IntDoubleAddition().evaluate((Integer)super.left,(Double)super.right);
        if (super.left instanceof Double && super.right instanceof Integer) return new DoubleIntAddition().evaluate((Double)super.left,(Integer)super.right);
        if (super.left instanceof Double && super.right instanceof Double) return new DoubleDoubleAddition().evaluate((Double)super.left,(Double)super.right);*/
        return null;

    }

}

class IntegerIntegerAddition{

    IntegerIntegerAddition() {

    }

    public Number evaluate(int left, int right) {
        return left + right;
    }

}

class IntegerDoubleAddition {

    public IntegerDoubleAddition() {
    }

    public Number evaluate(int left, double right) {
        return left + right;
    }
}
class DoubleIntegerAddition {

    public DoubleIntegerAddition() {
    }

    public Number evaluate(double left, int right) {
        return left + right;
    }
}
class DoubleDoubleAddition {

    public DoubleDoubleAddition() {
    }

    public Number evaluate(double left, double right) {
        return left + right;
    }
}

我已经成功了,现在我想在加法课中使用反射。

我想实现一个类,然后调用evaluate()方法。

3 个答案:

答案 0 :(得分:1)

T永远不会绑定,因此其上限为Object。因此,只有Object上的方法可用。

您正在混淆表达式的值类型(T,可能是Integer)和子表达式本身(Expression的子类型)。也许它应该是这样的:

public Addition(Expression<T> left, Expression<T> right) {
   //...

另请注意,Constant<T>和类似应该实现Expression<T>,而不是原始类型Expression。同样,Addition<T>应该延伸Operation<T>,而不是Operation

尽管如此,你对Addition的处理方法一般都被打破了,因为它不能扩展到一般情况(你不能只将+运算符应用于任意类型)。我会仅针对Addition案例实施Integer

class IntegerAddition extends Operation<Integer> {

    private final Expression<Integer> left, right;

    public IntegerAddition(Expression<Integer> left, Expression<Integer> right) {
        this.left = left;
        this.right = right;
    }

    public Integer evaluate() {
        return left.evaluate() + right.evaluate();
    }
}

答案 1 :(得分:0)

您需要在编译时将super.left转换为Expression或包含evaluate()函数的任何其他类型。请记住,java具有类型擦除并且是一种强类型语言,您的Addition.Evaluate()方法在编译时不知道leftright的类型,因为evaluate()不是在Operation中定义,存在编译器错误。

public T evaluate() {
    if(left instanceof Integer){
        if(right instanceof Integer){
            return ((Expression)super.left).evaluate() + ((Expression)right).evaluate();
        }else{
            return ((Expression)left).evaluate() + ((Expression)right).evaluate(); 
        }
    }else{
        return ((Expression)left).evaluate() + ((Expression)right).evaluate();
    }
}

此外,您无法添加evaluate()方法返回的对象,因为java中的泛型实际上只是键入为Java.Lang.Object。相反,您需要使用类型感知的add()方法,使用instanceOf运算符为您添加,因为无法覆盖java中的“+”运算符。 (这看起来就像你想要实现的那样,你还没有走完整个100码)

只要将泛型类型“变量”视为java中没有意义,它们只是帮助您在编译时避免类型错误,但是在字节代码中将其编译为原始类型。

编辑:

另外......我不确定块的含义:

if(left instanceof Integer){
        if(right instanceof Integer){

然后你继续打电话给left.evaluate()并尝试将其添加到right.evaluate() ...但问题是你似乎没有任何来自Integer的东西所以你就是留下了奇怪的代码。如果你知道你将处理整数,并且所有嵌套的leftright对象也将是Integer s,你应该只将表达式转换为int然后将它们加在一起。更好的是,您应该使用Integer限定类型,以便使用非泛型类型限定的Addition类。

答案 2 :(得分:0)

你至少有两个问题。

  • leftright类型为T,但您尝试在evaluate()上调用Constant<T>,这是在课程left中定义的。由于rightConstant<?>不一定属于T类型,因此编译器无法理解这些调用。
  • 您正在尝试添加两个类型为T的表达式。对于a + b可能存在的大多数类型,这没有意义。例如,如果ab属于ColorInputStream类型或其他类似内容,那么您希望{{1}}为您提供什么? ; t有意义添加?