目录
一、枚举介绍
当我们创造一个Season对象的时候,因为Season只有4个(春夏秋冬)常量,不能更改,只能使用,且选择有限,此时创造Season对象就不太合适。
枚举是一组常量的集合,属于一种特殊的类,里面只包含一组有限的特定的对象。
对于季节这种有固定值的,不能更改,就需要使用枚举。
二、实现枚举的两种方式
(一)自定义类实现枚举
步骤:
- 不需要提供setXxx方法,因为枚举对象值通常为只读;
- 对枚举对象/属性使用static+final共同修饰,实现底层优化;
- 枚举对象名通常使用全部大写,遵循常量的命名规范;
- 枚举对象根据需要,也可以有多个属性。
public class TestDemo {
public static void main(String[] args) {
System.out.println(Season.SPRING); // Season{name='春天', desc='温暖'}
System.out.println(Season.SUMMER); // Season{name='夏天', desc='炎热'}
System.out.println(Season.AUTUMN); // Season{name='秋天', desc='凉爽'}
System.out.println(Season.WINTER); // Season{name='冬天', desc='寒冷'}
}
}
// 自定义实现枚举
class Season {
private String name;
private String desc;
// 定义四个对象
public static final Season SPRING = new Season("春天", "温暖");
public static final Season SUMMER = new Season("夏天", "炎热");
public static final Season AUTUMN = new Season("秋天", "凉爽");
public static final Season WINTER = new Season("冬天", "寒冷");
// 1.将构造器私有化,防止直接new传参
// 2.去掉set方法,防止属性被修改
// 3.在Season内部,直接创建固定的对象
// 4.固定的对象用final修饰
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
(二)enum关键字实现枚举
注意事项:
- 当使用enum关键字开发一个枚举类时,默认会隐式继承Enum类,而且是一个final类;
- 常量(参数列表),这里必须知道它调用的是哪个构造器;
- 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略,只写常量名即可;
- 当有多个枚举对象时,使用 , 间隔,最后有一个分号结尾;
- 枚举对象必须放在枚举类的行首。
enum Season2 {
// 定义四个对象
// public static final Season2 SPRING = new Season2("春天", "温暖");
// public static final Season2 SUMMER = new Season2("夏天", "炎热");
// public static final Season2 AUTUMN = new Season2("秋天", "凉爽");
// public static final Season2 WINTER = new Season2("冬天", "寒冷");
/**
* 如果使用enum来实现枚举类
* 1.使用关键字enum替代class
* 2.SPRING("春天", "温暖") => 常量名(实参列表)
* 替代public static final Season2 SPRING = new Season2("春天", "温暖");
* 3.如果有多个常量(对象),使用 , 号分割
* 4.如果使用enum实现枚举,定义的常量对象必须写在前面
*/
SPRING("春天", "温暖"),
SUMMER("夏天", "炎热"),
AUTUMN("秋天", "凉爽"),
WINTER("冬天", "寒冷");
private String name;
private String desc;
Season2(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
因为继承的Enum类中已经提供了toString()方法,所以定义枚举时,不需要写toString()方法
三、enum常用方法说明
1.toString
public static void main(String[] args) {
// 以Season2演示
Season2 winter = Season2.WINTER;
System.out.println(winter); // WINTER
// toString:Enum类已经重写过了,返回的是当前对象名,
// 子类可以重写该方法,用于返回对象的属性信息
System.out.println(Season2.SPRING.toString()); // SPRING
}
2.name
// name:返回当前对象名(常量名),子类中不能重写
System.out.println(winter.name()); // WINTER
3.ordinal
// ordinal:返回当前对象的位置号,默认从0开始编号
System.out.println(winter.ordinal()); // 3
4.value
// values方法:返回当前枚举类中所有的常量
Season2[] values = Season2.values();
for (Season2 season : values) {
System.out.println(season);
}
5.valueOf
// valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
// 如果输入的值不在枚举中,会报错:IllegalArgumentException
Season2 winter1 = Season2.valueOf("WINTER");
System.out.println(winter1); // SUMMER
System.out.println(winter1 == winter); // 返回true 说明是同一个对象
6.compareTo
// compareTo:比较两个枚举常量,比较的就是编号
System.out.println(Season2.SPRING.compareTo(Season2.WINTER)); // 0 - 3 = -3
// return self.ordinal - other.ordinal;
四、Enum练习
题目:声明Week吗,枚举类,其中包含星期一至星期日,使用values返回所有的枚举数组,并遍历,输出星期几。
设置枚举类:
public enum Week {
MONDAY("星期一"),
TUESDAY("星期二"),
WEDNESDAY("星期三"),
THURSDAY("星期四"),
FRIDAY("星期五"),
SATURDAY("星期六"),
SUNDAY("星期日");
private String name;
Week(String name) { // 构造器
this.name = name;
}
@Override // 重写toString
public String toString() {
return name;
}
}
调用枚举类:
public class TestDemo1 {
public static void main(String[] args) {
Week[] values = Week.values();
System.out.println("==所有星期的信息如下==");
for (Week week : values) {
System.out.println(week);
}
}
}
五、enum使用细节——继承、接口
使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。
枚举类和普通类一样,可以实现接口。
public class EnumDetail {
public static void main(String[] args) {
Music.POP.playing(); // 播放音乐...
}
}
interface IPlaying {
public void playing();
}
enum Music implements IPlaying {
POP;
@Override
public void playing() {
System.out.println("播放音乐...");
}
}
六、注解
(一)注解的理解
1)注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。
2) 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。
3) 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替javaEE旧版中所遗留的繁冗代码和XML配置等。
(二)基本的Annotation介绍
使用Annotation时要在前面增加@符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素。
三个基本的Annotation:
1) @Override:限定某个方法,检测是否重写了父类方法,该注解只能用于方法。
@Override源码:这里的 @interface 表示一个注解类。
@Override只能修饰方法,不能修饰其它类、包、属性等等
@Target(ElementType.METHOD)表示只能修饰方法
@Target是修饰注解的注解,成为元注解。
2) @Deprecated:用于表示某个程序元素(类, 方法等)已过时,过时不代表不能用,可以修饰方法、类、字段、包、参数等等。
3) @SuppressWarnings:抑制编译器警告。
使用前:
使用后:
1.当我们不希望看到这些警告的时候,可以使用 SuppressWarnings注解来抑制警告信息
2.在{""} 中,可以写入你希望抑制(不显示)警告信息
3.可以指定的警告类型有:
all,抑制所有警告
boxing,抑制与封装/拆装作业相关的警告
cast,抑制与强制转型作业相关的警告
dep-ann,抑制与淘汰注释相关的警告
deprecation,抑制与淘汰的相关警告
fallthrough,抑制与switch陈述式中遗漏 break 相关的警告
finally,抑制与未传回finally 区块相关的警告
hiding,抑制与隐藏变数的区域变数相关的警告
incomplete-switch,抑制与 switch 陈述式(enum case)中遗漏项目相关的警告
javadoc,抑制与 javadoc 相关的警告
nls,抑制与非nls 字串文字相关的警告
null,抑制与空值分析相关的警告
rawtypes,抑制与使用raw类型相关的警告
resource,抑制与使用 Closeable 类型的资源相关的警告
restriction,抑制与使用不建议或禁止参照相关的警告
serial,抑制与可序列化的类别遗漏serialVersionUID 栏位相关的警告
static-access,抑制与静态存取不正确相关的警告
static-method,抑制与可能宣告为 static 的方法相关的警告
super,抑制与置换方法相关但不含super呼叫的警告
synthetic-access,抑制与内部类别的存取未最佳化相关的警告
sync-override,抑制因为置换同步方法而遗漏同步化的警告
unchecked,抑制与未检查的作业相关的警告
unqualified-field-access,抑制与栏位存取不合格相关的警告
unused,抑制与未用的程式码及停用的程式码相关的警告
4.关于SuppressWarnings 作用范围是和你放置的位置相关
5.比如 @SuppressWarnings放置在main方法,那么抑制警告的范围就是main通常我们可以放置具体的语句、方法、类。
@SuppressWarnings 源码:
(1) 放置的位置就是TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE
(2)该注解类有数组 String[]values()设置一个数组比如{"rawtypes", "unchecked", "unused"}