Java枚举

枚举是什么

  • Java 5 首次引入了 enum 关键字。它表示一种特殊类型的类,枚举扩展自 java.lang.Enum 类。
  • 以这种方式定义的常量使代码更具可读性,允许在编译时进行检查,提前记录下可接受的值列表,并避免因传入无效值而导致的意外行为。

例如,下面用枚举定义了三种颜色:

package com.enumdemo;

public enum Color {
    RED, GREEN, BLUE;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

定义测试类:

package com.enumdemo;

public class Test {

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

编译后:
在这里插入图片描述

用javap反编译Color.class文件:
在这里插入图片描述

  • 枚举类的第一行必须罗列枚举对象的名字,这些名称是常量,并且每个常量记住的都是枚举的一个对象。
  • 枚举类的构造器都是私有的(写不写private都是私有的),因此,枚举类对外不能创建对象。
    例如,下面的枚举类:
package com.enumdemo;

public enum Color {
    RED, GREEN, BLUE;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

用IDEA反编译以后可以看到,构造器是私有的:
在这里插入图片描述

如果用枚举类对外创建对象,会编译报错:
在这里插入图片描述

  • 枚举都是最终类,不可以被继承。
    例如下面的枚举类:
package com.enumdemo;

public enum Color {
    RED, GREEN, BLUE;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

用javap反编译以后,可以看到是被final修饰的:
在这里插入图片描述

  • 在枚举类中,从第二行开始,可以定义类的其它各种成员。

  • 编译器为枚举类新增了几个方法,并且枚举类都是继承java.lang.Enum,所以枚举类会从Enum类继承一些方法。
    例如枚举类:

package com.enumdemo;

public enum Color {
    RED, GREEN, BLUE;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

用javap反编译h以后,可以看到新增、继承的方法:
在这里插入图片描述

枚举在if 和 switch 语句中的使用

以下示例展示了在 ifswitch 语句中使用枚举的方法。

package com.enumdemo;

enum Mobile {
    Huawei,
    Xiaomi,
    Honor
}

public class Test {
    public static void main(String[] args) {
        System.out.println(Mobile.Huawei);

        Mobile mobile = Mobile.Xiaomi;
        if (mobile == Mobile.Xiaomi) {
            System.out.println("匹配成功");
        }

        switch (mobile) {
            case Huawei:
                System.out.println("华为");
                break;
            case Xiaomi:
                System.out.println("小米");
                break;
            case Honor:
                System.out.println("荣耀");
                break;
            default:
        }
    }
}

输出:

Huawei
匹配成功
小米

枚举的构造函数

  • Java枚举是一种特殊类型的类,表示一组预定义的常量值,可以在 switch 表达式中用于比较,也可以作为常量在应用程序代码中使用。
  • 默认情况下,枚举不需要任何构造函数,其默认值与声明时的值相同。例如:
package com.enumdemo;

enum WEEKDAY {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

public class Test {
    public static void main(String[] args) {
        System.out.println(WEEKDAY.MONDAY);
    }
}

输出:

MONDAY

从输出可以看到,如果我们打印上述枚举中的任何一个值,它将打印声明时相同的字符串。

使用枚举的构造函数

  • Java枚举类可以定义构造函数,枚举常量后面括号中的参数值就是传递给构造函数的参数。

现在,如果我们想为枚举分配一个默认值,可以按如下方式创建一个枚举构造函数:

enum WEEKDAY {
    MONDAY("第1天");
    private final String description;

    WEEKDAY(String description) {
        this.description = description;
    }
}

在这种情况下,我们使用构造函数为枚举分配了一个默认描述。

枚举构造函数的访问范围

  • 枚举类的构造函数只能是private的,写不写private这个关键字都一样。如果不明确声明private的,编译器也会编译为private的。
  • 如果声明为其它的访问控制修饰符(例如public、protected),就会编译出错。

例如,下面为枚举构造函数设置public修饰符将导致编译时错误:
在这里插入图片描述

示例:私有构造函数

package com.enumdemo;

enum WEEKDAY {
    MONDAY("第1天"),
    TUESDAY("第2天"),
    WEDNESDAY("第3天"),
    THURSDAY("第4天"),
    FRIDAY("第5天"),
    SATURDAY("第6天"),
    SUNDAY("第7天");

    private final String description;

    private WEEKDAY(String description) {
        this.description = description;
    }

    public String getDescription() {
        return this.description;
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(WEEKDAY.MONDAY);
        System.out.println(WEEKDAY.MONDAY.getDescription());
    }
}

输出:

MONDAY1

Java枚举字符串

Java 枚举是一种特别的构造,用于表示一组预定义的常量字符串,并在应用代码中作为常量使用时提供清晰的代码。默认情况下,枚举的字符串表示形式与其声明相同。

考虑以下示例:

enum WEEKDAY {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;
}

如果我们使用枚举本身、toString()方法或name()方法来打印上述枚举的字符串表示形式,它将打印与声明时相同的字符串:

package com.enumdemo;

enum WEEKDAY {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;

}

public class Test {
    public static void main(String[] args) {
        System.out.println(WEEKDAY.MONDAY);
        System.out.println(WEEKDAY.MONDAY.toString());
        System.out.println(WEEKDAY.MONDAY.name());
    }
}

输出:

MONDAY
MONDAY
MONDAY

重写Enum的toString() 方法

现在,如果我们想要更改默认的字符串表示形式,可以重写toString()方法。

示例:重写toString()方法

package com.enumdemo;

enum WEEKDAY {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;

    @Override
    public String toString() {
        return switch (this) {
            case MONDAY -> {
                yield "第1天";
            }
            case TUESDAY -> {
                yield "第2天";
            }
            case WEDNESDAY -> {
                yield "第3天";
            }
            case THURSDAY -> {
                yield "第4天";
            }
            case FRIDAY -> {
                yield "第5天";
            }
            case SATURDAY -> {
                yield "第6天";
            }
            case SUNDAY -> {
                yield "第7天";
            }
        };
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(WEEKDAY.MONDAY);
        System.out.println(WEEKDAY.THURSDAY);
        System.out.println(WEEKDAY.WEDNESDAY);
    }
}

输出:

1天
第4天
第3

示例:为每个值重写toString()方法

在这个示例中,我们为WEEKDAY枚举的每个值都重写了toString()方法。这样我们就可以用这种方式为每个值自定义字符串表示形式。

package com.enumdemo;

enum WEEKDAY {
    MONDAY {
        @Override
        public String toString() {
            return "第1天";
        }
    },
    TUESDAY {
        @Override
        public String toString() {
            return "第2天";
        }
    },
    WEDNESDAY {
        @Override
        public String toString() {
            return "第3天";
        }
    },
    THURSDAY {
        @Override
        public String toString() {
            return "第4天";
        }
    },
    FRIDAY {
        @Override
        public String toString() {
            return "第5天";
        }
    },
    SATURDAY {
        @Override
        public String toString() {
            return "第6天";
        }
    },
    SUNDAY {
        @Override
        public String toString() {
            return "第7天";
        }
    };
}

public class Test {
    public static void main(String[] args) {
        System.out.println(WEEKDAY.MONDAY);
        System.out.println(WEEKDAY.THURSDAY);
        System.out.println(WEEKDAY.WEDNESDAY);
    }
}

输出:

1天
第4天
第3

使用 == 操作符比较枚举类型

  • 由于枚举类型确保了在 JVM 中每个常量只有一个实例,因此我们可以安全地使用“==”运算符来比较两个变量。
  • 此外,==运算符提供了编译时和运行时的安全性。

示例:用==操作符比较

package com.enumdemo;

enum Color {
    RED,
    GREEN,
    BLUE;
}

public class Test {
    private Color color;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.setColor(Color.RED);

        if (test.getColor() == Color.RED) {
            System.out.println("红色");
        } else {
            System.out.println("不是红色");
        }
    }
}

输出:

红色

示例:用==操作符比较枚举类型带来运行时安全性

我们将在下面的代码中查看运行时安全性,其中我们将使用“==”运算符来比较状态。任何一个值都可能为 null,而且我们不会遇到 NullPointerException。相反,如果我们使用 equals 方法,就会遇到 NullPointerException

package com.enumdemo;

enum Color {
    RED,
    GREEN,
    BLUE;
}

public class Test {
    private Color color = null;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public static void main(String[] args) {
        Test test = new Test();
        // test.setColor(Color.RED);

        System.out.println("color变量的值是:" + test.getColor());

        // 用 == 比较
        if (test.getColor() == Color.RED) {
            System.out.println("红色");
        } else {
            System.out.println("不是红色");
        }

        // 用equals比较
        if (test.getColor().equals(Color.RED)) {
            System.out.println("用equals比较,是红色");
        } else {
            System.out.println("用equals比较,不是红色");
        }
    }
}

输出:

color变量的值是:null
不是红色
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.enumdemo.Color.equals(Object)" because the return value of "com.enumdemo.Test.getColor()" is null
	at com.enumdemo.Test.main(Test.java:32)

示例:用==操作符比较枚举类型带来编译时安全性

下面示例中,定义了两个不同的枚举类型,用==操作符比较的时候,给出编译时错误:

package com.enumdemo;

enum Color {
    RED, GREEN, BLUE;
}

enum TaskStatus {
    RED, GREEN, BLUE;
}

public class Test {
    private Color color = null;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public static void main(String[] args) {
        Test test = new Test();
        if (test.getColor() == TaskStatus.RED) {

        }
    }
}

在这里插入图片描述

在枚举中自定义属性、方法

package com.enumdemo;

enum TaskStatus {
    STARED(20) {
        @Override
        public boolean isStarted() {
            return true;
        }
    },
    RUNNING(10) {
        @Override
        public boolean isRunning() {
            return true;
        }
    },
    FINISHED(0) {
        @Override
        public boolean isFinished() {
            return true;
        }
    };

    private int timeToFinish;

    public boolean isStarted() {
        return false;
    }

    public boolean isRunning() {
        return false;
    }

    public boolean isFinished() {
        return false;
    }

    public int getTimeToFinish() {
        return this.timeToFinish;
    }

    TaskStatus(int timeToFinish) {
        this.timeToFinish = timeToFinish;
    }
}

public class Test {
    private TaskStatus taskStatus;

    public TaskStatus getTaskStatus() {
        return taskStatus;
    }

    public void setTaskStatus(TaskStatus taskStatus) {
        this.taskStatus = taskStatus;
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.setTaskStatus(TaskStatus.RUNNING);
        System.out.println(test.getTaskStatus().getTimeToFinish());
        System.out.println(test.getTaskStatus().isStarted());
        System.out.println(test.getTaskStatus().isRunning());
        System.out.println(test.getTaskStatus().isFinished());
    }
}

输出:

10
false
true
false

抽象枚举

所谓的抽象枚举,就是在枚举中定义抽象方法,在定义枚举常量的时候实现抽象方法。

示例:抽象枚举

package com.enumdemo;

public enum Color {
    RED() {
        @Override
        public void doSomething() {

        }
    },
    GREEN() {
        @Override
        public void doSomething() {

        }
    };

    public abstract void doSomething();
}

示例:抽象枚举和构造函数一起使用

定义抽象枚举:

package com.enumdemo;

public enum Color {
    RED() {
        @Override
        public void doSomething() {

        }
    },
    GREEN("张三") {
        @Override
        public void doSomething() {
            System.out.println(getName() + "向大家问好");
        }
    };

    private String name;

    Color() {
    }

    Color(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract void doSomething();
}

定义测试类:

package com.enumdemo;

public class Test {

    public static void main(String[] args) {
        Color color = Color.GREEN;
        color.doSomething();
    }

}

输出:

张三向大家问好

用枚举实现单例模式

package com.enumdemo;

public enum Singleton {
    INSTANCE;
}

枚举的常见应用场景

用来表示一组信息,然后作为参数进行传递

下面示例定义一个枚举,用来表示系统的状态:

package com.enumdemo;

public enum SystemStatus {
    STARTED, RUNNING, FINISHIED;
}

定义一个测试类:

package com.enumdemo;

public class Test {

    public static void main(String[] args) {
        Test test = new Test();
        test.check(SystemStatus.STARTED);
        test.check(SystemStatus.RUNNING);
        test.check(SystemStatus.FINISHIED);
    }

    public void check(SystemStatus systemStatus) {
        switch (systemStatus) {
            case STARTED -> System.out.println("系统启动了");
            case RUNNING -> System.out.println("系统运行中");
            case FINISHIED -> System.out.println("系统已完成");
        }

    }
}

输出:

系统启动了
系统运行中
系统已完成
### 关于ArcGIS License Server无法启动的解决方案 当遇到ArcGIS License Server无法启动的情况,可以从以下几个方面排查并解决问题: #### 1. **检查网络配置** 确保License Server所在的计算机能够被其他客户端正常访问。如果是在局域网环境中部署了ArcGIS Server Local,则需要确认该环境下的网络设置是否允许远程连接AO组件[^1]。 #### 2. **验证服务状态** 检查ArcGIS Server Object Manager (SOM) 的运行情况。通常情况下,在Host SOM机器上需将此服务更改为由本地系统账户登录,并重启相关服务来恢复其正常工作流程[^2]。 #### 3. **审查日志文件** 查看ArcGIS License Manager的日志记录,寻找任何可能指示错误原因的信息。这些日志可以帮助识别具体是什么阻止了许可服务器的成功初始化。 #### 4. **权限问题** 确认用于启动ArcGIS License Server的服务账号具有足够的权限执行所需操作。这包括但不限于读取/写入特定目录的权利以及与其他必要进程通信的能力。 #### 5. **软件版本兼容性** 保证所使用的ArcGIS产品及其依赖项之间存在良好的版本匹配度。不一致可能会导致意外行为完全失败激活license server的功能。 #### 示例代码片段:修改服务登录身份 以下是更改Windows服务登录凭据的一个简单PowerShell脚本例子: ```powershell $serviceName = "ArcGISServerObjectManager" $newUsername = ".\LocalSystemUser" # 替换为实际用户名 $newPassword = ConvertTo-SecureString "" -AsPlainText -Force Set-Service -Name $serviceName -StartupType Automatic New-ServiceCredential -ServiceName $serviceName -Account $newUsername -Password $newPassword Restart-Service -Name $serviceName ``` 上述脚本仅作为示范用途,请依据实际情况调整参数值后再实施。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值