Java枚举and单例
枚举
什么是枚举?
所谓的枚举,就是把某个类所有的对象一一罗列出来。
枚举类:这个类的对象是有限的。
定义枚举的语法格式
public enum 枚举类类名{值1, 值2, 值3, 值4;
}
示例
public enum Season {SPRING, SUMMER, AUTUMN, WINTER;
}
枚举的使用
枚举一般是配合switch…case使用的。
public class TestEnum {public static void main(String[] args) {Season s = Season.SPRING;switch(s) {case SPRING:{System.out.println("春天想去小河边散步");break;}case SUMMER:{System.out.println("夏天我想逆流而上");break;}case AUTUMN:{System.out.println("秋天想去拍婚纱照");break;}case WINTER:{System.out.println("冬天去三亚玩");break;}}}
}
枚举的剖析
枚举的本质是一个类,这个类继承于Enum。
public final class Season extends Enum
{public static final Season SPRING;public static final Season SUMMER;public static final Season AUTUMN;public static final Season WINTER;private static final Season ENUM$VALUES[];private Season(String s, int i){super(s, i);}public static Season[] values(){Season aseason[];int i;Season aseason1[];System.arraycopy(aseason = ENUM$VALUES, 0, aseason1 = new Season[i = aseason.length], 0, i);return aseason1;}public static Season valueOf(String s){return (Season)Enum.valueOf(com/lanu/enumeration/Season, s);}static {SPRING = new Season("SPRING", 0);SUMMER = new Season("SUMMER", 1);AUTUMN = new Season("AUTUMN", 2);WINTER = new Season("WINTER", 3);ENUM$VALUES = (new Season[] {SPRING, SUMMER, AUTUMN, WINTER});}
}
上述代码是对Season反编译的结果,从反编译的结果可以看出:枚举本质上是一个类。每一个枚举值本质上是一个(public static final)对象。
既然是对象,就可以调用方法,方法要么是自己定义的,要么是继承于父类的方法。
它的父类提供了2个常用的方法:
String name(); //获取枚举值的名字
int ordinal(); //获取枚举值的序号,序号从0开始。
由于枚举本质上是一个类,所以枚举可以添加属性,添加方法,添加构造器等,类所能做的事情,它都可以做。
下面为Season添加属性,方法以及构造器:
public enum Season {SPRING("春"), SUMMER("夏"), AUTUMN("秋"), WINTER("冬");private String name;//自定义属性private Season(String name) {//自定义构造器this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void test() {//自定义方法System.out.println("hello,my name is " + this.name());}
}
反编译后的结果如下:
import java.io.PrintStream;public final class Season extends Enum
{public static final Season SPRING;public static final Season SUMMER;public static final Season AUTUMN;public static final Season WINTER;private String name;private static final Season ENUM$VALUES[];private Season(String s, int i, String name){super(s, i);this.name = name;}public String getName(){return name;}public void setName(String name){this.name = name;}public void test(){System.out.println((new StringBuilder("hello,my name is")).append(name()).toString());}public static Season[] values(){Season aseason[];int i;Season aseason1[];System.arraycopy(aseason = ENUM$VALUES, 0, aseason1 = new Season[i = aseason.length], 0, i);return aseason1;}public static Season valueOf(String s){return (Season)Enum.valueOf(com/lanu/enumeration/Season, s);}static {SPRING = new Season("SPRING", 0, "春");SUMMER = new Season("SUMMER", 1, "夏");AUTUMN = new Season("AUTUMN", 2, "秋");WINTER = new Season("WINTER", 3, "冬");ENUM$VALUES = (new Season[] {SPRING, SUMMER, AUTUMN, WINTER});}
}
枚举的总结
枚举就是一种数据类型,只不过这种数据类型把可能出现的值提前定义好了,用的时候拿类直接访问即可。枚举多用于switch…case和if语句。
单例
什么是单例?
单例是一种设计模式, 指的是单个实例。如果一个类只能创建一个对象,这样的类叫单例类,这个类的对象就是单例。
如何把一个类定义成单例类呢?
- 构造器私有化。(禁用new)。提供一个私有的构造器,这样外界就无法创建对象了。
- 提供一个获取本类对象的静态方法。(方法内部要保证对象的唯一性)。
懒汉模式的单例
所谓懒汉模式,也叫懒加载,也叫延迟加载,即:在首次用到的时候才加载。懒汉模式的好处:节省内存空间,首次用到的时候才创建对象,如果一直没有用到,就一直不创建对象。缺点:代码较多。
public class Singleton {// 第二步定义一个 本类类型的静态属性。private static Singleton s = null;// 第一步 禁用new,让外界无法创建对象private Singleton() {}//第三步 提供一个获取本类对象的方法public static Singleton sharedSingleton() {//如果s为空,说明尚未创建对象,如果s不为空,说明已经创建过对象,直接使用对象即可。if(s == null) {s = new Singleton();}return s; }
}
上述代码定义了一个单例类,这个类只能创建一个对象(通过Singleton.sharedSingleton()创建对象)。
上述的单例类在单线程模式下是没有问题的,但是在多线程环境中,有可能会出现不止一个对象。在多个线程中同时获取对象时,有可能不止一个对象产生(即执行了多次new)。
可以通过添加同步代码块(或同步方法)的方式来应对多线程环境。
public class Singleton {// 第二步定义一个 本类类型的静态属性。private static Singleton s = null;// 第一步 禁用new,让外界无法创建对象private Singleton() {}// 第三步 提供一个获取本类对象的方法(多线程安全的写法)public static synchronized Singleton sharedSingleton() {// 如果s为空,说明尚未创建对象,如果s不为空,说明已经创建过对象,直接使用对象即可。if (s == null) {s = new Singleton();}return s;}}
上述代码是同步代码块的方式解决多线程环境下有可能产生多个对象的问题。
在某个线程执行 Singleton.sharedSingleton()的时候,加锁,这样别的线程就会处于等待状态,从而保证只创建一个对象。但是问题是,唯一的对象创建出来以后,每次调用Singleton.sharedSingleton()获取对象的时候仍然会加锁,无形之中降低了获取单例对象的效率。
改进代码如下:
public class Singleton {// 第二步定义一个 本类类型的静态属性。private static Singleton s = null;// 第一步 禁用new,让外界无法创建对象private Singleton() {}// 第三步 提供一个获取本类对象的方法(多线程安全的写法)public static Singleton sharedSingleton() {// 如果s为空,说明尚未创建对象,如果s不为空,说明已经创建过对象,直接使用对象即可。if (s == null) {synchronized (Singleton.class) {if(s == null) {s = new Singleton();}}}return s;}
}
这个代码既保证了创建对象时的唯一性,又提升了获取对象的效率。即创建对象的时候上锁,一旦对象创建完毕以后,获取对象就不会触发上锁的代码。
饿汉模式的单例
在类加载的时候,就把对象创建好,用的时候,直接返回这个类的对象。
public class Singleton2 {//第二步,创建一个对象private static Singleton2 s = new Singleton2();//第一步,禁用newprivate Singleton2() {}//返回这个类的对象public static Singleton2 sharedSington2() {return s;}
}
饿汉模式的好处:代码少,多线程下是安全的。缺点:只要类一加载,对象就创建出来了,哪怕后面一直没有调用Singleton2.sharedSingleton2();对象也存在于内存中。
面试的时候,面试官想让你写懒汉模式。实际开发中都写饿汉模式。系统的单例类也通常写饿汉模式。饿汉模式的缺点是个伪命题,既然你写了单例类,肯定是项目中要使用单例对象。
变形的懒汉模式
public class Singleton3 {//第一步 禁用newprivate Singleton3() {}//第二步 定义一个静态内部类private static class SingletonLoader {static Singleton3 s = new Singleton3();}//第三步 提供一个获取单例对象的方法public Singleton3 sharedSingleton3() {return SingletonLoader.s;}
}
这种模式结合了懒汉模式的延迟加载优点以及饿汉模式代码简洁以及多线程安全的特点。
单例有什么用?
只能创建一个实例的类有什么用呢?
单例是比较常用的设计模式,主要处理不同类(不同页面)之间传递数据。
单例传值的思路
把要存储的值以及要读取的值都放到单例对象里。只需要给单例对象添加属性以及getter、setter方法即可。存的时候使用单例对象的setter方法,读取的时候,使用单例对象的getter方法。
public class Singleton {private String privence;//用于存取省份private String city;//用于存取城市private String street;//用于存取区public String getPrivence() {return privence;}public void setPrivence(String privence) {this.privence = privence;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getStreet() {return street;}public void setStreet(String street) {this.street = street;}// 第二步定义一个 本类类型的静态属性。private static Singleton s = null;// 第一步 禁用new,让外界无法创建对象private Singleton() {}// 第三步 提供一个获取本类对象的方法(多线程安全的写法)public static Singleton sharedSingleton() {// 如果s为空,说明尚未创建对象,如果s不为空,说明已经创建过对象,直接使用对象即可。if (s == null) {synchronized (Singleton.class) {if(s == null) {s = new Singleton();}}}return s;}}
public class TestSingleton {public static void main(String[] args) {//假定第一个页面要把省份传递给第二个页面。//不直接传给第二个页面,而是把省份信息放到单例对象里。Singleton s1 = Singleton.sharedSingleton();s1.setPrivence("江苏");//这是第二个页面,我要根据省份来确定显示哪些城市。Singleton s2 = Singleton.sharedSingleton();String privence = s2.getPrivence();//显示该省份的城市列表。//假定已经选择某个城市,不直接把城市传递给第三个页面,而是存到单例里。s2.setCity("南京市");//这是第三个页面,我要根据城市来确定显示哪些区。Singleton s3 = Singleton.sharedSingleton();String city = s3.getCity();s3.setStreet("玄武区");//显示该城市下的全部区。//假定已经选择了区,要把选择的省市区都返回到最初的页面。不是把每个页面的数据返回到最初的页面//而是这些信息放单例里,最初的页面去单例里取就可以了。 //假定这是最初的页面,你要显示用户选择的省市区。Singleton s4 = Singleton.sharedSingleton();String p = s4.getPrivence();String c = s4.getCity();String s = s4.getStreet();}}
Java枚举and单例相关推荐
- 面试官:为啥需要枚举?枚举有什么作用?怎么用枚举实现单例?
点赞再看,养成习惯,微信搜索[三太子敖丙]关注这个互联网苟且偷生的工具人. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的 ...
- 笔记:Java中的单例设计模式
之前接触过单例模式,当初不明白这样的设计用意,今天特地研究了下java中的单例设计模式的用处及用法. 单例模式:单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.一个类 ...
- JAVA设计模式之单例设计模式
单例模式,是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例. 在JAVA中实现单例,必须了 ...
- 黑马程序员,黑马论坛--------枚举和单例设计模式的区别
文章来源:黑马程序员,黑马论坛 枚举和单例设计模式的区别,黑马面试有的 public class Test11 { public static void main(String[] args) { ...
- 【Effective Java】3.单例
传统单例 private 构造函数 最优单例实现:使用Enum 1.无需担心序列化 先说说传统单例,其如果序列化再反序列化产生的效果和构造一个新的对象差不多的.除非增加以下来阻止: //readRes ...
- 【单例深思】枚举实现单例原理
单例的枚举实现在<Effective Java>中有提到,因为其 功能完整.使用简洁.无偿地提供了序列化机制.在面对复杂的序列化或者反射攻击时仍然可以绝对防止多次实例化等优点, 单元素的枚 ...
- 【单例】JAVA中的单例
单例模式,属于创建类型的一种常用的软件设计模式.通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例. Java中单例模式定义:& ...
- java 防止反射_如何防止JAVA反射对单例类的攻击?
在我的上篇随笔中,我们知道了创建单例类有以下几种方式: (1).饿汉式; (2).懒汉式(.加同步锁的懒汉式.加双重校验锁的懒汉式.防止指令重排优化的懒汉式); (3).登记式单例模式; (4).静态 ...
- java中的单例_细说Java中的几种单例模式
在Java中,单例模式分为很多种,本人所了解的单例模式有以下几种,如有不全还请大家留言指点: 饿汉式 懒汉式/Double check(双重检索) 静态内部类 枚举单例 一.饿汉式 image 饿汉式 ...
最新文章
- opencv_imread出错(release/debug、X86/X64)
- cout 输出指定位数,不足补0
- redis实践及思考
- 苹果出5g手机吗_华为打响5G手机第一枪,苹果却扔出620亿“王炸”,任正非:榜样...
- 进一步理解CSS浮动与清除浮动
- 功放音量调节原理_汽车音响知识关于功放和低音喇叭的匹配
- 【JAVA SE】第十一章 正则表达式、包装类和BigDecimal
- 敏捷开发“松结对编程”实践之二:计划与设计篇(大型研发团队,学习型团队,139团队,师徒制度,设计评审,预想陈述,共同估算,扑克牌估算)...
- 洛谷——P1144 最短路计数
- 机器学习中数据标准化相关方法
- eyoucms留言模版验证码实现
- Elasticsearch-7(全文搜索应用分享)
- 李智慧 - 架构师训练营 第六周
- 教师公开课教学课件PPT模板
- Mongodb std::exception::what(): basic_filebuf::underflow error reading the file: iostream error
- 白盒测试方法的简单理解(通俗易懂)
- 字符串转化int类型(整数)
- 001 JAVA知识体系
- lc1819——枚举因数并判定,两种解法
- 令人拍案叫绝的 Wasserstein GAN,彻底解决GAN训练不稳定问题