当前位置: 首页 > news >正文

java 之枚举问题(超详细!!!!)

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.972E24
        System.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函数嵌套函数的规范格式。

相关文章:

  • MySQL(索引)
  • 华为ISC+战略规划项目数字化转型驱动的智慧供应链革新(169页PPT)(文末有下载方式)
  • 架构师面试(十七):总体架构
  • numpy学习笔记4:np.arange(0, 10, 2) 的详细解释
  • 深度学习零碎知识
  • 【C语言】自定义类型:结构体
  • Android 15 获取网络切片信息的标准接口
  • 《C语言中的ASCII码表:解锁字符与数字的桥梁》
  • Netty基础—Netty实现消息推送服务
  • go语言中数组、map和切片的异同
  • Mobile-Agent-V:通过视频引导的多智体协作学习移动设备操作
  • PCDN 在去中心化互联网中的角色
  • 个人.clang-format配置,适合Linux C/C++
  • 韩顺平教育-家居网购
  • 搜广推校招面经五十四
  • 【从0到1学Redis】Redis基础篇
  • 生信分析服务作图TCGA/GEO数据库挖掘细胞测序转录学代做指导辅导
  • 靶场(十三)---小白心得思路分享---Levram
  • 基于Netty实现高性能HTTP反向代理
  • Python-素数
  • 长三角铁路今日预计发送旅客420万人次,有望创单日客发量新高
  • 亚马逊拟为商品标注“关税成本”,特朗普致电贝索斯讨说法
  • 民生访谈|支持外贸企业拓内销,上海正抓紧制定便利措施
  • 比黄油年糕热量还高,这个火爆全网的甜品劝你慎吃
  • 孙磊已任中国常驻联合国副代表、特命全权大使
  • 三大白电巨头去年净利近900亿元:美的持续领跑,格力营收下滑