main 方法在枚举和类中的工作方式是不是不同?
Posted
技术标签:
【中文标题】main 方法在枚举和类中的工作方式是不是不同?【英文标题】:Does main method work differently in enums and classes?main 方法在枚举和类中的工作方式是否不同? 【发布时间】:2015-08-12 06:16:01 【问题描述】:在以下代码中:
enum Rank
FIRST(20), SECOND(0), THIRD(8);
Rank(int value)
System.out.print(value);
public static void main (String[] args)
System.out.println(" " + Rank.values().length);
这给出了以下输出:
2008 3
如果 main
方法在其他类中声明,如下所示:
class XYZ
public static void main (String[] args)
System.out.println("\n" + Rank.values().length);
输出只有3
。
枚举中的main
和类中的main
有什么区别?为什么我有两个不同的输出?
【问题讨论】:
枚举和其他类没有区别。只是在加载类时运行代码这一事实有所不同。有点像你在 XYZ 中有一个静态块并在那里添加了一个打印语句。 你确定你的第一个代码 sn-p 对左花括号和右花括号是正确的吗? 我无法重现您的问题。当我使用外部类时,我得到了输出2008 3
。我还在Rank
中注释掉了他的main
方法,但输出仍然相同
枚举实例为public static final
。如果您向XYZ
添加等效字段和一个ctor,它会做同样的事情,因为静态字段在类第一次使用时由类加载器初始化。
【参考方案1】:
枚举常量是static
。它们在类初始化时被初始化(enum
只是一个类)。这意味着当您调用引用enum
类型的类的main
时,所有值都是使用构造函数创建的。
如果其他类没有以任何方式引用enum
,则不会打印任何输出,因为没有评估enum
。
【讨论】:
无法重现您的问题。当我使用外部类时,我得到了输出2008 3
。我还在Rank
中注释掉了他的主要方法,但输出仍然相同【参考方案2】:
您实际上看到的是枚举打印的构造函数。
所以一开始Rank.FIRST
被创建,System.out.print(value);
被调用为 20。
那么Rank.SECOND
和Rank.THIRD
也会发生同样的事情;这都是由类加载器完成的,因为EnumCreation
正在使用Rank 枚举。
由于Rank
中的构造函数使用print
而不是println
,它们都显示在1 行。
然后,当EnumCreation
进入 main 方法时,它会打印一个空格,然后是 Rank.values().length
和一个换行符。
当XYZ
进入主方法时,它应该做同样的事情;但它会打印一个换行符而不是空格。
不过,从班级的角度来看,您有 3 个班级。排名、EnumCreation 和 XYZ。 Rank 和 EnumCreation 恰好共享 1 个 *.java 文件。
希望这有助于解决问题!
【讨论】:
看起来问题中两个类中的主要方法都被编辑以删除System.out.println()
语句。由于该更改,EnumCreation
在运行时仍会导致 2008 打印,因为类加载器会在运行时将Rank
加载到同一文件中,从而导致所有 3 个枚举值都是静态构造的。而且由于XYZ
现在根本没有对Rank
类的引用或其主方法中的任何指令,它不会做任何事情。
无法重现您的问题。当我使用外部类时,我得到了输出2008 3
。我还在Rank
中注释掉了他的主要方法,但输出仍然相同【参考方案3】:
类和枚举之间最显着的区别是 ENUM 预定义了它的实例。该值在枚举加载时被打印,它执行 Enum 的构造函数以创建排名,然后依次打印其值。为普通类执行 main 时没有方法实现,也没有自动创建对象。你必须创建类的实例。希望你明白我的意思。
关于Enum的更多详情
因此 main 方法没有区别,但您可以看到区别,因为枚举的实例是在 VM 加载枚举时创建的。 :)
根据@Blip 的要求,我正在更新我的答案,因此即使您分离出主要方法,它也不会改变任何事情。由于 main 方法仍然引用 Rank 枚举,因此 Enum 正在由运行时加载,并且我们已经知道 Enums 的实例将在加载类时创建,它仍将执行构造函数,因此您将看到输出为 2008 3
【讨论】:
无法重现您的问题。当我使用外部类时,我得到了输出2008 3
。我还在Rank
中注释掉了他的主要方法,但输出仍然相同
@Blip 这不是关于分离主要方法,而是关于何时创建 Enum 的实例。看到这是枚举和类之间最显着的区别。 JVM 在加载该特定枚举时会负责为枚举创建实例。因此,即使您分离出该主要方法,您仍然会得到 2008 3 作为输出,但请尝试从 System.out.println 语句中删除 Rank。进一步参考我为枚举提供的链接将给出一些关于差异的基本概念:) :) 希望它有所帮助
我检查并发现它是正确的。感谢您指出。我会要求您更改答案,以纠正问题中提到的这一差异点。【参考方案4】:
Class
初始化程序和实例(或Object
)初始化程序之间存在差异。 Class
初始化程序在 Class
加载时运行,这通常在第一次被引用时发生。 Object
初始化器是构造函数,仅在使用 new
关键字创建新实例时运行(禁止反射)。
Enum
s 是静态实例。你可以把它们想象成单例——你从来没有new
和Enum
。
假设我有这个Class
定义
public class Foo
static
System.out.println("Someone loaded the class");
public Foo()
System.out.print("Foo constructor");
public static void main(String[] args)
System.out.println("Making Foo");
Foo foo = new Foo();
输出是
有人加载了这个类 制作Foo Foo 构造函数
Enum
将像Foo
中的静态块一样工作。
这是一个Enum
示例
public enum FooValues
HELLO,GOODBYE,WHAT;
private FooValues()
System.out.println(this);
public static void main(String[] args)
System.out.println("in main");
这给了
你好 再见 什么 在主要
因为在加载Enum
时,所有值在类加载阶段初始化,然后运行main
方法。
【讨论】:
无法重现您的问题。当我使用外部类时,我得到了输出2008 3
。我还在Rank
中注释掉了他的主要方法,但输出仍然相同
@Blip 很确定您的评论是针对 OP 的,是吗?可能想从我的答案中删除它并将其放在 OP 的问题上。
不,它也针对您,以便您可以更正此场景的答案此外,我已对这个问题的所有帖子发表了此评论,因为个人可以采取适当的行动。以上是关于main 方法在枚举和类中的工作方式是不是不同?的主要内容,如果未能解决你的问题,请参考以下文章