当前位置:  开发笔记 > 编程语言 > 正文

为什么我不能从Java中的专用枚举值访问静态最终成员

如何解决《为什么我不能从Java中的专用枚举值访问静态最终成员》经验,为你挑选了1个好方法。

我想知道为什么,尽管在Java中执行以下操作是完全有效的

public enum Test {
   VALUE1() {
      public static final String CONST_RELATED_TO_VALUE1 = "constant";
      public static final String OTHER_CONST_RELATED_TO_VALUE1 = "constant";
   },
   VALUE2() {
      public static final String CONST_RELATED_TO_VALUE2 = "constant";
   },
   VALUE3;
}

正如人们期望的那样访问常量Test.VALUE1.CONST_RELATED_TO_VALUE1不起作用.

现在我明白了VALUE1,VALUE2等等,实际上都普遍被视为类型的静态终审Test,因此不具备这些领域,但信息理论上应该可以在编译时,它可以很容易地验证运行一个小测试

     // print types and static members
     for (Object o: Test.values()) {
        System.out.println(o.toString() + ": " + o.getClass());
        for (Field field : o.getClass().getDeclaredFields()) {
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
                System.out.println("\t" + field);
            }
        }             
     }

这导致以下输出

VALUE1: class Test$1                                                                                                                                                                               
        public static final java.lang.String Test$1.CONST_RELATED_TO_VALUE1                                                                                                                
        public static final java.lang.String Test$1.OTHER_CONST_RELATED_TO_VALUE1                                                                                                          
VALUE2: class Test$2                                                                                                                                                                               
        public static final java.lang.String Test$2.CONST_RELATED_TO_VALUE2                                                                                                                
VALUE3: class Test                                                                                                                                                                                 
        public static final Test Test.VALUE1                                                                                                                                    
        public static final Test Test.VALUE2                                                                                                                                    
        public static final Test Test.VALUE3                                                                                                                                    
        private static final Test[] Test.$VALUES

很显然,我们实际上在运行时有适当的专用子类VALUE1VALUE2.但它看起来也是我们丢失具体类型信息的原因VALUE1,VALUE2也是编译器为基本枚举类生成静态枚举值的方式,Test如下所示VALUE3:所有成员都是类型Test,具体类型被丢弃.

但是,在我看来,如果编译器只是保留这些类型

        public static final Test$1 Test.VALUE1                                                                                                                                    
        public static final Test$2 Test.VALUE2                                                                                                                                    
        public static final Test Test.VALUE3                                                                                                                                    

所有周围的代码仍然有效.此外,我们还可以做什么,我最初尝试并获得CONST_RELATED_TO_VALUE1通过Test.VALUE1,这是现在显然类型的实例,Test$1而不是只Test,虽然它一般应避免,似乎在这种情况下,完全没有通过一个实例来访问静态成员.

现在正如许多人正确指出的那样,使用左侧的匿名类不是有效的Java代码,并且可能也不允许在没有一些主要规范更改的情况下编译器.但是,这可以通过使用命名的内部类来轻松解决,所以我们可以

        public static final Test.Value1 Test.VALUE1                                                                                                                                    
        public static final Test.Value2 Test.VALUE2                                                                                                                                    
        public static final Test Test.VALUE3                                                                                                                                    

这甚至为调试提供了额外的好处,即内部子类名称清楚地映射到相应的枚举值.

现在我明白了必须进行一些细微的改动,但是从匿名到命名的类而不是丢弃这些类似乎是一个很小的改变,这看起来很不错,没有一个简单的方法来使用重写来模拟它成员或什么的.

所以我想知道为什么除了时间之外没有像这样实现?我是否遗漏了一些关键的东西,这会阻止编译器这样做(关于实现复杂性或类型系统不可能)是否只是为了保持简单而没有实现,因为这些行没有时间或东西?

(我主要是寻找为什么决定从编译器/类型系统的角度来实现它的原因,而不是实际的替代方案,因为肯定有一对,尽管它似乎仍然是一个很好的模式)



1> Raul Santeli..:

静态成员如是CONST_RELATED_TO_VALUE1相应枚举值的匿名类的成员,但不是枚举类本身的成员.与其他匿名类一样,VALUE1这里的对象被声明为类型,Test即使它是匿名子类的实例Test.

因此,您无法访问CONST_RELATED_TO_VALUE1via VALUE1.CONST_RELATED_TO_VALUE1因为VALUE1是类型的引用,Test并且CONST_RELATED_TO_VALUE1是匿名子类的成员但不是Test.CONST_RELATED_TO_VALUE1只能由匿名类的其他成员访问.

如果要访问匿名类中定义的值,则VALUE1需要m()在枚举对象的匿名类中重写枚举类型的方法(例如),并以某种方式返回或提供所需的值暴露(通过VALUE1.m()).

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有