还有你不知道的Java枚举特性(上篇)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/AndroidBluetooth/article/details/99069266

简介

博文 Java 枚举的本质 跟大家一起学习了 Java 语言中枚举到底是什么,探索其本质和原理。用一句话来概括其本质就是:“Java 中的枚举是一个特殊的 Java 类”,有兴趣的同学可以点击了解上面那篇文章。

今天跟大家一起学习和总结一下 Java 中的枚举的其他特性和用途,由于内容较多,这次的分享分为两篇文章来写,欢迎大家拍砖、指正和交流!

本篇主要内容:

  • Java switch 语句支持枚举类型以及注意事项
  • Java 枚举的常量使用
  • 如何在自定义枚举中自定义成员变量和成员方法、静态方法
  • Java 枚举实现接口

下篇主要内容:

  • Java 枚举是一个特殊的类,聊聊其方法的重写
  • 如何使用接口来组织 Java 枚举?
  • JDK 数据结构中关于枚举的集合 EnumSet 和字典 EnumMap

switch 语句支持枚举

JDK1.5 才开始有枚举类型,同时可爱的 Java 组织丰富了 switch 语句,即支持枚举。

我们还是动手写个例子~

定义一个枚举 Color,示例如下:

public enum Color {
	RED("red color", 0), 
	GREEN("green color", 1),
	BLUE("blue color", 2), 
	YELLOW("yellow color", 3);
 
    // 构造方法
	Color(String name, int id) {
		_name = name;
		_id = id;
	}
 
	private String _name;
	private int _id;
 
	public String getName() {
		return _name;
	}
 
	public int getId() {
		return _id;
	}
 
	public static Color getColor(int max) {
		Random random = new Random(System.currentTimeMillis());
		int num = random.nextInt(max);
		switch (num) {
		case 0:
			return Color.RED;
		case 1:
			return Color.GREEN;
		case 2:
			return Color.BLUE;
		case 3:
			return Color.YELLOW;
		default:
			return Color.BLUE;
		}
	}
}

为枚举 Color 提供了一个静态方法 getColor,可以获取随机的颜色值。

那么,可以结合 switch 语句这样使用,示例代码如下:

public static void main(String[] args) {
	int len = Color.values().length;
	Color color = Color.getColor(len);
	switch (color) {
	case RED:
		System.out.println("select " + "RED");
		break;
	case GREEN:
		System.out.println("select " + "GREEN");
		break;
	case BLUE:
		System.out.println("select " + "BLUE");
		break;
	case YELLOW:
		System.out.println("select " + "YELLOW");
		break;
	default:
		System.out.println("select " + "unknow!!");
		break;
	}
}

可以看出,switch 语句中条件值是 Color 对象。

这里提醒大家要注意一个问题,如果 case 的条件带上类的名字,代码是无法通过编译的。如下面的代码(错误示例):

// Error
case Color.RED:
	System.out.println("select " + "RED");
    break;

编译的错误信息:

Error: An enum switch case label must be the unqualified name of an enumeration constant

switch case 语句结合枚举使用时,只能写枚举类定义的变量名称,不能加类名。

当常量使用

一般在 Java 中我们定义常量最常用的方式就是使用下面的方式,如下:

public static final int MAX_NAME_LENGTH = 0x1112;

有了枚举之后,也可以使用枚举来定义常量。

public enum Color {
    YELLOW, BLANK, RED, GREEN
}

自定义方法、成员变量

上面的例子中自定义的一个枚举 Color,大家可以看到可以给它添加成员变量 _id_name,构造方法和其他方法 getColor(静态方法)。

如果这部分很难理解,建议去阅读 Java 枚举的本质 这篇文章。

实现接口

所有的枚举类都继承自 Enum,因为 Java 不支持多继承,所以枚举无法继承其它类。

枚举既然是和 Java 的普通类基本一样,那么,枚举当然也可以实现接口。

下面是枚举 Color 实现接口 Paint 的例子,如下:

interface Paint {
        void setColor();
    }

public enum Color implements Paint {
    RED("red color"),
    GREEN("green color"),
    BLUE("blue color"),
    YELLOW("yellow color");

    Color(String name) {
        _name = name;
    }

    private String _name;

    @Override
    public void setColor() {
        System.out.println("Current paint color: " + _name);
    }
}

还可以采用匿名内部类的方式,让每个枚举值实现接口 Paint 的方法,示例如下:

public enum Color implements Paint {
        RED("red color") {
            @Override
            public void setColor() {
                System.out.println("Current paint color: " + RED._name);
            }
        },
        GREEN("green color") {
            @Override
            public void setColor() {
                System.out.println("Current paint color: " + GREEN._name);
            }
        },
        BLUE("blue color") {
            @Override
            public void setColor() {
                System.out.println("Current paint color: " + BLUE._name);
            }
        },
        YELLOW("yellow color") {
            @Override
            public void setColor() {
                System.out.println("Current paint color: " + YELLOW._name);
            }
        };

        Color(String name) {
            _name = name;
        }

        private String _name;

        @Override
        public void setColor() {
            System.out.println("Current paint color: " + _name);
        }
}

可以写个方法测试一下,如下:

public static void main(String[] args) {
    for (Color color : Color.values()) {
        color.setColor();
    }
}

输出结果,如下:

Current paint color: red color
Current paint color: green color
Current paint color: blue color
Current paint color: yellow color

人生没有永远的赢家,切勿大喜大悲,要以平常心对待一切~
在这里插入图片描述

展开阅读全文

不知道java(SE)

08-06

(这个标题很有种似曾相识的感觉吧?嘿嘿。)rnrn知其然,知其所以然。我们学习、使用java,刚开始一些细节的东西可能会困扰我们,时间久了,往往会觉得理所当然,问题还是不太清楚。被人问起的时候,可能会“理所当然”的告诉别人,“这是java封装了的,知道怎么用就行啦”。长此以往,我们可能会的工具或配置很多,却无所长进。rnrn为了一定程度上辅助我们搞清楚这种模糊的概念、细节,特此在java大版各个子板,开通一个《你不知道的java》系列帖子,希望汇聚众“Java人”的经验和汗水,发扬“开源”的思想,使我们知道一些java的细节、工具或配置文件的处理流程,成为多懂一些Java的人。rnrn规则:rn[size=19px][color=#0000FF]1. 留言的同学,先抛出自己发现的,别人可能不知道的细节问题,再给出这个问题的答案。rn2. 围观的同学,如果觉得有哪些细节让你为之叫好,请您点一下“对我有用”。rn3. 每月结贴一次,根据“对我有用”的程度和问题精彩程度,奖励相应比例积分。[/color][/size](俺的权限就200分,要是僧多粥少了,希望众大大别怪俺小气哈!)rnrn你不知道的java(SE)rn这里先厚颜扔两块板砖:rn1. 执行java程序,如何给main方法传参?rn命令行执行的时候,在类名后跟参数,以空格分隔多个参数,例如:rnjava MyTest Tomcat is good in use.rn"Tomcat is good in use."会分成五个字符串,传递给MyTest的main方法(作为args)。rnrn2. 我们平时使用的String、Integer等j2se基本类,在java安装环境什么地方?rn在$HOME\jre\lib\rt.jar中。(rt,无处不在啊。。)rnrn3. 打的jar包没问题,MANIFEST.MF也设置了Main-Class,为何还是无法执行响应的main方法(报错“Invalid or corrupt jarfile”)?rnMain-Class: 冒号后面要加空格,再配置上带上包路径的类,例如:rnMain-Class: com.test.HelloWorldrn这样就可以在命令行里执行jar包:java -jar XXX.jarrn(当然,如果配置了jar文件的默认打开方式为“Java(TM) platform SE binary”,也可以双击jar文件执行)rnrn4. 都说字符串hashCode相同,不一定equals,如何构造俩字符串,使其hashCode相同,字符串不同?rn首先,为了简化问题,我们可以限定,长度同为两位的字符串。rn我们知道String.hashCode方法的哈希策略(参考源码):循环遍历字符串中的字符(c表示字符,ASCc表示c的ASCII值),计算:hashcode = 31*hashcode+ASCcrn因为字符串只有两位,hashcode初始值为0,我们的两个字符串假设为"XY"与"MN",则其hashcode分别为(31*ASCX+ASCY)和(31*ASCM+ASCN)。rn接下来凑数就可以了:ASCX和ASCM可以取任意值(尽量小些,在ASCII码范围内),ASCY和ASCN要根据ASCX和ASCM的取值,得到曲线关系(取值也要在ASCII码范围0~127内凑)。rn比如ASCX取值49,ASCM取值50,则得到等式:31*49+ASCY=31*50+ASCN ,转换:ASCY=31+ASCN。此时,不妨ASCN取值66,则ASCY取值97。rn接下来大家可以用System.out.println((char)49);方式得知各ASCII码对应的字符:49,'1'; 50,'2'; 66,'B'; 97,'a'。rn于是乎,hashCode相同,字符串不同的两个字符串构造好了:"1a","2B"(我擦,不是故意构造这个字符串的。。)。rn(这里为了好看,凑了个常规字符,大家也可以试试其他ASCII码字符,0~127范围内的哦)rnrn[size=19px][color=#0000FF][b]不积跬步无以至千里,不积小流无以成江海。[/b][/color][/size]rnrn题外话:rn因个人能力有限,先在J2SE版试行,欢迎对java其他版块有经验的同学,以同样的标题发个话题。rn如果分数有限的话,也可以给我留言,我来汇总发帖(并标注问题提供者的ID)。rn欢迎大家提出改进意见。 论坛

超级玛丽都30岁了——这里还有不知道的事!

03-22

几年前,我著书一部来分析《超级马里奥世界(1990)》的所有关卡,由此我发现市面上多数游戏关卡的系统设计体系。《超级马里奥世界》作为一款经典游戏,本身就有研究价值。不过书中所讲内容广泛适用于电子游戏设计。“超级马里奥世界的设计方法论”,或“任天堂系游戏设计大法”实际上出现在各种各样的游戏中-甚至是非任天堂系游戏。rnrn在本教程中,你会领略到二十世纪九十年代开始关卡设计的自然组织形式。随着电子游戏设计师(尤其是任天堂的设计师)实践越来越多,他们开始习惯性的组织运用设计技巧。这里我会解释如何将所有这些直观技巧从容不迫的展现在自己的游戏中。rnrnrn范例rnrn我应用这个方法设计制作了《超级马里奥制造》的一个关卡(附注释)。rn关卡代号: 0740-0000-00CD-4D5Brnrnrn挑战-节奏-技巧主题rnrn设计框架叫做“挑战,节奏,技巧主题”,简称CCST。我从《洛克人》,《银河战士》,《传送门》,《半条命》,《超级食肉男孩》和许多其他的游戏中都能找到CCST结构。为了方便起见,我以《超级马里奥制造》为例来解释CCST结构。通过练习,你将能够在一些你最喜欢的游戏身上识别出这个结构,从而极大提升你在游戏内容上的层次组织能力和深掘能力。rnrnrn挑战rnrn首先我们需要理解和并识别挑战。挑战是一个简短的任务,它跻身于相对安全的游戏阶段之间,要求玩家在短时间内完成。看看下面的例子,马里奥必须在一个移动平台上面跳上跳下,而平台下面是个无底深渊。 论坛

没有更多推荐了,返回首页