尚硅谷_Java零基础教程-java入门必备-初学者基从入门到精通全套完整版(宋红康主讲)
P498
文章目录
枚举类
- 类的对象只有有限个,确定的。
- 星期、性别、状态
- 当需要定义一组常量时,强烈建议使用枚举类。
自定义枚举类
- 声明Season对象的属性:private final修饰
- 私有化类的构造器,并给对象属性赋值
- 提供当前枚举类的多个对象,public static final的
- 其他需求:get属性、toString()
class Season {
public final static Season SPRING = new Season("spring",3,5);
public final static Season SUMMER = new Season("summer",6,8);
public final static Season AUTUMN = new Season("autumn",9,11);
public final static Season WINTER = new Season("winter",12,2);
private final String name;
private final int begMonth;
private final int endMonth;
private Season(String name, int begMonth, int endMonth) {
this.name = name;
this.begMonth = begMonth;
this.endMonth = endMonth;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", begMonth=" + begMonth +
", endMonth=" + endMonth +
'}';
}
}
enum关键字定义枚举类
jdk5之后,可以使用enum关键字定义枚举类
enum NewSeason {
SPRING("spring",3,5),
SUMMER("summer",6,8),
AUTUMN("autumn",9,11),
WINTER("winter",12,2);
private final String name;
private final int begMonth;
private final int endMonth;
private NewSeason(String name, int begMonth, int endMonth) {
this.name = name;
this.begMonth = begMonth;
this.endMonth = endMonth;
}
}
不重写toString()的情况下,
SPRING
SUMMER
AUTUMN
WINTER
Enum类中的常用方法
values()方法:
NewSeason[] values = NewSeason.values();
结果同样是
SPRING
SUMMER
AUTUMN
WINTER
System.out.println(NewSeason.valueOf("WINTER"));
//WINTER
可以在枚举对象里面重写方法:
enum NewSeason implements Info {
SPRING("spring",3,5){
@Override
public void show() {
System.out.println("spring spring");
}
},
SUMMER("summer",6,8),
AUTUMN("autumn",9,11),
WINTER("winter",12,2);
注解Annotation
概述
- 从jdk5.0开始,java增加了对元数据的支持,也就是Annotation。
- Annotation其实就是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或部署。
- Annotation可以像修饰符一样被使用,可用于修饰包,类,构造器,方法,成员变量,参数,局部变量的声明,这些信息被保存在Annotation的“name=value”对中。
- 在javaSE中注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在javaEE/Android中注解占据了更重要 的角色,例如用来配置应用程序的任何切面,代替javaEE旧版中所遗留的繁冗代码和XML配置等。
- 未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的structs2有一部分也是基于注解的了,注解是一种趋势,一定程度上可以说:框架=注解+反射+设计模式。
注解示例
生成文档相关的注解
- @author:作者
- @version:版本
- @see:相关主题
- @since:从哪个版本开始增加的
- @param:对方法中某参数的说明
- @return:对方法返回值的说明
- @exception:对可能抛出的异常进行说明
在编译时进行格式检查(JDK内置的三个基本注解)
@Override
:限定重写父类方法,只能用于方法@Deprecated
:已过时@SuppressWarnings
:抑制编译器警告
跟踪代码依赖性,实现替代配置文件功能
- Servlet3.0提供了注解
@WebServlet("/login")
- Spring框架关于事务的管理
@Transactional
三个基本注解的使用
校验:不是重写方法的话,@Override会提示
@Override
public void wa1k() {
System.out.println("student walk");
}
@Deprecated
会标注在过时的代码上。
不加的话,没有使用的变量是灰色的,加了之后就不会变灰
@SuppressWarnings("unused")
int age;
自定义注解
参照 @SuppressWarnings
- 定义新的Annotation类型使用@interface关键字
- 自定义注解自动继承了java.lang.annotation.Annotation接口
- Annotation的成员变量在Annotation定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能是八种基本数据类型、String类型、Class类型、enum类型、Annotation类型、以及以上所有类型的数组。
- 可以在定义Annotation的成员变量时为其指定初始值,指定成员变量的初始值可使用default关键字。
- 如果只有一个参数成员,建议使用参数名为value
- 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是“参数名=参数值”,如果只有一个参数成员,且名称为value,可以省略“value=”
- 没有成员定义的Annotation称为标记;含有成员变量的Annotation称为元数据Annotation
- 注意:自定义注解必须配上注解的信息处理流程才有意义。
public @interface MyAnnotation {
String value() default "hello";
}
SuppressWarnings :
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p> The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
JDK中的元注解
- JDK的元注解用于修饰其它注解定义
- JDK5.0提供了4个标准的元注解类型,分别是:
- Retention
- Target
- Documented
- Inherited
- 自定义注解通常都会指明Retention和Target
@Retention
:只能用于修饰一个Annotation,用于指定该Annotation的生命周期,包含一个RetentionPolicy类型的成员变量,使用时必须为该value成员变量指定值:- RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释
- RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行java程序时,JVM不会保留注释,这是默认值
- RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行Java程序时,JVM会保留注释。程序可以通过反射获取该注释。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Target
:用于修饰Annotation定义,用于指定被修饰的Annotation能用于修饰那些程序元素。@Target也包含一个名为value的成员变量。- CONSTRUCTOR :用于描述构造器
- FIELD :用于描述域
- LOCAL_VARIABLE :用于描述局部变量
- METHOD:用于描述方法
- PACKAGE :用于描述包
- PARAMETER :用于描述参数
- TYPE : 用于描述类、接口(包括注解类型)或enum声明
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE
}
@Documented
:用于指定被该元注解修饰的Annotation类将被javadoc工具提取成文档。默认情况下,javadoc是不包括注解的。- 定义为@Documented的注解必须设置Retention值为RUNTIME。
Deprecated 有 @Documented
标识,在生成文档时,会把被Deprecated 修饰的 提取出来。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
/**
* Returns the version in which the annotated element became deprecated.
* The version string is in the same format and namespace as the value of
* the {@code @since} javadoc tag. The default value is the empty
* string.
*
* @return the version string
* @since 9
*/
String since() default "";
/**
* Indicates whether the annotated element is subject to removal in a
* future version. The default value is {@code false}.
*
* @return whether the element is subject to removal
* @since 9
*/
boolean forRemoval() default false;
}
@Inherited
:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。- 比如:如果把标有@Inherited注解的自定义 的注解标注在类级别上,子类则可以继承父类类级别的注解。
- 实际应用中,使用较少。
通过反射获取注解
Student是Person的子类,Person被@MyAnnotation(value = “world”)修饰。
- 若@MyAnnotation有@Inherited,两个类都有注解。
- 若@MyAnnotation没有@Inherited,则Student类没有注解。
//通过反射获取注解信息
@Test
public void testGetAnnotation(){
Class<Student> studentClass = Student.class;
Annotation[] annotations = studentClass.getAnnotations();
for (Annotation a:annotations ) {
System.out.println(a);
}
for (Annotation a:Person.class.getAnnotations() ) {
System.out.println(a);
}
}
JDK8中注解的新特性
可重复注解
- jdk8之前的写法
@MyAnnotations({@MyAnnotation(value = "yes"),@MyAnnotation(value = "ok")})
public @interface MyAnnotations {
MyAnnotation[] value();
}
- jdk8之后的写法
@MyAnnotation(value = "yes")
@MyAnnotation(value = "ok")
声明@Repeatable
@Inherited
@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello";
}
注意:两个注解的@Target、@Retention、@Inherited等元注解需一致。
@Inherited
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations {
MyAnnotation[] value();
}
类型注解
- jdk8之后,关于元注解@Target的参数类型ElementType枚举值多了两个:TYPE_PARAMETER , TYPE_USE 。
- 在jdk8之前,注解只能是在声明的地方所使用,java8开始,注解可以应用在任何地方。
- ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如:泛型声明)
- ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。
修饰泛型:
class Generic< @MyAnnotation T>{
public void show(){
ArrayList<@MyAnnotation String> list = new ArrayList<>();
int num = (@MyAnnotation int) 10L;
}
}