Java语言是纯面向对象的。
一、注解简介
1.引入时间:JDK1.5版本引入注解。
2.什么是注解?
注解,也叫做元数据。一种代码级别的说明。它与类,接口,枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数的前面,用来对这些元素进行说明,注释。这些说明被存储在Annotation注解的“name=value”结构中。
3.注解的作用
编写文档:通过代码里标识的元数据生成文档。
代码分析:通过代码里标识的原数据对代码进行分析。
编译检查:通过代码里标识的原数据让编译器能实现基本的编译检查。
4.注解的分类
4.1 JDK自带的注解
@override:表示子类覆写父类的方法。
@Deprecated:表示该方法已被弃用。
@SuppressWarnings:表示忽略指定警告,eg:@SuppressWarnings("Deprecation");
说明:(1)这三种注解都是在编译时注解,在源码和.class文件中都存在。
(2)注解的继承只能作用在类上,方法上的注解不会被继承,Interface中的所有注解不会被继承。
还有四种元注解
@Target 注解作用域,表示该注解可以用于一个类中的那些属性及方法上,,如果该作用域有多个可以用英文逗号分隔。
@Retention 表示该注解的生命周期。
@Documented 表示生成javadoc时会包含注解。
@Inherited 标识性的元注解,表示当前注解可以由子注解继承。
4.2 第三方注解
4.3 自定义注解
语法:
@<注解名>(<成员名1>=<成员值1>,<成员名2=成员值2>,...)
5.注解的生命周期
每个Annotation都有自己的运行范围,而这些范围在一个枚举类(java.lang.annotation.RetentionPolicy)中定义:
SOURCE:在源代码中出现的注解,编译时丢弃。
CLASS:编译时还在,运行时丢弃。
RUNTIME:运行时仍然存在,可以通过反射获取。
二、反射与Annotation
1.反射取得注解信息
public Annotation[] getAnnotations(); 取得全部Annotation
public T getAnnotation(Class annotationClass); 取得指定的Annotation
1.1 取得在类上定义的Annotation
package com.com.company.reflection;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@SuppressWarnings("serial")//告诉编译器忽略“serial”警告信息。
@Deprecated//表明A类被禁用,在使用时会出现A划斜线。
class A implements Serializable {
@Override
public String toString(){
return "覆写";
}
}
public class TestAnnotation {
public static void main(String[] args) {
Annotation[] annotations=A.class.getAnnotations();
for(Annotation annotation:annotations){
System.out.print(annotation+" ");
}
Annotation annotation = A.class.getAnnotation(java.lang.annotation.Annotation.class);
System.out.println(annotation);
}
}
因为不同的Annotation有自己的保存范围,它们的返回也不同。因此此时只返回了一个Annotation。
1.2 在方法上使用Annotation
package com.com.company.reflection;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@SuppressWarnings("serial")
@Deprecated
class A implements Serializable {
@Deprecated
@Override
public String toString(){
return super.toString();
}
}
public class TestAnnotation {
public static void main(String[] args) {
Annotation[] annotations=new Annotation[0];
try {
annotations=A.class.getMethod("toString").getAnnotations();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
for(Annotation annotation:annotations){
System.out.print(annotation+" ");
}
}
}
结果:
2.自定义注解
package com.com.company.reflection;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//自定义注解
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
public String name() default "张三";//设置默认值
public int age() default 18;
}
@MyAnnotation(name="李四",age=38)//可以在注解后面修改
class A {
@Deprecated
@Override
public String toString(){
return super.toString();
}
}
public class TestAnnotation {
public static void main(String[] args) {
MyAnnotation myAnnotation=A.class.getAnnotation(MyAnnotation.class);
System.out.println("姓名:"+myAnnotation.name());
System.out.println("年龄:"+myAnnotation.age());
}
}
结果:
三、注解与工厂设计模式
前面介绍的工厂有一个用于不同产品实现不同方法的接口,产品类和工厂类。在工厂类中生产产品(实例化对象),接口中定义方法,不同的产品类根据自己的需要实现接口中的方法。在反射(一)中已经介绍过传统的工厂设计模式的缺点是一旦增加商品,在工厂类中实例化对象的方法代码就要进行改动。我们通过反射机制避免了这一弊端,通过类的Class对象的newInstance()获取实例化对象,避免了大量代码的改动。而通过对注解的认识,我们可以通过在注解中设置目标。在工厂类上面可以对想要的目标进行修改,从而获取实例化对象。
package com.com.company.reflection;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
public Class<?> target();
}
//定义一个接口,产品都要实现这个接口。
interface IFastFood{
public void eat();
}
class Pizza implements IFastFood{
@Override
public void eat() {
System.out.println("吃披萨");
}
}
class Hamburger implements IFastFood{
@Override
public void eat() {
System.out.println("吃汉堡包");
}
}
//定义一个工厂生产这种产品
@MyAnnotation(target=Hamburger.class)//设置要生产的产品
class Factory{
public static IFastFood getInstance() throws IllegalAccessException, InstantiationException {
MyAnnotation a=Factory.class.getAnnotation(MyAnnotation.class);
return (IFastFood)a.target().newInstance();
}
}
public class TestAnnotation {
public static void main(String[] args) {
try {
IFastFood fastFood= (IFastFood) Factory.getInstance();
fastFood.eat();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
结果: