你连简单的枚举类都不知道,还敢说自己会Java???滚出我的公司

// 私有化构造器是为了保证不能在类的外部创建其对象,否则就不能确定对象的个数

private Season2(String seasonName, String seasonDesc){

this.seasonName=seasonName;

this.seasonDesc=seasonDesc;

}

//其他需求:获取枚举类对象的属性

//只需要提供属性的get方法即可,但是不能提供set方法,而且也不允许提供set方法,因为枚举类是不可变的常量类,不能被修改

public String getSeasonName() {

return seasonName;

}

public String getSeasonDesc() {

return seasonDesc;

}

}

public class SeasonTest {

public static void main(String[] args) {

Season2 spring = Season2.SPRING;

System.out.println(spring);//SPRING

}

}

2、Enum类中的常用方法

values()方法:返回枚举类型的对象数组,该方法可以很方便地遍历所有的枚举值;

//使用方法如下:

Season2[] seasons = Season2.values();

for (int i = 0; i < seasons.length; i++) {

System.out.println(seasons[i]);

}

valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。

如不是,会报运行时异常:IllegalArgumentException;

//使用方法如下:

Season2 spring = Season2.valueOf(“SPRING”);

System.out.println(spring);//SPRING

toString():返回当前枚举类对象的名称

//使用方法如下:

Season2 spring = Season2.SPRING;

System.out.println(spring.toString());//SPRING

3、使用enum关键字定义枚举类实现接口

枚举类和普通类一样,可以实现一个或多个接口。枚举类实现接口分为两种情况:

情况一:若枚举类的所有枚举对象在调用实现的接口方法时,呈现相同的行为方式,则只要统一实现该方法即可;此时与普通类实现接口一样,没有任何区别。

public interface Show {

void show();

}

//使用enum关键字定义枚举类

public enum Season2 implements Show{

//1.提供当前枚举类的对象,多个对象之间使用",“隔开,末尾使用”;"结束

//系统默认使用public static final修饰

SPRING(“春天”,“鸟语花香”),

SUMMER(“夏天”,“夏日炎炎”),

AUTUMN(“秋天”,“秋高气爽”),

WINNER(“冬天”,“寒风瑟瑟”);

//2.声明Season对象的属性,又因为枚举类对象的属性不应允许被改动, 所以应该使用 private final修饰

private final String seasonName;

private final String seasonDesc;

//3.枚举类的构造器只能使用 private 权限修饰符

// 私有化构造器是为了保证不能在类的外部创建其对象,否则就不能确定对象的个数

private Season2(String seasonName, String seasonDesc){

this.seasonName=seasonName;

this.seasonDesc=seasonDesc;

}

//其他需求:获取枚举类对象的属性

//只需要提供属性的get方法即可,但是不能提供set方法,而且也不允许提供set方法,因为枚举类是不可变的常量类,不能被修改

public String getSeasonName() {

return seasonName;

}

public String getSeasonDesc() {

return seasonDesc;

}

//重写show()方法,与普通类实现接口一样,没有任何区别

@Override

public void show() {

System.out.println(“一年四季:春夏秋冬”);

}

}

public class SeasonTest {

public static void main(String[] args) {

Season2 spring = Season2.SPRING;

spring.show();

Season2 summer = Season2.SUMMER;

summer.show();

Season2 autumn = Season2.AUTUMN;

autumn.show();

Season2 winner = Season2.WINNER;

winner.show();

}

}

运行结果:

情况二:若枚举类的每个枚举对象在调用实现的接口方法时,需要呈现出不同的行为方式,则可以让每个枚举对象分别来实现该方法

public interface Show {

void show();

}

//使用enum关键字定义枚举类

public enum Season2 implements Show{

//1.提供当前枚举类的对象,多个对象之间使用",“隔开,末尾使用”;"结束

//系统默认使用public static final修饰

SPRING(“春天”,“鸟语花香”){

//每个枚举对象分别来实现该方法

@Override

public void show() {

System.out.println(“春天是一个鸟语花香的季节!”);

}

},

SUMMER(“夏天”,“夏日炎炎”){

@Override

public void show() {

System.out.println(“夏天是一个夏日炎炎的季节!”);

}

},

AUTUMN(“秋天”,“秋高气爽”){

@Override

public void show() {

System.out.println(“秋天是一个秋高气爽的季节!”);

}

},

WINNER(“冬天”,“寒风瑟瑟”){

@Override

public void show() {

System.out.println(“冬天是一个寒风瑟瑟的季节!”);

}

};

//2.声明Season对象的属性,又因为枚举类对象的属性不应允许被改动, 所以应该使用 private final修饰

private final String seasonName;

private final String seasonDesc;

//3.枚举类的构造器只能使用 private 权限修饰符

// 私有化构造器是为了保证不能在类的外部创建其对象,否则就不能确定对象的个数

private Season2(String seasonName, String seasonDesc){

this.seasonName=seasonName;

this.seasonDesc=seasonDesc;

}

//其他需求:获取枚举类对象的属性

//只需要提供属性的get方法即可,但是不能提供set方法,而且也不允许提供set方法,因为枚举类是不可变的常量类,不能被修改

public String getSeasonName() {

return seasonName;

}

public String getSeasonDesc() {

return seasonDesc;

}

}

public class SeasonTest {

public static void main(String[] args) {

Season2 spring = Season2.SPRING;

spring.show();

Season2 summer = Season2.SUMMER;

summer.show();

Season2 autumn = Season2.AUTUMN;

autumn.show();

Season2 winner = Season2.WINNER;

winner.show();

}

}

运行结果:

image.png

4、枚举类对switch的语句的影响

Java1.5新增enum关键字的同时,也扩大了switch的语句使用范围。Java1.5之前,switch中的值只能是简单数据类型,比如int、byte、short、char, 有了枚举类型之后,就可以使用枚举类的对象了。同时在switch表达式中使用enum定义的枚举类的对象作为表达式时, case子句可以直接使用枚举对象的名字, 无需添加枚举类作为限定。这样一来,程序的控制选择就变得更加的方便,看下面的例子:

public enum WeekDay {

// 定义一周七天的枚举类型

Monday,Tuesday, Wednesday ,Thursday,Friday,Saturday,Sunday;

}

class Test{

public static void getDay(WeekDay weekDay){

switch (weekDay){

case Monday:

System.out.println(“Today is Monday”);

break;

case Tuesday:

System.out.println(“Today is Tuesday”);

break;

case Wednesday:

System.out.println(“Today is Wednesday”);

break;

case Thursday:

System.out.println(“Today is Thursday”);

break;

case Friday:

System.out.println(“Today is Friday”);

break;

case Saturday:

System.out.println(“Today is Saturday”);

break;

case Sunday:

System.out.println(“Today is Sunday”);

break;

default:

System.out.println(“data error”);

}

}

public static void main(String[] args) {

WeekDay sunday = WeekDay.Sunday;

getDay(sunday);

WeekDay friday = WeekDay.Friday;

getDay(friday);

}

}

运行结果:

image.png

对于这些枚举的日期,JVM都会在运行期构造成出一个简单的对象实例一一对应。这些对象都有唯一的identity,类似整型数值一样,switch语句就会根据此来identity进行执行跳转。

5、枚举类的线程安全问题

枚举类天生线程就是安全的,下面我们就来进行验证。

先写一个简单的枚举类,还是以季节类为例:

public enum Season {

SPRING,SUMMER,AUTUMN,WINNER;

}

然后我们使用反编译,看看枚举类代码到底是怎么实现的,反编译后的代码内容如下:

枚举类都不知道,还敢说自己会Java?

public final class zzuli.edu.Season extends java.lang.Enum<zzuli.edu.Season> {

public static final zzuli.edu.Season SPRING;

public static final zzuli.edu.Season SUMMER;

public static final zzuli.edu.Season AUTUMN;

public static final zzuli.edu.Season WINNER;

private static final zzuli.edu.Season[] $VALUES;

public static zzuli.edu.Season[] values();

public static zzuli.edu.Season valueOf(java.lang.String);

private zzuli.edu.Season();

static {};

}

由上述代码可知,每一个枚举类的枚举对象都是被public static final 进行修饰的,又因为被static修饰的属性在类加载的时候就会被加载,而且只会被加载一次,所以枚举类天生就是线程安全的。

6、枚举类实现单例模式

实现单例模式的方法有很多种,但是使用枚举类实现单例模式是最好、最安全的一种方式,这种方式也是Effective Java作者Josh Bloch 提倡的方式。因为它天生线程安全,不仅能避免多线程同步问题,而且还能防止使用反射重新创建新的对象。

使用枚举类实现单例模式非常简单,如下所示:

public enum EnumSingle {

INSTANCE;

public EnumSingle getInstance(){

return INSTANCE;

}

}

下面使用代码进行测试,看创建的对象是否是单例:

public class Test {

public static void main(String[] args) throws NoSuchMethodException {

EnumSingle instance1 = EnumSingle.INSTANCE;

EnumSingle instance2 = EnumSingle.INSTANCE;

System.out.println(instance1==instance2);

}

}

运行结果:

枚举类都不知道,还敢说自己会Java?

由运行结果可知,成功使用了单例模式。接下来测试使用反射能不能创建新的实例对象。

先来看一下使用反射创建实例对象newInstance方法的源码:

[图片上传失败…(image-8ba546-1633679059670)]

由newInstance方法的源码可知,反射在通过newInstance方法创建对象时,会先检查该类是否是枚举类,如果是,则会抛出IllegalArgumentException(“Cannot reflectively create enum objects”)异常,导致使用反射创建对象失败。下面我们就来测试一下:

先看一下枚举类的源码是有参构造函数还是无参构造函数,编译后的源码如下:

枚举类都不知道,还敢说自己会Java?

由源码可知,枚举类的构造函数为无参构造函数,下面就使用反射获取枚举类的无参构造函数,看使用反射是否能创建新的实例对象。

public class Test2 {

public static void main(String[] args) throws Exception {

EnumSingle instance1 = EnumSingle.INSTANCE;

Constructor declaredConstructor = EnumSingle.class.getDeclaredConstructor();

declaredConstructor.setAccessible(true);

EnumSingle instance2 = declaredConstructor.newInstance();

System.out.println(instance1);

System.out.println(instance2);

}

}

运行结果:

枚举类都不知道,还敢说自己会Java?

由运行抛出的异常可知,并不是我们预期的newInstance方法中的IllegalArgumentException(“Cannot reflectively create enum objects”)异常,而是NoSuchMethodException异常,说明枚举类中并没有无参构造函数,编译后的源码欺骗了我们。

接着我们通过javap反编译看一下枚举类的代码

[图片上传失败…(image-182813-1633679059670)]

public final class zzuli.edu.enumTest.EnumSingle extends java.lang.Enum<zzuli.edu.enumTest.EnumSingle> {

public static final zzuli.edu.enumTest.EnumSingle INSTANCE;

private static final zzuli.edu.enumTest.EnumSingle[] $VALUES;

public static zzuli.edu.enumTest.EnumSingle[] values();

public static zzuli.edu.enumTest.EnumSingle valueOf(java.lang.String);

private zzuli.edu.enumTest.EnumSingle();

public zzuli.edu.enumTest.EnumSingle getInstance();

static {};

}

由上述反编译后的枚举类代码可知,反编译后的枚举类中存在的仍然是无参构造函数,说明反编译后的代码仍然骗了我们。下面我们就使用更专业的工具jad来进行反编译。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

Kafka进阶篇知识点

image

Kafka高级篇知识点

image

44个Kafka知识点(基础+进阶+高级)解析如下

image

由于篇幅有限,小编已将上面介绍的**《Kafka源码解析与实战》、Kafka面试专题解析、复习学习必备44个Kafka知识点(基础+进阶+高级)都整理成册,全部都是PDF文档**

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

P-1712891734696)]
[外链图片转存中…(img-byFlyJWm-1712891734697)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-2q18xnGI-1712891734697)]

Kafka进阶篇知识点

[外链图片转存中…(img-loTBIEuF-1712891734697)]

Kafka高级篇知识点

[外链图片转存中…(img-JFY9tmQv-1712891734697)]

44个Kafka知识点(基础+进阶+高级)解析如下

[外链图片转存中…(img-y2gKJ922-1712891734698)]

由于篇幅有限,小编已将上面介绍的**《Kafka源码解析与实战》、Kafka面试专题解析、复习学习必备44个Kafka知识点(基础+进阶+高级)都整理成册,全部都是PDF文档**

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-B3wqjGC9-1712891734698)]

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值