首页 > 编程语言 >java枚举Enum与Enumeration源码详解

java枚举Enum与Enumeration源码详解

时间:2023-02-23 23:06:53浏览次数:34  
标签:SeasonEnum java String Enum final 枚举 源码 public name


java枚举Enum与Enumeration源码详解

类的定义

public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
}

属性定义

private final String name;

public final String name() {
return name;
}

private final int ordinal;

public final int ordinal() {
return ordinal;
}

protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}

public String toString() {
return name;
}

public final boolean equals(Object other) {
return this==other;
}
public final int hashCode() {
return super.hashCode();
}

protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}

public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}

@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}

public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}


protected final void finalize() { }


private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}

private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
  1.  使用final修饰 无疑会在内存上有稍多的消耗,因为final修饰后的属性所在的常量池。

    常量池(constant_pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量和符号引用。运行时常量池是方法区的一部分。 

    常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References),字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念,包括了如下三种类型的常量: 

        1.类和接口的全限定名 

        2.字段名称和描述符 

        3.方法名称和描述符

Java中八种基本类型的包装类的大部分都实现了常量池技术,它们是Byte、Short、Integer、Long、Character、Boolean,另外

两种浮点数类型的包装类(Float、Double)则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在

对应值在-128到127时才可使用对象池

final 修饰属性:则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值(但只能选其一)。

     2. 比较两个枚举类型的值,永远不需要调用equals,直接使用"=="就可以了。

     3. 所有的枚举类型都是Enum的子类,继承了许多的方法,其中最有用的就是toString方法,这个方法能返回枚举常量名。如SeasonEnum.SPRING.toString返回SPRING

     4. toString的逆方法是静态方法valueof。例如 SeasonEnum s = Enum.valueof(SeasonEnum.class,“SPRING”),将s设置为SeasonEnum.SPRING

     5. ordinal方法返回enum声明中枚举常量的位置,位置从0开始计数,例如SeasonEnum.SUMMER.ordinal()返回1.

     6.类型参数在CompareTo方法中的使用,如同Class类一样,鉴于简化的考虑,Enum类省略了一个类型参数。实际上,应将枚举类型SeasonEnum扩展为Enum<SeasonEnum>。如果枚举常量出现在other之前,则返回一个负值;如果this==other,则返回0;否则返回正值,枚举常量的出现次序在enum声明中给出。

     7. 因为equals、hashcode方法是被final修饰的,所以不可以被枚举重写(只可以继承),但是,可以重写toString方法。

先来看看Java枚举的基本使用

java枚举Enum与Enumeration源码详解_常量池

java枚举Enum与Enumeration源码详解_枚举类_02

java枚举Enum与Enumeration源码详解_常量池_03

如果我们冒然的提供set方法(外界可以改变其成员属性),好像是有点违背了设计的初衷。那么,我们应该舍弃set方法,保留get方法。

 

枚举是什么?

  Java中的枚举其实是一种语法糖,在 JDK 1.5之后出现,用来表示固定且有限个的对象。比如一个季节类有春、夏、秋、冬四个对象;一个星期有星期一到星期日七个对象。这些明显都是固定的,且有限个。

枚举类和普通类的区别

  ①、使用 enum 定义的枚举类默认继承 java.lang.Enum 类,即枚举类是不能再继承别的类了。而普通类的一般父类默认是 Object

  ②、枚举类的构造器只能使用 private 定义,而普通类的还可以用 public 修饰

  ③、枚举类的所有实例必须在枚举类中显示列出(,分隔   ;结尾),列出的实例系统会默认自动添加 public static final 修饰

  ④、所有的枚举类都提供了一个 values() 方法,可以用来遍历枚举值

使用 Enum 来表示季节类:

public enum SeasonEnum {

//必须在第一行写出有哪些枚举值
SPRING("春天", "春暖花开"),
SUMMER("夏天", "炎炎盛夏"),
FALL("秋天", "秋高气爽"),
WINTER("冬天", "大雪纷飞");

private final String name;
private final String desc;

private SeasonEnum(String name, String desc) {
this.name = name;
this.desc = desc;
}

public static void main(String[] args) {

System.out.println(SeasonEnum.SPRING); //SPRING
//用 values() 来获取所有的枚举值
for(SeasonEnum s : SeasonEnum.values()){
System.out.println(s);
}
}
}

java枚举Enum与Enumeration源码详解_枚举类_04

枚举类还能实现接口:

定义一个接口,方法是返回季节的月份

public interface SeasonEnumImpl {
//用来返回季节的月份
String getMonth();

}
public enum SeasonEnum implements SeasonEnumImpl{

//必须在第一行写出有哪些枚举值
SPRING("春天", "春暖花开"){
@Override
public String getMonth() {
return "12-2";
}
},
SUMMER("夏天", "炎炎盛夏"){
@Override
public String getMonth() {
return "3-5";
}
},
FALL("秋天", "秋高气爽"){
@Override
public String getMonth() {
return "6-8";
}
},
WINTER("冬天", "大雪纷飞"){
@Override
public String getMonth() {
return "9-11";
}
};

private final String name;
private final String desc;

private SeasonEnum(String name, String desc) {
this.name = name;
this.desc = desc;
}

public static void main(String[] args) {

System.out.println(SeasonEnum.SPRING); //SPRING

//用 values() 来获取所有的枚举值
for(SeasonEnum s : SeasonEnum.values()){
System.out.println(s.getMonth());
}
}

}

java枚举Enum与Enumeration源码详解_System_05

JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。 

public enum Fruit {
APPLE, BANANA, ORANGE, WATERMELON;
}
public class EnumTest {
public static void main(String[] args)
{
for(Fruit fruit : Fruit.values())
{
test(fruit);
}
}

public static void test(Fruit fruit)
{
switch (fruit)
{
case APPLE:
System.out.println("This is an apple");
break;
case BANANA:
System.out.println("This is a banana");
break;
case ORANGE:
System.out.println("This is an orange");
break;
case WATERMELON:
System.out.println("This is a watermelon");
break;

default:
break;
}
}
}

java枚举Enum与Enumeration源码详解_枚举类_06

 

Enumeration类源码

public interface Enumeration<E> {

boolean hasMoreElements();


E nextElement();
}

遍历枚举类

Map map = request.getParameterMap();    
java.util.Enumeration enum=this.getRequest().getParameterNames();
while(enum.hasMoreElements()){
String paramName=(String)enum.nextElement();
String[] values=request.getParameterValues(paramName);
for(int i=0;i<values.length;i++){
System.out.println("["+i+"] "+paramName+" "+values[i]);
}
}

//形成键值对应的map
map.put(paramName, paramValue);
}

Mybatis中的枚举

java枚举Enum与Enumeration源码详解_枚举类_07

java枚举Enum与Enumeration源码详解_枚举类_08

java枚举Enum与Enumeration源码详解_枚举类_09

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:SeasonEnum,java,String,Enum,final,枚举,源码,public,name
From: https://blog.51cto.com/u_11837698/6081992

相关文章

  • java的Integer类源码详解
    java的Integer类源码详解类的定义publicfinalclassIntegerextendsNumberimplementsComparable<Integer>{@NativepublicstaticfinalintMIN_VALUE=0x800......
  • JavaScript 如何验证 URL
    前言当开发者需要为不同目的以不同形式处理URL时,比如说浏览器历史导航,锚点目标,查询参数等等,我们经常会借助于JavaScript。然而,它的频繁使用促使攻击者利用其漏洞。这种被......
  • Java核心技术读书笔记-输入与输出
    IO流InputStream与OutputStream设计的目的是处理字节流的数据;而Reader和Writer是专门用于处理Unicode字符的类层次结构。read和write方法在执行时都将阻塞,直至字节确实......
  • java的一个小demo
    publicstaticvoidmain(String[]args){intnum=0;num=num++;System.out.println(num);//0num=++num;Sys......
  • java日期类Date与DateFormat源码详解
    java日期类Date与DateFormat源码详解Date类的定义publicclassDateimplementsjava.io.Serializable,Cloneable,Comparable<Date>{privatestaticfinalBaseCal......
  • java的DateFormat、SimpleDateFormate类源码的详解
    java的DateFormat、SimpleDateFormate类源码的详解抽象类Format的定义publicabstractclassFormatimplementsSerializable,Cloneable{privatestaticfinallong......
  • java的NumberFormat、DecimalFormat、MessageFormat类源码详解
    java的NumberFormat、DecimalFormat、MessageFormat类源码详解NumberFormat类的定义publicabstractclassNumberFormatextendsFormat{protectedNumberFormat(){......
  • Jenkins 添加节点 java web方式
    启用代理端口可以自己指定添加节点参数说明:Name(名称):即节点名称Description(描述):介绍该节点的作用,如Docker构建ofexecutors(并发构建数):定义该节点可以执行多少......
  • 深入学习jquery源码之each()
    $.each()遍历一个数组或对象,可以是DOM、json等格式,等价于for循环返回值:jQuery.each(callback) 参数:对于每个匹配的元素所要执行的函数概述:以每一个匹配的元素作为上下文......
  • 深入学习jquery源码之trigger()与triggerHandler()
    深入学习jquery源码之trigger()与triggerHandler()trigger(type,[data])概述:在每一个匹配的元素上触发某类事件。这个函数也会导致浏览器同名的默认行为的执行。比如,如果用......