起因是听课到
该段的输出boy输出什么?
答案就是输出BOY,但韩老师解释的有点笼统。
但是我看了一眼源码关于这个name确实有点没头绪
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
/**
* The name of this enum constant, as declared in the enum declaration.
* Most programmers should use the {@link #toString} method rather than
* accessing this field.
*/
//在enum声明中声明的枚举常量的名称。大多数程序员应该使用{@link #toString}方法,而不是直接访问这个字段。
private final String name;
/**
* Returns the name of this enum constant, exactly as declared in its
* enum declaration.
*
* <b>Most programmers should use the {@link #toString} method in
* preference to this one, as the toString method may return
* a more user-friendly name.</b> This method is designed primarily for
* use in specialized situations where correctness depends on getting the
* exact name, which will not vary from release to release.
*
* @return the name of this enum constant
*/
//返回这个枚举常量的名称,与enum声明中的名称完全一致。大多数程序员应该优先使用{@link #toString}方法,因为toString方法可能会返回一个更友好的名称。这个方法主要是为特殊情况设计的,在这种情况下,正确性取决于准确的名称,不同版本的名称不会有变化。@返回这个枚举常量的名称
public final String name() {
return name;
}
/**
* Sole constructor. Programmers cannot invoke this constructor.
* It is for use by code emitted by the compiler in response to
* enum type declarations.
*
* @param name - The name of this enum constant, which is the identifier
* used to declare it.
* @param ordinal - The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*/
//唯一的构造函数。程序员不能调用这个构造函数。它由编译器响应enum类型声明而发出的代码使用。
//* @param name——这个枚举常量的名称,是用来声明它的标识符。
//* @param ordinal—枚举常量的序号(它的位置
//*在枚举声明中,初始常量被赋值为0)。
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
/**
* Returns the name of this enum constant, as contained in the
* declaration. This method may be overridden, though it typically
* isn't necessary or desirable. An enum type should override this
* method when a more "programmer-friendly" string form exists.
*
* @return the name of this enum constant
*/
//返回这个枚举常量的名称,正如声明中所包含的。这个方法可能会被重写,尽管它通常不是必要的或理想的。如果存在对程序员更友好的字符串形式,enum类型应该覆盖这个方法。
//@返回这个枚举常量的名称
public String toString() {
return name;
}
源码的注释解释的倒是蛮清楚
翻译如下
//在enum声明中声明的枚举常量的名称。大多数程序员应该使用{@link #toString}方法,而不是直接访问这个字段。
//返回这个枚举常量的名称,与enum声明中的名称完全一致。大多数程序员应该优先使用{@link #toString}方法,因为toString方法可能会返回一个更友好的名称。这个方法主要是为特殊情况设计的,在这种情况下,正确性取决于准确的名称,不同版本的名称不会有变化。@返回这个枚举常量的名称
//唯一的构造函数。程序员不能调用这个构造函数。它由编译器响应enum类型声明而发出的代码使用。
//返回这个枚举常量的名称,正如声明中所包含的。这个方法可能会被重写,尽管它通常不是必要的或理想的。如果存在对程序员更友好的字符串形式,enum类型应该覆盖这个方法。
//@返回这个枚举常量的名称
解决:其实重要的是这一句话Sole constructor. Programmers cannot invoke this constructor.It is for use by code emitted by the compiler in response to enum type declarations.
也就是说compiler编译器执行了这一段抽象类的构造器使用,所以在源码中我们是看不见这个String name形式参数是哪一个实际参数传入的,只能知道的是代码运行时,该类被使用(因为程序员写的比如enmu XXX{}实际上是继承了该类)的时候就传入了,而且能确定的是如果子类型enmu XXX{}没有重写,那么这里toString返回的name就是常量名字。
不过确实,随着编译器版本的不同,这个name也不同。
总结:编译器执行了构造方法的实参的传入,没有显式的表现;传入的时间在代码运行时,该类被使用了,就会创建对象空间
关于enmu 类的枚举可以参考
小谈Java Enum的多态性 - Perifort Pro. - ITeye博客
https://www.cnblogs.com/xiangguoguo/p/9061678.html
还有个rz问题,刚刚我在想为什么enmu Season{}在系统中能默认继承为abstract的Enmu,突然想起来,Enmu类内并没有抽象方法,所以是可以被继承的,就跟下面这个一样。