JAVA面向对象学习——java面向对象概念———Java 枚举(enum)


                           Java 枚举(enum)

Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。

例如定义一个颜色的枚举类。

enum Color 
{ 
    RED, GREEN, BLUE; 
}

以上枚举类 Color 颜色常量有 RED, GREEN, BLUE,分别表示红色,绿色,蓝色。

使用实例:

enum Color
{
    RED, GREEN, BLUE;
}

public class Test2
{
    // 执行输出结果
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}

====================================================

内部类中使用枚举

枚举类也可以声明在内部类中:

public class Test2
{
    enum Color
    {
        RED, GREEN, BLUE;
    }

    // 执行输出结果
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}

每个枚举都是通过 Class 在内部实现的,且所有的枚举值都是 public static final 的。

以上的枚举类 Color 转化在内部类实现:

class Color
{
     public static final Color RED = new Color();
     public static final Color BLUE = new Color();
     public static final Color GREEN = new Color();
}

迭代枚举元素

可以使用 for 语句来迭代枚举元素:

enum Color
{
    RED, GREEN, BLUE;
}
public class Test2
{
    public static void main(String[] args)
    {
        for (Color myVar : Color.values()) 
        {
            System.out.println(myVar);
        }
    }
}

在 switch 中使用枚举类

枚举类常应用于 switch 语句中:

enum Color
{
    RED, GREEN, BLUE;
}
public class Test2
{
    public static void main(String[] args)
    {
        Color myVar = Color.BLUE;

        switch(myVar) {
            case RED:
                System.out.println("红色");
                break;
            case GREEN:
                System.out.println("绿色");
                break;
            case BLUE:
                System.out.println("蓝色");
                break;
        }
    }
}

=============================================================

values(), ordinal() 和 valueOf() 方法

enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。
enum Color
{
    RED, GREEN, BLUE;
}

public class Test2
{
    public static void main(String[] args)
    {
        // 调用 values()
        Color[] arr = Color.values();

        // 迭代枚举
        for (Color col : arr)
        {
            // 查看索引
            System.out.println(col + " at index " + col.ordinal());
        }

        // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
        System.out.println(Color.valueOf("RED"));
        // System.out.println(Color.valueOf("WHITE"));
    }
}

=========================================================

枚举类成员

枚举跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所以外部无法调用。

枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

enum Color
{
    RED, GREEN, BLUE;

    private Color()
    {
        System.out.println("Constructor called for : " + this.toString());
    }

    public void colorInfo()
    {
        System.out.println("Universal Color");
    }
}

public class Test2
{
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
        c1.colorInfo();
    }
}

enum Color
{
    RED, GREEN, BLUE;

    private Color()
    {
        System.out.println("Constructor called for : " + this.name());
    }

    public void colorInfo()
    {
        System.out.println("Universal Color");
    }
}

public class Test2
{
    public static void main(String[] args)
    {
        Color c1 = Color.GREEN;
        System.out.println(c1.name());
        System.out.println(c1);
        c1.colorInfo();
        System.out.println(c1.toString());
        System.out.println(c1.ordinal());
    }
}

enum Color
{
    RED, GREEN, BLUE;

    public void colorInfo()
    {
        System.out.println("Universal Color");
    }
}

public class Test2
{
    public static void main(String[] args)
    {
        Color c1 = Color.GREEN;
        System.out.println(c1.name());
        System.out.println(c1);
        c1.colorInfo();
        System.out.println(c1.toString());
        System.out.println(c1.ordinal());
    }
}

  

==============================================

枚举类中的抽象方法实现,需要枚举类中的每个对象都对其进行实现。

enum Color{
    RED{
        public String getColor(){//枚举对象实现抽象方法
            return "hong se ";
        }
    },
    GREEN{
        public String getColor(){//枚举对象实现抽象方法
            return "lv se";
        }
    },
    BLUE{
        public String getColor(){//枚举对象实现抽象方法
            return "lan se";
        }
    };

    public abstract String getColor();//定义抽象方法
}

public class Test2
{
    public static void main(String[] args)
    {
        for (Color c:Color.values()){
            System.out.print(c.getColor() + "-------");
        }
    }
}

 =================================================================

 =================================================================

枚举类


Java 5新增了一个enum关键字(它与class、interface关键字的地位相同),用以定义枚举类。

正如前面看到的,枚举类是一种特殊的类,它一样可以有自己的成员变量、方法,可以实现一个或者多个接口,也可以定义自己的构造器。

一个Java源文件中最多只能定义一个public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。

但枚举类终究不是普通类,它与普通类有如下简单区别:

? 枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是默认继承Object类,因此枚举类不能显式继承其他父类。

    其中java.lang.Enum类实现了java.lang.Serializable和java.lang.Comparable两个接口。

? 使用enum定义、非抽象的枚举类默认会使用final修饰。

? 枚举类的构造器只能使用private访问控制符,如果省略了构造器的访问控制符,则默认使用private修饰;

    如果强制指定访问控制符,则只能指定private修饰符。由于枚举类的所有构造器都是private的,而子类构造器总要调用父类构造器一次,因此枚举类不能派生子类。

? 枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加public static final修饰,无须程序员显式添加。

     枚举类默认提供了一个values()方法,该方法可以很方便地遍历所有的枚举值。

public enum SeasonEnum
{
	// 在第一行列出4个枚举实例
	SPRING, SUMMER, FALL, WINTER;
}
public class EnumTest
{
	public void judge(SeasonEnum s)
	{
		// switch语句里的表达式可以是枚举值
		switch (s)
		{
			case SPRING:
				System.out.println("春暖花开,正好踏青");
				break;
			case SUMMER:
				System.out.println("夏日炎炎,适合游泳");
				break;
			case FALL:
				System.out.println("秋高气爽,进补及时");
				break;
			case WINTER:
				System.out.println("冬日雪飘,围炉赏雪");
				break;
		}
	}
	public static void main(String[] args)
	{
		// 枚举类默认有一个values方法,返回该枚举类的所有实例
		for (var s : SeasonEnum.values())
		{
			System.out.println(s);
		}
		// 使用枚举实例时,可通过EnumClass.variable形式来访问
		new EnumTest().judge(SeasonEnum.SPRING);
	}
}

public class EnumTest
{
    public void judge(SeasonEnum s)
    {
        switch (s)
        {
            case SPRING:
                System.out.println("1");
                break;
            case SUMMER:
                System.out.println("2");
                break;
            case FALL:
                System.out.println("3");
                break;
            case WINTER:
                System.out.println("4");
                break;
        }
    }
    public static void main(String[] args)
    {
        System.out.println("------------------");

        for (SeasonEnum s : SeasonEnum.values())
        {
            System.out.println(s);
        }

        System.out.println("------------------");

        new EnumTest().judge(SeasonEnum.SPRING);
    }
}

  

 

 枚举类的成员变量、方法、构造器

 枚举类也是一种类,只是它是一种比较特殊的类,因此它一样可以定义成员变量、方法、构造器。

public enum Gender
{
	MALE, FEMALE;
	// 定义一个public修饰的实例变量
	public String name;
}
public class GenderTest
{
	public static void main(String[] args)
	{
		// 通过Enum的valueOf()方法来获取指定枚举类的枚举值
		Gender g = Enum.valueOf(Gender.class, "FEMALE");

		// 直接为枚举值的name实例变量赋值
		g.name = "女";

		// 直接访问枚举值的name实例变量
		System.out.println(g + "代表:" + g.name);
	}
}

 ----------------------------------------------------------------------------------------------------------------------------------------------

public enum Gender
{
	MALE, FEMALE;
	private String name;
	public void setName(String name)
	{
		switch (this)
		{
			case MALE:
				if (name.equals("男"))
				{
					this.name = name;
				}
				else
				{
					System.out.println("参数错误");
					return;
				}
				break;
			case FEMALE:
				if (name.equals("女"))
				{
					this.name = name;
				}
				else
				{
					System.out.println("参数错误");
					return;
				}
				break;
		}
	}
	public String getName()
	{
		return this.name;
	}
}
public class GenderTest
{
	public static void main(String[] args)
	{
		Gender g = Gender.valueOf("FEMALE");

		g.setName("女");

		System.out.println(g + "代表:" + g.getName());

		// 此时设置name值时将会提示参数错误。
		g.setName("男");

		System.out.println(g + "代表:" + g.getName());
	}
}
public enum Operation
{
	PLUS
	{
		public double eval(double x, double y)
		{
			return x + y;
		}
	},
	MINUS
	{
		public double eval(double x, double y)
		{
			return x - y;
		}
	},
	TIMES
	{
		public double eval(double x, double y)
		{
			return x * y;
		}
	},
	DIVIDE
	{
		public double eval(double x, double y)
		{
			return x / y;
		}
	};

	// 为枚举类定义一个抽象方法

	// 这个抽象方法由不同的枚举值提供不同的实现

	public abstract double eval(double x, double y);

	public static void main(String[] args)
	{
		System.out.println(Operation.PLUS.eval(3, 4));
		System.out.println(Operation.MINUS.eval(5, 4));
		System.out.println(Operation.TIMES.eval(5, 4));
		System.out.println(Operation.DIVIDE.eval(5, 4));
	}
}

 枚举类里面定义抽象方法时,不能使用abstract关键字将枚举类定义为抽象类(因为系统会自动为它添加abstract关键字);

但是因为枚举类需要显式创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则错误。

相关