草庐IT

Java:枚举常量中方法和变量的定义

coder 2024-03-11 原文

我正在做一些实验,无意间写了一个代码,这很奇怪,我还没完全明白。我什至可以编译它,我什至感到惊讶。看起来像这样:

enum Foo {
    VALUE_1 {
        public int myVariable = 1;
    },
    VALUE_2 {
        public void myMethod() {
            //
        }
    },
    VALUE_3;
}

不出所料,无法通过以下方式访问此类元素:
Foo.VALUE_2.myMethod();

原因是,编译器将在枚举本身内寻找该方法。

我认为不可能从枚举之外访问这些方法和变量。因此,我尝试创建一个参数构造函数,并使用一些内部变量进行调用:
enum Foo {
    VALUE(internalVariable) {
        int internalVariable = 1;
    };

    private Foo(int param) {
        //
    }
}

不可能编译这样的构造。现在,我在想如果没有办法访问常量,那么在常量内定义某些东西有什么意义呢?

我试图在常量本身以及枚举中创建同名方法,以检查其是否以某种方式发生冲突。没有!
enum Foo {
    VALUE_1 {
        int myVariable = 1;

        public int myMethod() {
            return myVariable;
        }
    },
    VALUE_2 {
        //
    };

    public int myMethod() {
        return 0;
    }
}

有趣的时刻到了!我试图在枚举中进行myMethod()的调用,并实际上弄清楚了Java魔术的工作原理。在常量内部定义的方法将覆盖枚举内部定义的方法。
Foo.VALUE_1.myMethod(); // Returns 1
Foo.VALUE_2.myMethod(); // Returns 0

但是,我们不能覆盖变量,对吗?所以我很好奇,它仅适用于变量。
enum Foo {
    VALUE_1 {
        public int myVariable = 1;
    },
    VALUE_2 {
        //
    };

    public int myVariable = 0;
}

....

System.out.println(Foo.VALUE_1.myVariable); // Returns 0
System.out.println(Foo.VALUE_2.myVariable); // Returns 0

现在,我终于开始回答我的问题了:
  • 如果在常量内部创建公共(public)方法且没有此方法而将枚举留为空白,为什么我不会出现任何错误?在这种情况下,我刚刚定义的方法根本不能称为。还是我错了?

    更新:我知道枚举可以实现接口(interface)。但是,如果我还没有
    具体说来,整个代码是没有意义的。

    有人指出,即使不能从正常语言中访问方法
    方式,仍然可以使用反射。好吧...我们为什么不设计一个不可访问的
    关键词?
    inaccessible void magicalMethod() {
         //
    }
    

    这样的方法将被编译到* .class文件中。当您想使用它时,您必须
    自己加载字节码并进行解释。

    我只是不明白,为什么可以定义不可达的方法。唯一的原因
    我可以认为是程序员正在工作,还没有接口(interface)的定义。所以
    他只是准备单一方法的代码,稍后将添加“implements”关键字。旁
    这是不合逻辑的,仍然需要在所有常量中都使用这种方法。

    我认为这应该以错误结尾,而不仅仅是警告未使用的方法。你可能会忘记
    在枚举中添加“implement”子句或定义方法(
    覆盖),并会在首次使用后意识到这一点。 Java是非常严格的语言,
    所以我希望这种行为。
  • 如果在常量内创建公共(public)变量(或更确切地说是字段),为什么没有出现任何错误?在任何情况下(从外部)都无法访问它。因此,修饰符“public”在这里没有任何意义。

    更新:除了可见性外,其他内容与上一点相同
    修饰符在这里完全没用。是否公开, protected 真的没关系
    或私有(private)),因为无论如何您都无法访问它。我认为这是一个错误。
  • 为什么可以定义一个类(不带可见性修饰符),但是不与接口(interface)?是的,您可能不想编写如此残酷的枚举,以至于您不需要在常量内定义类,甚至在此处使用继承。但是,如果可以定义类和抽象类,这似乎并不奇怪。

    更新:这绝对不是您定期需要的东西,但是我了解
    可能有用。但是为什么它只限于类而接口(interface)却不能
    定义为好吗?
    enum Foo {
        VALUE {
            class MyClass {
                // OK
            }
    
            abstract class MyAbstractClass {
                // OK
            }
    
            interface MyInterface {
                // FAIL. It won't compile.
            }
        }
    }
    
  • 您在某处使用过这种功能吗?我可以想象它可能有用,但是一点也不令人困惑。另外,当我搜索有关此的一些资源时,我什么也没找到。

    更新:我想在枚举常量类主体中看到一些覆盖了方法的实际示例。您在某个开源项目中看到过它吗?

  • 环境:
    $ java -version
    java version "1.7.0_21"
    OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.10.1)
    OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
    

    感谢您的时间和回答!

    最佳答案

    Why I don't get any error if I create public method inside the constant and left enumeration empty without this method? In that case, the method I just defined can't be called at all. Or am I wrong?



    实际上,编译器应该能够看到该方法在枚举常量的类主体之外不可见,并在未使用该方法时警告您-我知道Eclipse会这样做。作为dasblinkenlight points out,这样的公共(public)方法实际上可以是由枚举实现的接口(interface)声明的方法的替代。

    I just can't understand, why it's possible to define unreachable method. The only reason I can think is that programmer is working and doesn't have definition of interface yet. So he's just preparing code of single methods and will add "implements" keyword later. Beside this is illogical, it would still require to have such a method in all constants.



    正如我已经指出的那样,这不适用于枚举常量类。范围很广-私有(private)嵌套类,本地类,匿名类-成员公开是毫无意义的。

    这个问题的问题在于,只有语言设计师才能真正回答它。我只能给出我的意见,那就是:为什么要出错?语言规范不是免费提供的-必须精心定义JLS中的所有内容,然后对其进行实现和测试。真正的问题是,使它成为错误有什么好处?唯一的事实是,尽管一个未使用的成员可能表示一个错误(因此发出警告),但它没有任何伤害。

    Why I don't get any error if I create public variable (or field, to be more precise) inside the constant? It can't be accessed in the any case (from the outside). Therefore, modifier "public" doesn't make any sense here.



    与上述相同-如果未使用变量,则编译器或至少某些IDE会警告您。这与在public嵌套类中声明private变量,然后未在任何地方引用它相同。在任何情况下,禁止JLS优先考虑这种情况,尽管反射的眼睛可以看到一切。

    It's more less the same thing as in the previous point, except the visibility modifier is completely useless here. It really doesn't matter if it's public, protected or private, because you won't be able to access that anyway. I think this is a bug.



    在这里,您忘记了成员可能仍在枚举常量类主体中使用-例如考虑一个辅助方法。只是在这种情况下,访问修饰符根本没有关系,可以保留。

    Why it's possible to define a class (without visibility modifiers), but not interface? Yeah, you wouldn't probably want to write so brutal enumeration that you would need to define classes inside the constant and even to use inheritance there. But if it's possible to define classes and abstract classes, it seems little weird.



    这是一个很好的问题,我花了一段时间了解您的意思。为了澄清,您是说在这种情况下仅允许该类:
    VALUE_1 {
        class Bar { }
        interface Baz { }
    },
    

    为了阐明这一点,请尝试创建static类:
    VALUE_1 {
        static class Bar { }
        interface Baz { }
    },
    

    现在都不允许。为什么?在枚举常量主体中无法声明static,因为主体在该常量实例的上下文中。这类似于在内部(非静态嵌套)类的范围内:
    class Outer {
    
        class Inner {
            // nothing static allowed here either!
        }
    }
    

    此类范围内均禁止使用静态变量,方法,类和接口(interface)(嵌套时隐式静态)。

    Did you use such a functionality somewhere? I can imagine it might be useful, but it's little confusing. Also, when I was searching for some resources about that, I didn't find anything.



    目前尚不清楚您在此指的是什么功能。请更新问题以指定您要查找的内容-枚举常量类主体中的重写方法?田野?辅助方法?助手类?请说清楚。

    关于Java:枚举常量中方法和变量的定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18392885/

    有关Java:枚举常量中方法和变量的定义的更多相关文章

    1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

      我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

    2. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

      在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

    3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

      我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

    4. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

      我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

    5. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

      我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

    6. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

      我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

    7. ruby - 通过 ruby​​ 进程共享变量 - 2

      我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

    8. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

      我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

    9. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    10. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

      我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

    随机推荐