简体   繁体   English

Java泛型和加法运算的问题

[英]Problems with Java Generics and Addition arithmetic

Does anybody know why Im getting this error? 有人知道我为什么会收到此错误吗?

error: cannot find symbol return left.evaluate() + right.evaluate(); 错误:找不到符号返回left.evaluate()+ right.evaluate(); symbol: method evaluate() location: variable left of type T where T is a type-variable: T extends Object declared in class Operation 符号:方法validate()位置:类型T的左侧变量,其中T是类型变量:T扩展在Operation类中声明的对象

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

EDIT: 编辑:

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

I've been succes with it, now I want to use reflection in the addition class. 我一直很成功,现在我想在加法类中使用反射。

I want to instanciate a class and then call the evaluate() method. 我想实例化一个类,然后调用validate()方法。

T is never bound, so its upper bound is Object . T永无界,所以它的上限是Object Therefore, only methods on Object are available. 因此,仅Object上的方法可用。

You are mixing up the value type of the expression ( T , which could be Integer ) and the sub expressions themselves (subtypes of Expression ). 您正在混合表达式的值类型( T ,可以是Integer )和子表达式本身( Expression的子类型)。 Perhaps it should look like this: 也许应该看起来像这样:

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

Note also that Constant<T> and similar should implement Expression<T> , not the raw type Expression . 还要注意, Constant<T>和类似的应该实现Expression<T> ,而不是原始类型Expression Similarly, Addition<T> should extend Operation<T> , not Operation . 同样, Addition<T>应该扩展Operation<T> ,而不是Operation

That said, your approach to Addition is broken in general, because it can't extend to the general case (you can't just apply the + operator to any arbitrary type). 就是说,您对Addition的使用方法总的来说是不可行的,因为它不能扩展到一般情况(您不能仅将+运算符应用于任何任意类型)。 I would implement Addition solely for the Integer case: 我将仅针对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();
    }
}

You need to cast the super.left to Expression , or any other type that contains an evaluate() function at compile-time. 您需要在编译时将super.leftExpression或任何其他包含super.left evaluate()函数的类型。 Remember, java has type erasure and is a strongly typed language, your Addition.Evaluate() method has no idea what type left and right will be at compile-time, and since evaluate() is not defined in Operation, there is a compiler error. 请记住,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();
    }
}

Additionally, you cannot add the objects returned by the evaluate() method as generics in java are really just typed as Java.Lang.Object . 此外,您不能添加由Java.Lang.Object evaluate()方法返回的对象,因为Java中的泛型实际上只是键入为Java.Lang.Object Instead, you will need to have a type-aware add() method that does the adding for you using the instanceOf operator, as there is no way to override the "+" operator in java. 相反,您将需要有一个类型感知的add()方法,该方法使用instanceOf运算符为您执行添加操作,因为无法在Java中覆盖“ +”运算符。 (This seems like what you are trying to achieve, you just have not gone the full 100 yards yet) (这似乎是您要实现的目标,您还没有走满100码)

Just think of generic type "variables" as meaningless in java, they just help you to avoid type errors at compile-time, but are compiled down to their raw types in byte code. 只需将泛型类型“变量”认为在Java中是没有意义的,它们就可以帮助您避免在编译时出现类型错误,但会以字节码形式编译为原始类型。

Edit: 编辑:

Also... I'm not exactly sure what about block : 另外...我不太确定block是什么:

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

You then go on to call left.evaluate() and try to add it to right.evaluate() ... but the problem here is that you don't seem to have anything that derives from Integer so all you are left with strangely behaving code. 然后,您继续调用left.evaluate()并尝试将其添加到right.evaluate() ...但是这里的问题是您似乎没有从Integer派生的任何东西,所以剩下的一切都奇怪了行为代码。 If you DO know that you will be dealing with integers, and that all of your nested left and right objects will also be Integer s, you should just cast the expressions to int and then add them together. 如果你不知道你将处理整数,而所有的嵌套的leftright的对象也将是Integer S,你应该只投表达式为int,然后把它们相加。 Better yet, you should qualify your types with Integer so that you are working with the non-generic type qualified Addition class. 更好的是,您应该使用Integer来限定类型,以便使用非通用类型限定的Addition类。

You've got at least two problems. 您至少有两个问题。

  • left and right are type T , but you're trying to call evaluate() on them, which is defined in class Constant<T> . leftright均为T类型,但是您尝试在其上调用在类Constant<T>定义的evaluate() Because left and right aren't necessarily of type Constant<?> , the compiler can't make sense of these calls. 由于leftright不一定是Constant<?>类型的,因此编译器无法理解这些调用。
  • You're trying to add two expressions, of type T . 您正在尝试添加两个类型为T表达式。 This doesn't make sense for most types that T could be. 对于大多数T类型而言,这没有意义。 For example, what do you expect a + b to give you if a and b are both of type Color or InputStream or something else that it doesn't make sense to add? 例如,如果ab都是ColorInputStream类型,或者添加了其他没有意义的东西,您期望a + b给您什么?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM