[英]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.left
为Expression
或任何其他包含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()
方法是什么类型不知道left
和right
将在编译时,由于评估()操作中没有定义,有一个编译器错误。
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. 如果你不知道你将处理整数,而所有的嵌套的
left
和right
的对象也将是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>
. left
和right
均为T
类型,但是您尝试在其上调用在类Constant<T>
定义的evaluate()
。 Because left
and right
aren't necessarily of type Constant<?>
, the compiler can't make sense of these calls. left
和right
不一定是Constant<?>
类型的,因此编译器无法理解这些调用。 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? a
和b
都是Color
或InputStream
类型,或者添加了其他没有意义的东西,您期望a + b
给您什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.