做搞机网站我是seo关键词
Java 枚举基础知识讲解 (实例配套解析!!)
我将为你详细讲解 Java 枚举(Enum)的基本知识,包括定义、特性、使用场景以及常见操作。
1. 什么是 Java 枚举?
Java 中的枚举(enum
)是一种特殊的数据类型,用于定义一组命名的常量。枚举是在 Java 5 中引入的,通过关键字 enum
定义。它本质上是一个类,继承自 java.lang.Enum
,但开发者无需显式继承。
示例:
enum Day {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
在这个例子中,Day
是一个枚举类型,包含 7 个常量,表示一周的每一天。
2. 枚举的特性
- 类型安全:枚举限制了变量只能取定义中的值,避免无效值。
- 单例性:每个枚举常量都是一个唯一的实例,由 JVM 在类加载时创建。
- 继承自 Enum 类:枚举自动继承
java.lang.Enum
,因此具有一些内置方法(如name()
和ordinal()
)。 - 不可继承:枚举不能被其他类继承,也不能继承其他类(因为已经隐式继承了
Enum
)。 - 可实现接口:枚举可以实现接口,但不能被继承。
3. 基本用法
(1) 定义和使用
public class Main {enum Color {RED, GREEN, BLUE}public static void main(String[] args) {Color myColor = Color.RED;System.out.println(myColor); // 输出: RED}
}
(2) 在 switch 语句中使用
枚举非常适合与 switch
语句结合使用:
enum Day {MONDAY, TUESDAY, WEDNESDAY
}public class Main {public static void main(String[] args) {Day today = Day.MONDAY;switch (today) {case MONDAY:System.out.println("今天是星期一");break;case TUESDAY:System.out.println("今天是星期二");break;case WEDNESDAY:System.out.println("今天是星期三");break;}}
}
4. 枚举的高级特性
(1) 带构造方法和字段
枚举可以有构造方法、字段和方法,但构造方法必须是私有的(默认就是 private)。
enum Planet {EARTH(5.972e24, 6.371e6), // 质量 (kg), 半径 (m)MARS(6.417e23, 3.389e6);private final double mass; // 质量private final double radius; // 半径// 私有构造方法Planet(double mass, double radius) {this.mass = mass;this.radius = radius;}public double getMass() {return mass;}public double getRadius() {return radius;}
}public class Main {public static void main(String[] args) {Planet earth = Planet.EARTH;System.out.println("地球质量: " + earth.getMass()); // 输出: 地球质量: 5.972E24System.out.println("地球半径: " + earth.getRadius()); // 输出: 地球半径: 6371000.0}
}
(2) 实现接口
枚举可以实现接口,为每个常量定义不同的行为。
interface Description {String getDesc();
}enum Season implements Description {SPRING {public String getDesc() {return "春天,温暖而美好";}},SUMMER {public String getDesc() {return "夏天,炎热且充满活力";}};// 抽象方法必须由每个常量实现public abstract String getDesc();
}public class Main {public static void main(String[] args) {System.out.println(Season.SPRING.getDesc()); // 输出: 春天,温暖而美好}
}
5. 内置方法
由于枚举继承自 java.lang.Enum
,它提供了一些有用的方法:
name()
:返回枚举常量的名称。Day day = Day.MONDAY; System.out.println(day.name()); // 输出: MONDAY
ordinal()
:返回枚举常量的声明顺序(从 0 开始)。System.out.println(day.ordinal()); // 输出: 0
values()
:返回包含所有枚举常量的数组(由编译器自动生成)。Day[] days = Day.values(); for (Day d : days) {System.out.println(d); // 输出: MONDAY, TUESDAY, WEDNESDAY, ... }
valueOf(String name)
:根据名称返回对应的枚举常量(名称大小写敏感)。Day d = Day.valueOf("TUESDAY"); System.out.println(d); // 输出: TUESDAY
6. 常见使用场景
- 状态表示:如订单状态(
PENDING
,SHIPPED
,DELIVERED
)。 - 配置选项:如日志级别(
INFO
,DEBUG
,ERROR
)。 - 替代常量:比使用
public static final
更安全、更灵活。
7. 注意事项
- 不能使用 new 创建实例:枚举常量在定义时由 JVM 创建,不能通过
new
实例化。 - 线程安全:枚举常量是单例的,天生线程安全,非常适合用作单例模式。
- 序列化:枚举默认支持序列化,且保证反序列化后仍是同一个实例。
8. 示例:完整代码
以下是一个综合示例:
enum TrafficLight {RED(30), // 红灯 30 秒GREEN(45), // 绿灯 45 秒YELLOW(5); // 黄灯 5 秒private final int duration;TrafficLight(int duration) {this.duration = duration;}public int getDuration() {return duration;}
}public class Main {public static void main(String[] args) {for (TrafficLight light : TrafficLight.values()) {System.out.printf("%s: %d 秒%n", light, light.getDuration());}// 输出:// RED: 30 秒// GREEN: 45 秒// YELLOW: 5 秒}
}
综合案例解析
一、 小新的神秘棋盘
问题描述
在一次偶然的机会,小新发现了一个神秘的棋盘。这个棋盘和普通的 8x8 格子棋盘不同,它的棋子可以进行非常神奇的移动。每个棋子都只能移动到与其当前所在位置颜色不同的格子上。
小新非常好奇,他想要知道如果他把棋子放在 (A,B)(A,B) 位置,那么把棋子移动到 (P,Q)(P,Q) 位置最少需要多少步。他希望你能帮他解答这个问题。
注意:棋盘是一个 8x8 的方形棋盘,其中 (i,j)(i,j) 表示第 ii 行和第 jj 列的交叉点。如果 i+ji+j 是偶数,(i,j)(i,j) 就是白色,如果 i+ji+j 是奇数,(i,j)(i,j) 就是黑色。
输入格式
输入的第一行包含一个单独的整数 TT,表示有多少个测试用例。
每个测试用例都包含一个单独的输入行,其中包含四个用空格分隔的整数 AA,BB,PP,QQ。
数据范围保证:1≤T≤50001≤T≤5000,1≤A,B,P,Q≤81≤A,B,P,Q≤8。
输出格式
对于每个测试用例,输出一个单独的行,其中包含一个整数 - 从 (A,B)(A,B) 到 (P,Q)(P,Q) 所需的最小移动次数。
样例输入
3
1 1 8 8
5 7 5 8
3 3 3 3
样例输出
2
1
0
说明
测试用例 1:(1,1)(1,1) 和 (8,8)(8,8) 的颜色是一样的,所以小新不能在一步之内移动棋子。小新首先可以把棋子从 (1,1)(1,1) 移动到 (8,1)(8,1),然后从 (8,1)(8,1) 移动到 (8,8)(8,8),总共需要 22 步。
测试用例 2:(5,7)(5,7) 和 (5,8)(5,8) 的颜色是不同的,所以小新可以在一步之内把棋子从 (5,7)(5,7) 移动到 (5,8)(5,8),总共需要 11 步。
测试用例 3:因为棋子已经处在目标位置 (3,3)(3,3),所以小新不需要移动棋子,总共需要 00 步。
-
解题思路
1.通过for循环,建造结构
2.分类讨论情况,分为以下三种情况
- 两点之和都为奇数 || 两点之和都为偶数–》 结果为2
- 两点位置相同 --〉 结果为0
- 其余情况都是 --》 结果为1
至此解决问题。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main{public static void main(String[] args) {Scanner scan = new Scanner(System.in);int num = scan.nextInt();for(int i=0;i<num;i++) {int a =scan.nextInt();int b =scan.nextInt();int p =scan.nextInt();int q =scan.nextInt();if(a == p&& b==q) {System.out.println(0);}else if(((a+b)%2==0&&(p+q)%2==0)||((a+b)%2!=0&&(p+q)%2!=0)) {System.out.println(2);}else {System.out.println(1);}}scan.close();}}
二、货物摆放
题目描述
小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。
小蓝希望所有的货物最终摆成一个大的长方体。即在长、宽、高的方向上分别堆 LL、WW、HH 的货物,满足 n=L×W×Hn=L×W×H。
给定 nn,请问有多少种堆放货物的方案满足要求。
例如,当 n=4n=4 时,有以下 66 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×11×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。
请问,当 n=2021041820210418 (注意有 16位数字)时,总共有多少种方案?
提示:建议使用计算机编程解决问题。
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
-
解题思路
1.通过尝试发现,直接三层for固然简单,但是计算机会超时,因此我们应该降低算法复杂度,通过发现,这与这个数的因子有关。
2.通过因子迭代寻找答案便会简化很多。
-
本题难点
1.如何求出n的因数。
2.如何存储n的因数(由于无法得出因子个数,故不能用数组直接存储,我们使用列表。
3.定义long的输入格式为nextLong();。
4.掌握求因子的快捷方法。
import java.util.Scanner;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
// 1:无需package
// 2: 类名必须Main, 不可修改public class 蓝桥杯真题_货物摆放 {public static void main(String[] args) {Scanner scan = new Scanner(System.in);ArrayList<Long> list = new ArrayList();long n =2021041820210418l;long res = 0;long sum = 0;for (long i = 1; i <= Math.sqrt(n); i++) {if (n % i == 0) {sum++;list.add(i);}long m = n/i;//根号后if(m!=i&&(m*i)==n) {sum++;list.add(m);}}// System.out.println(sum);for(Object i:list) {for(Object j:list) {for(Object k:list) {if((long)i *(long)j*(long)k==n) {res++;}}}}System.out.println(res);scan.close();}
}
三、特别数的和
题目描述
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 nn 中,所有这样的数的和是多少?
输入描述
输入格式:
输入一行包含两个整数 n(1≤n≤10000)n(1≤n≤10000)。
输出描述
输出一行,包含一个整数,表示满足条件的数的和。
输入输出样例
示例
输入
40
输出
574
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int n = scan.nextInt();long sum = 0;for(int i=1;i<=n;i++) {if(check(i)) {sum =sum + i;}}System.out.print(sum);scan.close();}private static boolean check(int i) {while (i!=0) {int n = i%10;if(n==0||n==1||n==2||n==9) {return true;}i = i/10;}return false;}
}
-
思路总结与难点
1.通过子函数实现判断过程。
2.理解判断一个数的每位数的迭代过程。
3.学会main函数嵌套函数的规范格式。