【问题标题】:Problems with Java Generics and Addition arithmeticJava泛型和加法运算的问题
【发布时间】:2014-05-11 08:37:26
【问题描述】:

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

错误:找不到符号 返回 left.evaluate() + right.evaluate(); 符号:方法评估() 位置:类型 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() 方法。

【问题讨论】:

    标签: java generics arithmetic-expressions


    【解决方案1】:

    T 永远不会被绑定,所以它的上限是Object。因此,只有Object 上的方法可用。

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

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

    还要注意Constant&lt;T&gt; 和类似的应该实现Expression&lt;T&gt;,而不是原始类型Expression。同样,Addition&lt;T&gt; 应该扩展 Operation&lt;T&gt;,而不是 Operation

    也就是说,您对Addition 的处理方式通常被破坏,因为它不能扩展到一般情况(您不能只将+ 运算符应用于任意类型)。我将仅针对Integer 案例实施Addition

    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();
        }
    }
    

    【讨论】:

    • 你知道如何在我的评估方法中添加反射,因为我想在运行时运行评估方法吗?
    【解决方案2】:

    你至少有两个问题。

    • leftrightT 类型,但您尝试在它们上调用 evaluate(),这是在类 Constant&lt;T&gt; 中定义的。因为leftright 不一定是Constant&lt;?&gt; 类型,所以编译器无法理解这些调用。
    • 您正在尝试添加两个表达式,类型为T。这对于T 可能的大多数类型没有意义。例如,如果 ab 都属于 ColorInputStream 或其他没有意义的类型,你希望 a + b 给你什么?

    【讨论】:

      【解决方案3】:

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

      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 中是没有意义的,它们只是帮助您避免在编译时出现类型错误,但在字节码中被编译为它们的原始类型。

      编辑:

      另外...我不太确定 block 是怎么回事:

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

      然后您继续调用left.evaluate() 并尝试将其添加到right.evaluate()... 但这里的问题是您似乎没有任何从 Integer 派生的东西,所以您只剩下奇怪的行为代码。如果您知道您将处理整数,并且您所有嵌套的leftright 对象也将是Integers,那么您应该将表达式转换为int,然后将它们加在一起。更好的是,您应该使用 Integer 限定您的类型,以便使用非泛型类型限定的 Addition 类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-04
        相关资源
        最近更新 更多