繁体   English   中英

在Java中,我如何显式引用`this`类的静态成员?

[英]In Java, how do I refer explicitly to a static member of the class of `this`?

在Java中,如何显式引用this的静态成员?

我想明确地引用静态成员以获得可读性,但是不要使用文字类名来尊重重写该值的子类。

一个人为的例子:

class Flying {
   static final String label = "A Flying Superhero";
   String exclamation() {
      return "Look! Up in the sky! It’s a bird! It’s a plane! It’s "+(WHAT GOES HERE?)+"!";
   }
}

class Superman extends Flying {
   static final String label = "Superman";
}
class Howard extends Flying {
   static final String label = "Howard the Duck";
}

请注意,我想避免单独使用label ,因为它的含义可能不明确; 我希望读者立即知道它是一个静态成员,就像他们从Flying.label ,但没有命名基类。

(在激发这个问题的情况下,静态成员也是最终的,但我认为这不会影响你如何引用它。)


编辑 :这是一个可能更具说服力的案例。 我想在超类中实现main ,并让它创建并使用被调用的子类的实例。

class Super
   public static void main( String[] args ) {
      Super instance = new (?WHAT GOES HERE?)( /*...*/ );
      instance.use();
   }
}

class Sub extends Super {
   void use() {
      /* ... */
   }
}

当在Sub上启动jvm时,我希望它使用相同的main实现,但是使用子类的实例。

这种情况的不同之处在于上下文是静态的,要访问的静态成员是构造函数。

(这是在建模和模拟的研究生课程中进行的家庭作业;超类是一个模型,不同的场景被实现为子类。)

为了澄清这个问题 ,我认为需要做三件事:

  • 在静态方法的调用中,获取调用该方法的Class(我还没有找到任何内容)
  • 给定一个类,访问该类的静态成员(可能使用aClass.getDeclaredField ?)
  • 给定一个类,构造该类的新实例(可能使用aClass.getConstructors ?)

结论

在读到答案之前,我没有意识到我试图做一些与Java方式相反的事情。 显然我已经习惯了更多动态语言。 (感觉我被JavaScript宠坏了似乎是错误的。)

这个架构主要是由我正在使用的框架提供的GUI激发的,它为您提供了一个类选择器,然后是一个UI,用于与您选择的类的实例进行交互。 这使得使用不同场景的便捷方式可以为每个场景创建一个类。

对于仅限于访问静态成员的原始情况,暂时使用文字类名称就足够了。

对于涉及实例化的编辑案例,我将实例化留在子类中并将实例传递给超类的方法,如下所示:

class Model {
   public static void run( Model m ) {
      /* ... */
   }
}

class Scenario extends Model {
   public static void main( String[] args ) {
      Model.run( new Scenario( /*...*/ ) );
   }
}

将来,我会尽量避免将某些图书馆引入与语言功能冲突的领域。

你不能覆盖变量,相反,你需要提供一个方法,例如......

class Flying {

    private final String label = "A Flying Superhero";

    String exclamation() {
        return "Look! Up in the sky! It’s a bird! It’s a plane! It’s " + getLabel() + "!";
    }

    public String getLabel() {
        return label;
    }
}

class Superman extends Flying {

    private final String label = "Superman";
    @Override
    public String getLabel() {
        return label;
    }

}

class Howard extends Flying {

    private final String label = "Howard the Duck";
    @Override
    public String getLabel() {
        return label;
    }
}

子类不继承静态成员。 在你的新例子中, main可以像Sub.main(args);一样被Sub Sub.main(args); 但它总是属于Super 您甚至可以检查堆栈跟踪,确认它是否在Super上调用。

  • 在静态方法的调用中,获取调用该方法的Class(我还没有找到任何内容)

这是不可能做到的。

  • 给定一个类,访问该类的静态成员(可能使用aClass.getDeclaredField ?)

这可以做到,但如果你只使用常规继承,那么解决一个非常简单的问题是一种非常麻烦的方法。

  • 给定一个类,构造该类的新实例(可能使用aClass.getConstructors ?)

这可以做到并且不时有用。 现在使用Java 8 Supplier不太有用,例如SomeClass::new

静态是在Java中处理这种问题的错误方法。 常规继承可以让您轻松地完成这些工作。

class InterfacesExample {
    public static void main(String[] args) {
        @SuppressWarnings("unchecked") // Arrays#asList
        List<Class<? extends Printer>> classes = Arrays.asList(
            FruitPrinter.class,
            TreePrinter.class
        );

        for(Class<? extends Printer> cls : classes) {
            try {
                Constructor<? extends Printer> ctor = cls.getDeclaredConstructor();
                Printer p = ctor.newInstance();
                p.print();
            } catch(Exception e) {
                System.err.println(e);
            }
        }
    }
}

interface Printer {
    void print();
}

class FruitPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Apple, Banana, Plum, Pear");
    }
}

class TreePrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Oak, Maple, Elm, Willow");
    }
}

暂无
暂无

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

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