襄阳谷城网站建设,wordpress获取页面链接,做企业官网需要什么手续,营销型网站建设 网络服务枚举的使用 1 背景及定义2 使用3 枚举优点缺点4 枚举和反射4.1 枚举是否可以通过反射#xff0c;拿到实例对象呢#xff1f; 5 总结面试问题(单例模式学完后可以回顾)#xff1a; 1 背景及定义
public static final int RED 1;
public static final int GREEN 2;
public … 枚举的使用 1 背景及定义2 使用3 枚举优点缺点4 枚举和反射4.1 枚举是否可以通过反射拿到实例对象呢 5 总结面试问题(单例模式学完后可以回顾) 1 背景及定义
public static final int RED 1;
public static final int GREEN 2;
public static final int BLACK 3;
但是常量举例有不好的地方例如可能碰巧有个数字1但是他有可能误会为是RED现在我们可以直接用枚举 来进行组织这样一来就拥有了类型枚举类型。而不是普通的整形1.
public enum TestEnum {RED,BLACK,GREEN;
}优点将常量组织起来统一进行管理
场景错误状态码消息类型颜色的划分状态机等等…
本质是 java.lang.Enum 的子类也就是说自己写的枚举类就算没有显示的继承 Enum 但是其默认继承了这个类。
2 使用
1、switch语句
public enum TestEnum {
RED,BLACK,GREEN,WHITE;
public static void main(String[] args) {
TestEnum testEnum2 TestEnum.BLACK;switch (testEnum2) {case RED:System.out.println(red);break;case BLACK:System.out.println(black);break;case WHITE:System.out.println(WHITE);break;case GREEN:System.out.println(black);break;default:break;}
}
}2、常用方法
Enum 类的常用方法 示例一
public enum TestEnum {RED,BLACK,GREEN,WHITE;public static void main(String[] args) {TestEnum[] testEnum2 TestEnum.values();for (int i 0; i testEnum2.length; i) {System.out.println(testEnum2[i] testEnum2[i].ordinal());}System.out.println();System.out.println(TestEnum.valueOf(GREEN));}
}示例二
public enum TestEnum {RED,BLACK,GREEN,WHITE;public static void main(String[] args) {//拿到枚举实例BLACKTestEnum testEnum TestEnum.BLACK;//拿到枚举实例REDTestEnum testEnum21 TestEnum.RED;System.out.println(testEnum.compareTo(testEnum21));System.out.println(BLACK.compareTo(RED));System.out.println(RED.compareTo(BLACK));}
}刚刚说过在Java当中枚举实际上就是一个类。所以我们在定义枚举的时候还可以这样定义和使用枚举
重要枚举的构造方法默认是私有的
public enum TestEnum {RED(red,1),BLACK(black,2),WHITE(white,3),GREEN(green,4);private String name;private int key;/*** 1、当枚举对象有参数后需要提供相应的构造函数* 2、枚举的构造函数默认是私有的 这个一定要记住* param name* param key*/private TestEnum (String name,int key) {this.name name;this.key key;}public static TestEnum getEnumKey (int key) {for (TestEnum t: TestEnum.values()) {if(t.key key) {return t;}}return null;}public static void main(String[] args) {System.out.println(getEnumKey(2));}
}3 枚举优点缺点
优点
枚举常量更简单安全 。枚举具有内置方法 代码更优雅
缺点
不可继承无法扩展
4 枚举和反射
4.1 枚举是否可以通过反射拿到实例对象呢
我们刚刚在反射里边看到了任何一个类哪怕其构造方法是私有的我们也可以通过反射拿到他的实例对象那么枚举的构造方法也是私有的我们是否可以拿到呢接下来我们来实验一下
public enum TestEnum {RED(red,1),BLACK(black,2),WHITE(white,3),GREEN(green,4);private String name;private int key;/*** 1、当枚举对象有参数后需要提供相应的构造函数* 2、枚举的构造函数默认是私有的 这个一定要记住* param name* param key*/private TestEnum (String name,int key) {this.name name;this.key key;}public static TestEnum getEnumKey (int key) {for (TestEnum t: TestEnum.values()) {if(t.key key) {return t;}}return null;}public static void reflectPrivateConstructor() {try {Class? classStudent Class.forName(TestEnum);//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类是提供了两个参数分别是String和int。Constructor? declaredConstructorStudent classStudent.getDeclaredConstructor(String.class,int.class);//设置为true后可修改访问权限declaredConstructorStudent.setAccessible(true);Object objectStudent declaredConstructorStudent.newInstance(绿色,666);TestEnum testEnum (TestEnum) objectStudent;System.out.println(获得枚举的私有构造函数testEnum);} catch (Exception ex) {ex.printStackTrace();}}public static void main(String[] args) {reflectPrivateConstructor();}
}输出结果 java.lang.NoSuchMethodException: TestEnum.(java.lang.String, int) at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.getDeclaredConstructor(Class.java:2178) at TestEnum.reflectPrivateConstructor(TestEnum.java:40) at TestEnum.main(TestEnum.java:54) 老铁们啊看到没有哇异常信息是 java.lang.NoSuchMethodException: TestEnum.(java.lang.String, int) ,什么意思是就是没有对应的构造方法我的天呐我们提供的枚举的构造方法就是两个参数分别是 String 和 int啊问题出现在哪里呢还记不记得我们说过的我们所有的枚举类都是默认继承与 java.lang.Enum ,说到继承继承了什么继承了父类除构造函数外的所有东西并且子类要帮助父类进行构造而我们写的类并没有帮助父类构造那意思是我们要在自己的枚举类里面提供super吗不是的枚举比较特殊虽然我们写的是两个但是默认他还添加了两个参数哪两个参数呢我们看一下Enum类的源码
protected Enum(String name, int ordinal) {this.name name;this.ordinal ordinal;
}也就是说我们自己的构造函数有两个参数一个是String一个是int同时他默认后边还会给两个参数一个是 String一个是int。也就是说这里我们正确给的是4个参数
public static void reflectPrivateConstructor() {try {Class? classStudent Class.forName(TestEnum);//注意传入对应的参数,获得对应的构造方法来构造对象,当前枚举类是提供了两个参数分别是String和int。Constructor? declaredConstructorStudent classStudent.getDeclaredConstructor(String.class,int.class,String.class,int.class);//设置为true后可修改访问权限declaredConstructorStudent.setAccessible(true);//后两个为子类参数大家可以将当前枚举类的key类型改为double验证Object objectStudent declaredConstructorStudent.newInstance(父类参数,666,子类参数,888);TestEnum testEnum (TestEnum) objectStudent;System.out.println(获得枚举的私有构造函数testEnum);} catch (Exception ex) {ex.printStackTrace();}
}此时运行程序结果是\ java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:416) at TestEnum.reflectPrivateConstructor(TestEnum.java:46) at TestEnum.main(TestEnum.java:55) 嗯没错他还报错了不过这次就是我想要的结果此时的异常信息显示是我的一个方法这个方法是 newInstance() 报错了没错问题就是这里我们来看一下这个方法的源码为什么会抛出 java.lang.IllegalArgumentException: 异常呢
源码显示 是的枚举在这里被过滤了你不能通过反射获取枚举类的实例这道题是2017年阿里巴巴曾经问到的一个问 题不看不知道一看吓一跳同学们记住这个坑。**原版问题是为什么枚举实现单例模式是安全的**希望同学们记住这个问题
5 总结
1、枚举本身就是一个类其构造方法默认为私有的且都是默认继承与 java.lang.Enum 2、枚举可以避免反射和序列化问题 3、枚举的优点和缺点
面试问题(单例模式学完后可以回顾)
后面博主在多线程时会讲到单例模式 1、写一个单例模式。
public class Singleton {private volatile static Singleton uniqueInstance;private Singleton() {}public static Singleton getInstance() {if (uniqueInstance null) {synchronized (Singleton.class){if(uniqueInstance null){//进入区域后再检查一次如果仍是null,才创建实例uniqueInstance new Singleton();}}}return uniqueInstance;}
}2、用静态内部类实现一个单例模式
博主之前讲过各种内部类包扩静态内部类大家可以去翻翻之前的博客看一下
class Singleton {/** 私有化构造器 */private Singleton() {}/** 对外提供公共的访问方法 */public static Singleton getInstance() {return UserSingletonHolder.INSTANCE;}/** 写一个静态内部类里面实例化外部类 */private static class UserSingletonHolder {private static final Singleton INSTANCE new Singleton();}
}
public class Main {public static void main(String[] args) {Singleton u1 Singleton.getInstance();Singleton u2 Singleton.getInstance();System.out.println(两个实例是否相同 (u1u2));}
}3、用枚举实现一个单例模式
public enum TestEnum {INSTANCE;public TestEnum getInstance(){return INSTANCE;
}public static void main(String[] args) {TestEnum singleton1TestEnum.INSTANCE;TestEnum singleton2TestEnum.INSTANCE;System.out.println(两个实例是否相同(singleton1singleton2));}
}