为什么使用==比较Enum.toString()返回值与字符串字面量结果为true?
问题现象说明
现有如下Java代码:
public enum Style { BIG,MEDIUM,SMALL; public static void main(String[] args) { System.out.println(Style.SMALL.toString() == "SMALL"); } }
按照常规认知,==用于比较对象引用地址,这段代码的输出应该为false,但实际运行返回true,底层原因可以从以下两点解释:
核心原因1:Enum类的默认toString实现
所有Java枚举类默认继承java.lang.Enum父类,如果你没有主动重写枚举的toString()方法,默认实现逻辑就是返回枚举常量的名称字符串,对应源码逻辑如下:
// java.lang.Enum类的toString方法 public String toString() { return name; }
其中name属性就是你定义枚举常量时写的字面量字符串,在枚举类初始化时就会完成赋值。
核心原因2:JVM字符串常量池机制
JVM会把编译期能确定的字符串字面量存入字符串常量池,同一个字面量在常量池中只会保留一份实例:
- 代码中直接写的
"SMALL"是编译期可知的字面量,类加载时会直接引用常量池中已有的SMALL实例。 - 枚举的
name属性赋值时用的也是编译期就确定的SMALL字面量,和代码中手写的"SMALL"指向常量池中同一个对象。
所以两个指向同一个对象的引用用==比较自然会返回true。
注意事项
这个结果只是默认场景下的巧合,不具备通用性,绝对不可以在生产代码中用==比较字符串内容:
- 如果手动重写了枚举的
toString()方法,返回新拼接的字符串,这个比较结果就会变成false。 - 不同JVM的字符串常量池实现有差异,不能保证所有场景下都返回相同结果。
- 字符串内容比较的标准写法永远是调用
equals()方法。
内容的提问来源于stack exchange,提问作者Danny Julian
相关产品推荐
相关产品推荐

