编译时类型未知的 Java 类属性

标签 java generics types

我有一个 Java 类,其属性可以是字符串、 boolean 值或列表。 声明该属性类型的最佳方法是什么?知道我只能在运行时知道它的类型。

我的第一个方法是使用 Object 类型定义该属性,但不确定是否有更好的方法来实现此目的。

private final String expression;

private Object expressionValue;

ParsedExpression(String expression, Person person) {
        this.expression= expression;
        expressionEvaluator(person);
}

private void expressionEvaluator(Person person) {
        switch (this.expression) {
        case "name":
            expressionValue = person.getName();
            break;
        case "adult":
            expressionValue = person.isAdult();
            break;
        case "addresses":
            expressionValue = person.getAddresses();
            break;
        default:
            throw new RuntimeException("Property does not exist on type Person");
        }
    }

最佳答案

如果您的类型很少并且不打算更改它们,您可以使用带有私有(private)构造函数的泛型类和一些工厂方法,这些方法允许仅使用指定的类型参数创建实例:

public final class ExpressionValue<T> {
    private final T value;

    private ExpressionValue(T value) {this.value = value;}

    public Optional<String> getAsString() {
        return (value instanceof String) ? Optional.of((String)value) : Optional.empty();
    }

    public Optional<Boolean> getAsBoolean() {
        return (value instanceof Boolean) ? Optional.of((Boolean) value) : Optional.empty();
    }

    // in this context empty collection and empty optional mean different things
    @SuppressWarnings("OptionalContainsCollection")
    public Optional<List<?>> getAsList() {
        return (value instanceof List) ? Optional.of((List<?>) value) : Optional.empty();
    }

    public void use(Consumer<? super String> stringUser, Consumer<? super Boolean> booleanUser, Consumer<? super List<?>> listUser) {
        getAsString().ifPresent(stringUser);
        getAsBoolean().ifPresent(booleanUser);
        getAsList().ifPresent(listUser);
    }

    public static ExpressionValue<String> fromString(String string) {
        return new ExpressionValue<>(string);
    }

    public static ExpressionValue<Boolean> fromBoolean(boolean bool) {
        return new ExpressionValue<>(bool);
    }

    public static ExpressionValue<List<?>> fromList(List<?> list) {
        return new ExpressionValue<>(list);
    }
}
<小时/>

如果您有许多可用类型或需要更灵活的类型,您可以使用分层方法。在这种情况下,您需要创建一个具有常见 String、boolean 和 List 方法的接口(interface),然后使用所有可用的类型参数创建该接口(interface)的实现。它可能看起来像这样:

public interface ExpressionValue<T> {
    boolean check();
}
public abstract class ExpressionValueSkeleton<T> implements ExpressionValue<T> {
    private T value;

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

    protected T getValue() {
        return value;
    }
}
public class StringExpressionValue extends ExpressionValueSkeleton<String> {
    public StringExpressionValue(String value) {
        super(value);
    }

    @Override
    public boolean check() {
        return !getValue().isEmpty();
    }
}
public class BooleanExpressionValue extends ExpressionValueSkeleton<Boolean> {
    public BooleanExpressionValue(Boolean value) {
        super(value);
    }

    @Override
    public boolean check() {
        return getValue();
    }
}
public class ListExpressionValue<E> extends ExpressionValueSkeleton<List<E>> {
    public ListExpressionValue(List<E> value) {
        super(value);
    }

    @Override
    public boolean check() {
        return !getValue().isEmpty();
    }
}

如果您想执行一些仅适用于某些类型的操作,您可以使用 Acyclic Visitor pattern .

关于编译时类型未知的 Java 类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57136163/

相关文章:

java - 如何测试java代码?

c# - 有没有一种方法可以使用对象的形状而不是继承来对通用函数参数进行类型检查?

c# - 多类型变量 C#

powershell - Powershell日期类型无法找到

java - 你能指定一个泛型类型来子类化另一个泛型类型_和_一个具体的接口(interface)吗?

collections - 通过System.Collections.Queue传递对象时丢失类型信息

java - 如何让 Eclipse JPA(大理)使用另一个项目的 persistence.xml?

java - Java中如何为类成员函数分配内存

java - 在 Eclipse 中执行 "sudo java"时扫描器失败

c# - 检查字典中是否存在某个项目并将其从 C# 中的字典中删除