【问题标题】:Tell Java compiler that on runtime the field will be accessible?告诉 Java 编译器在运行时该字段可以访问?
【发布时间】:2015-06-17 04:21:20
【问题描述】:

我有 3 个光源类(X、Y 和 Z),它们继承自更通用的光源类。

3 个类中的 2 个,有一个“位置”字段。 (X 和 Y)

在另一种方法中,我遍历某个列表的所有光源,并检查当前光源是否是 Z 的实例。 如果不是,我想在不转换当前实例的情况下访问 X(或 Y)的“位置”字段。 但是编译器不让我,我想告诉它,在运行时,访问这个字段是可以的。

实际上,在这两种情况下,它都不会让我在没有强制转换的情况下访问该字段,尽管在运行时它不会中断。

是的,我可以多写几行来处理这个问题,但我出于好奇和我喜欢极简编码而提出这个问题。

for (Light light : lights) {
    Vec vector;
    if (light instanceof DirLight) vector = light.direction;
    else vector = new Vec(intersectionPoint, light.position);
}

【问题讨论】:

    标签: java inheritance casting compiler-errors polymorphism


    【解决方案1】:

    通常需要强制转换是糟糕代码设计的标志。在你的情况下,我可以想象很多方法来编写更清晰的代码:

    1.Light 的每个实现都可以有一个返回 Vector 的方法。

    public abstract Vector getVector();
    

    2.如果使用这种方法不“正确”,您可以像这样实现Visitor-Pattern

    光:

    public abstract void visit(Visitor visitor);
    

    新界面:

    public interface Visitor {
         public void visit(Light1 light);
         public void visit(Light2 light);
         public void visit(Light3 light);
    }
    

    用法:

    light.visit(new Visitor() { ... });
    

    【讨论】:

    • 我将使用第一个技巧。在运行时进行强制转换有多贵?
    • 选角有多贵?见this question
    【解决方案2】:

    Java 是强类型的。您正在尝试访问存在于DirLight 但不存在于Light 的成员,这需要强制转换。没有办法解决。

    【讨论】:

      【解决方案3】:

      没有办法绕过它是不正确的。您可以使用反射来获取该字段。但是,这通常只能出于非常充分的原因使用,而不是出于您在问题中给出的原因。当然,您应该简单地对对象执行强制转换。

      但是,您可以通过以下方式获取对象的任何字段。

          // initialize o
          for (Field field : o.getClass().getDeclaredFields()) {
              Object value = field.get(o); 
              if (value != null) {
                  System.out.println(field.getName() + "=" + value);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-31
        相关资源
        最近更新 更多