1.枚举类的使用
- 类的对象只有有限个,确定的。
比如一星期有七天,一年有四季。
- 当需要定义一组常量时,强烈建议使用枚举类。
- 如果枚举类在只有一个对象,则可以作为单例模式的实现方式
1.1 自定义枚举类
- 先定义一个类作为枚举类
- 给这个类加属性(用private final修饰)
- 私有化类的构造器并给对象赋值
- 定义关于类的常量(public static final修饰)
- 提供对象的属性和toString方法
public class SeasonTest {
public static void main(String[] args) {
Seanson spring = Seanson.SPRING;
System.out.println(spring);
}
}
//自定义枚举类
class Seanson{
//1.声明Seanson对象的属性:用private final修饰
private final String seasonName;
private final String seasonDesc;
//2.私有化类的构造器,并给对象属性赋值
private Seanson(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//3.提供当前枚举类的多个对象:public static final的
public static final Seanson SPRING = new Seanson("春天","春暖花开");
public static final Seanson SUMMER = new Seanson("夏天","夏日炎炎");
public static final Seanson AUTUMN = new Seanson("秋天","秋高气爽");
public static final Seanson WINTER = new Seanson("冬天","冰天雪地");
//4.其他诉求1:获取枚举类对象的属性
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//4.其他诉求2:提供toString()
@Override
public String toString() {
return "Seanson{" +
"seasonName='" + seasonName + ''' +
", seasonDesc='" + seasonDesc + ''' +
'}';
}
}
1.2 用关键字enum定义枚举类
定义的枚举类默认继承于Enum类
提供当前枚举类的多个对象,多个对象之间用逗号隔开,分号结束。而且一定要放在枚举类的开头。
public class SeasonTest {
public static void main(String[] args) {
Seanson spring = Seanson.SPRING;
System.out.println(spring);
}
}
//使用enum关键字枚举类
enum Seanson{
//1.提供当前枚举类的多个对象,多个对象之间用逗号隔开,分号结束
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","冰天雪地");
//2.声明Seanson对象的属性:用private final修饰
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器,并给对象属性赋值
private Seanson(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//4.其他诉求1:获取枚举类对象的属性
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//4.其他诉求2:提供toString()
@Override
public String toString() {
return "Seanson{" +
"seasonName='" + seasonName + ''' +
", seasonDesc='" + seasonDesc + ''' +
'}';
}
}
1.3 Enum类的主要方法
- values():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值。
比如我想遍历一下线程的状态,Thread类里的State就是一个枚举类。可以Thread.State.values()引入局部变量去打印出线程的状态。
- valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException
- toString():返回当前枚举类对象常量的名称
比如上面的代码里我把其他诉求2里的toString()方法删掉,这样在主函数打印枚举类对象时只会出现枚举类中常量的名称
👇下方演示代码中Season类除了把重写的toString()方法删掉,其他和上面的一样
public static void main(String[] args) {
Seanson spring = Seanson.SPRING;
System.out.println(spring.toString());
System.out.println("*******************");
//values()
Seanson[] values = Seanson.values();
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]);
}
System.out.println("*******************");
Thread.State[] values1 = Thread.State.values();
for (int i = 0; i < values1.length; i++) {
System.out.println(values1[i]);
}
System.out.println("*******************");
//valueOf(String str):根据提供的str,返回枚举类中对应此str的常量名
//如果没有str的枚举类镀锡,则抛异常IllegalArgumentException
Seanson winter = Seanson.valueOf("WINTER");
System.out.println(winter);
}
1.4 实现接口的枚举类
- 比如我写了一个接口,打算让一个用enum定义的枚举类去实现它,则要重写抽象方法。
阅读下方代码,看Season类最后面重写了接口Info的方法
interface Info{
void show();
}
//使用enum关键字枚举类
enum Seanson implements Info{
//1.提供当前枚举类的多个对象,多个对象之间用逗号隔开,分号结束
SPRING("春天","春暖花开"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","冰天雪地");
//2.声明Seanson对象的属性:用private final修饰
private final String seasonName;
private final String seasonDesc;
//3.私有化类的构造器,并给对象属性赋值
private Seanson(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//4.其他诉求1:获取枚举类对象的属性
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
//4.其他诉求2:提供toString()
@Override
public String toString() {
return "Seanson{" +
"seasonName='" + seasonName + ''' +
", seasonDesc='" + seasonDesc + ''' +
'}';
}
@Override
public void show() {
System.out.println("显示季节");
}
}
- 让枚举类的对象分别实现接口中的方法
注意如果重写了show方法,要把Season重写的删去,让这些类单独重写
SPRING("春天","春暖花开"){
@Override
public void show() {
System.out.println("这是春天");
}
},
SUMMER("夏天","夏日炎炎"){
@Override
public void show() {
System.out.println("这是夏天");
}
},
AUTUMN("秋天","秋高气爽"){
@Override
public void show() {
System.out.println("这是秋天");
}
},
WINTER("冬天","冰天雪地"){
@Override
public void show() {
System.out.println("这是冬天");
}
};
2.注解
定义:注解就是代码里的特殊标记。
注解可以修饰:包、类、构造器、方法、成员变量、参数,局部变量的声明
重要性:未来的开发模式都是基于注解的,一定程度上可以说:框架 = 注解 + 反射 + 设计模式
2.1 常见的注解示例
- 生成文档相关的注解
名称 | 作用 |
---|---|
@author | 表明开发该类模块的作者,多个作者用逗号分割 |
@version | 表明该类模块的版本 |
@see | 参考转向,也就是相关主题 |
@since | 从哪个版本开始增加的 |
@param | 对方法中某参数的说明,如果没有参数就不能写 |
@return | 对方法返回值的说明,返回是void就不能写 |
@exception | 对方法可能抛出的异常进行说明,必须是用throws显式抛出 |
- @param格式:@param 形参名 形参类型 形参说明
- @return格式:@return 返回值类型 返回值说明
- @exception格式:@exception 异常类型 异常说明
- @param和@exception可以并列多个
- 编译时进行格式检查(jdk内置的三个基本注解)
名称 | 作用 |
---|---|
@Override | 限定重写父类方法,只能用于方法 |
@Deprecated | 表示所修饰的元素(类、方法等)已经过时 |
@SuppressWarnings | 抑制编译器警告 |
2.2 自定义注解
参照@SuppressWarnings定义
在新建时,我们可以选择创建类、接口、枚举类或是注解
比如我现在创建一个名字叫MyAnnotation的注解
public @interface MyAnnotation {
String value();
}
String value();是一个属性,在我使用这个自定义注解时必须要给参数,给value赋值,即(value = “xxxx”)的格式
当然也可以指定成员的默认值,使用default定义,即String value() default “xxx”;的格式
当一个自定义注解没有成员,表明是一个标识作用。
如果有成员,在使用注解时,需要指明成员的值。
注:自定义的注解必须配上注解的信息处理流程(使用反射)才有意义。
2.3 JDK中的元注解
对现有的注解进行解释说明的注解叫元注解
JDK5.0提供了4个标准的元注解类型:
- Retention
- Target
- Documented
- Inherited
- Retention:指定所修饰的注解的生命周期
- SOURCE:编译时抛弃
- CLASS:默认,运行时抛弃
- RUNTIME:加载到内存中,可通过反射读取
- Target:说明被修饰的注解可以修饰哪些程序元素
- Documented:指定被修饰的注解被javadoc解析时,保留下来
- Inherited:被它修饰的注解具有继承性,被修饰的注解的子类会自动具有该注解
2.4 JDK8中注解的新特性
- 可重复注解
在自定义注解MyAnnotation上声明@Repeatable,成员值为MyAnnotations.class
public @interface MyAnnotations {
String[] value();
}
MyAnnotation的Target和Retention和MyAnnotations相同
- 类型注解
- ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型声明)
- ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中