gpt4 book ai didi

java - 在运行时转换之前检查通用类型

转载 作者:搜寻专家 更新时间:2023-10-31 20:31:55 25 4
gpt4 key购买 nike

我们的任务是创建一个对象结构来评估表达式(例如“1 + 2”或“true & false”)。提供了解析器以及用于创建表达式对象的工厂接口(interface)。

我们对不同的表达式使用泛型:Expression<Integer>返回一个整数,Expression<Boolean>返回 boolean 值等。

我们面临的问题是提供的接口(interface)使用原始类型 Expression ,例如:

public Expression createSumExpression(Expression left, Expression right);

仅当操作数的类型为 Expression<Integer> 时才定义求和表达式或 Expression<Double> .我们如何检查这个?由于类型删除,类型信息在运行时不可用,它只会导致 ClassCastException如果不正确。

我可以修改所有内容,除了 createSumExpressioncreateAndExpression功能。


这是演示问题的一段简化代码。它可以工作,但看起来不太好,并且会给出多个警告。

主程序.java

public class Main {

public static void main(String[] args) {
Expression<?> left1 = new BasicExpression<>(42);
Expression<?> right1 = new BasicExpression<>(3);
Expression<?> sum = createSumExpression(left1, right1);
System.out.printf("%d + %d = %d%n",left1.getValue(), right1.getValue(), sum.getValue());

Expression<?> left2 = new BasicExpression<>(true);
Expression<?> right2 = new BasicExpression<>(false);
Expression<?> and = createAndExpression(left2, right2);
System.out.printf("%b & %b = %b%n",left2.getValue(), right2.getValue(), and.getValue());
}

private static Expression createSumExpression(Expression left, Expression right) { // Raw types because of given interface
return new BinaryExpression<Integer,Expression<Integer>,Expression<Integer>>(left, right) {
@Override
protected Integer operation(Expression<Integer> left, Expression<Integer> right) {
return left.getValue() + right.getValue();
}
};
}

private static Expression createAndExpression(Expression left, Expression right) { // Raw types because of given interface
return new BinaryExpression<Boolean,Expression<Boolean>,Expression<Boolean>>(left, right) {
@Override
protected Boolean operation(Expression<Boolean> left, Expression<Boolean> right) {
return left.getValue() & right.getValue();
}
};
}

}

表达式.java

abstract public class Expression<V> {
public abstract V getValue();
}

基本表达式.java

public class BasicExpression<V> extends Expression<V> {
public BasicExpression(V value) {
this.value = value;
}
@Override
public V getValue() {
return value;
}
private V value;
}

二进制表达式.java

abstract public class BinaryExpression<V, L, R> extends Expression<V> {
public BinaryExpression (L l, R r) {
this.left = l;
this.right = r;
}
@Override
public V getValue() {
return operation(left, right);
}
abstract protected V operation(L left, R right);

private L left;
private R right;
}

提供的接口(interface)是:

/**
* @param <E>
* Your class for representing an expression.
*/
public interface IExpressionFactory<E> {
public E createSumExpression(E left, E right) throws ModelException;
public E createAndExpression(E left, E right) throws ModelException;
// ...
}

最佳答案

泛型在这种情况下并不是很有用,因为大多数类型将在运行时从输入字符串派生,而泛型是编译时的事情。无法以任何方式提前知道类型。它仅在像这样的简单示例中真正有用。

所以我的建议是放弃泛型并实现你自己的动态类型系统。例如:

enum Type {
Integer,
Boolean;
}

class ScriptObject {
private final Object value;
private final Type type;

private ScriptObject(Object value, Type type) {
this.value = value;
this.type = type;
}

public static ScriptObject of(boolean b) {
return new ScriptObject(b, Type.Boolean);
}

public static ScriptObject of(int i) {
return new ScriptObject(i, Type.Integer);
}

public int asInt() {
return (int) value;
}

public boolean asBoolean() {
return (boolean) value;
}

public static boolean areType(Type type, ScriptObject...objects) {
for(ScriptObject o : objects) {
if(o.type != type)
return false;
}

return true;
}

@Override
public String toString() {
return value.toString();
}

}

abstract class Expression {
public abstract ScriptObject getValue();
}

class BasicExpression extends Expression {
private final ScriptObject value;

public BasicExpression(ScriptObject value) {
this.value = value;
}

@Override
public ScriptObject getValue() {
return value;
}

}

abstract class BinaryExpression extends Expression {
private final Expression left;
private final Expression right;

public BinaryExpression (Expression l, Expression r) {
this.left = l;
this.right = r;
}

@Override
public ScriptObject getValue() {
return operation(left.getValue(), right.getValue());
}

protected abstract ScriptObject operation(ScriptObject left, ScriptObject right);

}

转换您的示例将如下所示:

public static void main(String[] args) {
Expression left1 = new BasicExpression(ScriptObject.of(42));
Expression right1 = new BasicExpression(ScriptObject.of(3));
Expression sum = createSumExpression(left1, right1);
System.out.printf("%s + %s = %s%n",left1.getValue(), right1.getValue(), sum.getValue());

Expression left2 = new BasicExpression(ScriptObject.of(true));
Expression right2 = new BasicExpression(ScriptObject.of(false));
Expression and = createAndExpression(left2, right2);
System.out.printf("%s && %s = %s%n",left2.getValue(), right2.getValue(), and.getValue());

createAndExpression(left1, right2).getValue(); // fails with: Can not apply '&' to '42' and 'false'
}

private static Expression createSumExpression(Expression left, Expression right) {
return new BinaryExpression(left, right) {
@Override
protected ScriptObject operation(ScriptObject left, ScriptObject right) {
if(!ScriptObject.areType(Type.Integer, left, right)) {
throw new RuntimeException("Can not apply '+' to '" + left + "' and '" + right + "'");
}
return ScriptObject.of(left.asInt() + right.asInt());
}
};
}

private static Expression createAndExpression(Expression left, Expression right) {
return new BinaryExpression(left, right) {
@Override
protected ScriptObject operation(ScriptObject left, ScriptObject right) {
if(!ScriptObject.areType(Type.Boolean, left, right)) {
throw new RuntimeException("Can not apply '&' to '" + left + "' and '" + right + "'");
}
return ScriptObject.of(left.asBoolean() && right.asBoolean());
}
};
}

我尽量让示例保持简单,但有些注意事项是您可能想为类型检查创建一堆辅助函数,并且还使用自定义异常类型,可能是您随后捕获并输出的已检查异常类型它是某处的消息,而不仅仅是崩溃。

您必须自己进行类型检查,这需要更多工作,但优点是您完全可以决定何时(甚至是否)检查类型,以及提供何种错误消息。

还有为类型创建转换机制的空间,因此除了检查类型是否是您想要的类型之外,您还可以尝试将其转换为所需的类型,这不是一个功能(除了 auto-( un)boxing) 的 Java 类型系统。

关于java - 在运行时转换之前检查通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50374500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com