一、枚举类:
1.枚举类的使用
类的对象只有有限个,确定的。比如:星期、性别、季节
当需要定义一组常量时,强烈建议使用枚举类。
定义枚举类的方法:
一:jdk5.0之前,自定义枚举类
package com.ypl.meiju; /** * 一、枚举类的使用 * 1.枚举类的理解:类的对象只有有限个,确定的,我们称此类为枚举类 * 2.当需要定义一组常量时,强烈建议使用枚举类 * 3.如果枚举类中只有一个对象,则可以作为单例模式的实现方式 * 二、如何定义枚举类 * 方式一:jdk5.0之前,自定义枚举类 * 方式二:jdk5.0,可以使用enum关键字定义枚举类 */ public class SeasonTest { public static void main(String[] args) { Season spring = Season.AUTUMN; System.out.println(spring); } } //自定义枚举类 class Season{ //1.声明Season对象的属性:private final修饰 private final String seasonName; private final String seasonDesc; //2.私有化类的构造器,并给对象属性赋值 private Season(String seasonName,String seasonDesc){ this.seasonName=seasonName; this.seasonDesc=seasonDesc; } //3.提供当前枚举类的多个对象:public static final的 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("冬天","冰天雪地"); //4.其他诉求:获取枚举类对象的属性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //5.其他诉求二:提供toString() @Override public String toString() { return "Season{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; } }
运行之后如下所示:
二:使用enum关键字定义枚举类
package com.ypl.meiju; /** * 使用enum关键字定义枚举类 * 说明:定义的枚举类默认继承于java.lang.Enum类 */ public class SeasonTest1 { public static void main(String[] args) { Season1 summer = Season1.SUMMER; System.out.println(summer); System.out.println(Season1.class.getSuperclass()); } } //使用enum关键字定义枚举类 enum Season1{ //1.提供当前枚举类的对象,多个对象之间用","隔开,末尾对象";"结束 SPRING("春天","春暖花开"), SUMMER("夏天","夏日炎炎"), AUTUMN("秋天","秋高气爽"), WINTER("冬天","冰天雪地"); //2.声明Season对象的属性:private final修饰 private final String seasonName; private final String seasonDesc; //2.私有化类的构造器,并给对象属性赋值 private Season1(String seasonName,String seasonDesc){ this.seasonName=seasonName; this.seasonDesc=seasonDesc; } //4.其他诉求:获取枚举类对象的属性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //5.其他诉求二:提供toString() //可以进行重写,也可以不进行重写。 /* @Override public String toString() { return "Season1{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; }*/ }
运行之后如下所示:
三、Enum类中的常用方法:
values()方法:返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值
valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常
toString():返回当前枚举类对象常量的名称
package com.ypl.meiju; /** * 使用enum关键字定义枚举类 * 说明:定义的枚举类默认继承于java.lang.Enum类 * * 三、Enum类中的常用方法 *values()方法:返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值 *valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常 *toString():返回当前枚举类对象常量的名称 *我们之前在学习多线程的时候,Thread.State: *源码如下所示: *public enum State { *四、使用enum关键字定义的枚举类实现接口的情况 * 情况一:实现接口,在enum类中实现抽象方法 * 情况二:让枚举类的对象分别实现接口中的抽象方法 */ public class SeasonTest1 { public static void main(String[] args) { Season1 summer = Season1.SUMMER; System.out.println(summer); System.out.println(Season1.class.getSuperclass()); System.out.println("toString方法如下所示:"); //toString()方法 System.out.println(summer.toString()); //values()方法 System.out.println("***********"); Season1[] values = Season1.values(); for (int i=0;i< values.length;i++){ System.out.println(values[i]); } System.out.println("$$$$$$$$$$$$$$$$$"); for (int i=0;i< values.length;i++){ System.out.println(values[i]); values[i].show(); } System.out.println("$$$$$$$$$$$$"); System.out.println("Thread类的循环"); //Thread.state Thread.State[] values1 = Thread.State.values(); for (int i=0;i<values1.length;i++){ System.out.println(values1[i]); } System.out.println("*************"); //如果没有objNname的枚举类对象,则抛异常:IllegalArgumentException // valueOf(String objName):根据提供的objName,返回枚举类中对象名是objName的对象。 Season1 winter = Season1.valueOf("WINTER"); System.out.println(winter); winter.show(); } } interface Info{ void show(); } //使用enum关键字定义枚举类 enum Season1 implements Info{ //1.提供当前枚举类的对象,多个对象之间用","隔开,末尾对象";"结束 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.声明Season对象的属性:private final修饰 private final String seasonName; private final String seasonDesc; //2.私有化类的构造器,并给对象属性赋值 private Season1(String seasonName,String seasonDesc){ this.seasonName=seasonName; this.seasonDesc=seasonDesc; } //4.其他诉求:获取枚举类对象的属性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //5.其他诉求二:提供toString() //可以进行重写,也可以不进行重写。 /* @Override public String toString() { return "Season1{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; }*/ /*@Override public void show() { System.out.println("这是一个季节"); }*/ }
运行之后如下所示:
二、注解
从JDK5.0开始,Java增加了人对元数据的支持,也就是Annotation(注解)
Annotation其实就是代码里的特殊标记,这些标记可以在编译,类加载。运行时被读取,并执行相应的处理。通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息,代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署
Annotation可以像修饰符一样被使用,可用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotation的“name=value"对中。
框架=注解+反射+设计模式
使用Annotation时要在其前面增加@符号,并把该Annotation当成一个修饰符使用。用于修饰它支持的程序元素
示例一:生成文档相关的注解
示例二:在编译时进行格式检查(JDK内置的三个基本注解)
@Override:限定重写父类方法,该注解只能用于方法
@Deprecated:用于表示所修饰的元素(类,方法等)已过时,通常是因为所修饰的结构危险或存在更好的选择。
@SuppressWarnings:抑制编译器警告
示例三:跟踪代码依赖性,实现替代配置文件功能
package com.ypl.zhujie; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Date; /** * 注解的使用 * 1.理解Annotation: * (1)jdk5.0新增的功能 * (2)Annotation其实就是代码里的特殊标记,这些标记可以在编译 * ,类加载。运行时被读取,并执行相应的处理。通过使用Annotation,程 * 序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。 * 2.Annotation的使用示例: * 示例一:生成文档相关的注解 * 示例二:在编译时进行格式检查(JDK内置的三个基本注解) * @Override:限定重写父类方法,该注解只能用于方法 * @Deprecated:用于表示所修饰的元素(类,方法等)已过时,通常是因为所修饰的结构危险或存在更好的选择。 * 我们的类里面体现出如下所示: * @Deprecated * public Date(int year, int month, int date) { * this(year, month, date, 0, 0, 0); * } * v:抑制编译器警告 * 示例三:跟踪代码依赖性,实现替代配置文件功能 * 3.如何自定义注解:参照@SuppressWarnings定义 * public @interface SuppressWarnings * (1)注解声明为:@interface * (2)内部定义成员,通常使用value表示 * (3)可以指定成员的默认值,使用default定义 * (4)如果自定义注解没有成员,表明是一个标识作用。 * * 如果注解有成员,在使用注解时,需要指明成员的值 * 自定义注解必须配上注解的信息处理流程(使用反射)才有意义。 * 4.jdk提供的4种元注解 * JDK的元Annotation用于修饰其他Annotation定义 * 元数据:对现有数据的修饰 * 元注解:修饰其他注解的注解(对现有的注解进行解释说明的注解、 * 元注解示例如下所示: * @Target(ElementType.METHOD) * @Retention(RetentionPolicy.SOURCE) * public @interface Override { * } * * 自定义注解通常都会指明两个元注解:Retention、Target * 4.JDK5.0提供了4个标准的meta-annotation类型,分别是: * Retention:指定所修饰的Annotation的生命周期:SOURCE\CLASS(默认行为)\RUNTIME * 只有声明为RUNTIME生命周期的注解,才能通过反射获取。 * Target:用于指定被修饰的Annotation能用于修饰哪些程序元素 * *********出现的频率较低******* * Documented:表示所修饰的注解在被javaDoc解析时,保留下来。 * Inherited:被它修饰的Annotation将具有继承性。 * 5.通过反射来获取注解信息 * 6.jdk 8中注解的新特性:可重复注解、类型注解 * 6.1可重复注解:(1)在MyAnnotation上声明@Repeatable,成员值为MyAnnotations.class * (2)MyAnnotation的Target和Retention等元注解与MyAnnotations相同。 * 6.2类型注解: * public enum ElementType { * TYPE_PARAMETER, * TYPE_USE * ElementType.TYPE_PARAMETER表示该注解能写在类型变量的声明语句中(泛型声明) * ElementType.TYPE_USE表示该注解能写在使用类型的任何语句中 * */ public class AnnotationTest { public static void main(String[] args) { @SuppressWarnings("unused") int num=10; //未调用的时候颜色为灰色,添加此注释即可进行抑制 Class studentClass = Student.class; Annotation[] annotations = studentClass.getAnnotations(); for (int i=0;i<annotations.length;i++){ System.out.println(annotations[i]); } } } //jdk 8之前的写法: //@MyAnnotations({@MyAnnotation(value ="hi"),@MyAnnotation(value ="hi")} ) //JDK1.8后的写法: @MyAnnotation(value ="hi") @MyAnnotation(value ="abc") class Person{ private String name; private int age; @MyAnnotation public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } public void walk(){ System.out.println("人走路"); } public void eat(){ System.out.println("人吃饭"); } } interface Info{ void show(); } class Student extends Person implements Info{ @Override public void walk() { System.out.println("学生走路"); } @Override public void show() { } } class Generic<@MyAnnotation T>{ public void show() throws @MyAnnotation RuntimeException{ ArrayList<@MyAnnotation String> list=new ArrayList<>(); int num=(@MyAnnotation int)10L; } }
我们的自定义注解如下所示:
package com.ypl.zhujie; import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Repeatable(MyAnnotations.class) public @interface MyAnnotation { String value() default "hello"; }
package com.ypl.zhujie; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) public @interface MyAnnotations { MyAnnotation [] value(); }