03_框架基础之注解

1 概念

注解:annotation
     1.8以后的新特性
     注解:程序元素的元数据
     解释:程序元素:程序的组成:包+类+接口+方法+属性+形参+局部变量...
          元数据:给成员元素添加的数据
     理解:给程序的元素添加的"注释",此注释的数据可以通过反射获取 指挥编译器的编译和干涉虚拟机的运行 
     根接口:java.lang.annotation.Annotaition
     关键字 @interface

2 常见的注解

2.1 @Override

@Override//注解:重写:表示此方法是重写父类的方法::指挥编译器的编译
public String toString() {
    return super.toString();
}

2.2 @Deprecated

@Deprecated  //注解:过时::表示此方法是过时 有更好的替代者::指挥编译器的编译
public void hehe(){}
@Deprecated 
int a=1;

2.3 @SuppressWarnings

//@SuppressWarnings({"unused","static-access","deprecation"})//取消指定的警告
@SuppressWarnings({"all"})//注解:取消编译警告::取消编译器对当前方法的指定/所有警告::指挥编译器的编译
public void hai(){
    int a=1;//The value of the local variable a is not used
    Date date=new Date(2013, 01, 1);//The constructor Date(int, int, int) is deprecated
    this.b=1;//The static field Demo01.b should be accessed in a static way
    List list=null;// List is a raw type. References to generic type List<E> should be parameterized
    try{
        return;
    }finally{//finally block does not complete normally
        return;
    }
}
static int b=1;

在这里插入图片描述

2.4 @Test

在这里插入图片描述
在这里插入图片描述

//单元测试: 1 引入junit的jar包
//        2 在方法上添加注解:::干涉虚拟机的运行
//	@Test
//	public void hh1(){
//		System.out.println("public void hh1()"+1/1+":::"+this);
//	}
	
//	//java.lang.Exception: Method hh should have no parameters
//	@Test
//	public void hh2(int a){
//		System.out.println("public void hh2(a)"+1/1+":::"+this);
//	}
//	
	
	//java.lang.Exception: Method hh3() should be void
//	@Test
//	public int hh3(){
//		System.out.println("public int hh3()"+1/1+":::"+this);
//		return 1;
//	}
	
//	java.lang.Exception: Method hh4() should not be static
//	@Test
//	public static void hh4()throws Exception{
//		System.out.println("public static void hh4()throws Exception"+1/1+":::");
//	}
	
	@Test
	public final void hh5()throws Exception{
		System.out.println("public final void hh5()throws Exception"+1/1+":::");
	}
	
//	java.lang.Exception: Method hh6() should be public
//	@Test
//	protected final void hh6()throws Exception{
//		System.out.println("protected final void hh6()throws Exception"+1/1+":::");
//	}
	//@Test单元测试的方法要求:不能有返回值 不能有参数列表 不能是静态的 必须是public 可以是final的

3 自定义注解

@My1Anniotation(name="韩梅梅",age=11)//使用注解 并给属性赋值
public class Demo02 {
	public static void main(String[] args) {
		
	}
	@My2Anniotation(value="v_1")
	public void test11(){}
	@My2Anniotation("v_1")//如果一个注解的属性 只有value属性需要赋值时 value=可以省略
	public void test21(){}
}
//创建一个注解 可以加载类上
@interface My1Anniotation{
	//注解中定义属性
	String name();//定义一个属性:属性类型是String 属性名字是name
	//属性类型仅限于:String,Class,基本数据类型,枚举,注解,这些类型的一维数组
    //only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof
    
	int age() default 1;//给属性赋默认值
}
//创建一个注解 可以加载类上
@interface My2Anniotation{
     String value();//定义一个属性:
}

4 注解解析

4.1 自定义注解

@interface MyClassAnnotation{
	String name();
}
@interface MyFieldAnnotation{
	String name();
}
@interface MyMethodAnnotation{
	String value();
	Class type();
}

4.2 创建实体类

@MyClassAnnotation(name="学生")
public class Student {
	@MyFieldAnnotation(name="学号")
	private int id;
	@MyFieldAnnotation(name="名字")
	private String name;
	@MyFieldAnnotation(name="分数")
	private float score;
	@MyFieldAnnotation(name="性别")
	private char sex;
	public int getId() {
		return id;
	}
	@MyMethodAnnotation(value="1001",type=int.class)
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	@MyMethodAnnotation(value="韩梅梅",type=String.class)
	public void setName(String name) {
		this.name = name;
	}
	public float getScore() {
		return score;
	}
	@MyMethodAnnotation(value="99.5f",type=float.class)
	public void setScore(float score) {
		this.score = score;
	}
	public char getSex() {
		return sex;
	}
	@MyMethodAnnotation(value="女",type=char.class)
	public void setSex(char sex) {
		this.sex = sex;
	}
	public Student(int id, String name, float score, char sex) {
		super();
		this.id = id;
		this.name = name;
		this.score = score;
		this.sex = sex;
	}
	public Student() {
		//如果调用无参数的构造方法:通过反射获取set方法省的注解 并执行set方法给属性赋值	
	}
	@Override
	public String toString() {
		//return "Student [id=" + id + ", name=" + name + ", score=" + score + ", sex=" + sex + "]";
		//通过反射 动态获取类元素上的注解的信息 拼凑字符串::重写toString
		return "学生 [学号=" + id + ", 名字=" + name + ", 分数=" + score + ", 性别=" + sex + "]";
	    
	}
	
}

4.3 目标

1: 重写toString方法

@Override
public String toString() {
    //return "Student [id=" + id + ", name=" + name + ", score=" + score + ", sex=" + sex + "]";
    //通过反射 动态获取类元素上的注解的信息 拼凑字符串::重写toString
    return "学生 [学号=" + id + ", 名字=" + name + ", 分数=" + score + ", 性别=" + sex + "]";

}

2 实现无参数的构造方法

public Student() {
    //如果调用无参数的构造方法:通过反射获取set方法省的注解 并执行set方法给属性赋值	
}

4.4 元注解

注解:用来修饰类元素
元注解:用来修饰注解的注解
修饰:给被修饰者添加一些数据/一些特性

元注解1:@Retention

//@Retention  //注定注解保留范围  属性value取值:RetentionPolicy.CLASS(默认) RUNTIME SOURCE
//             RetentionPolicy.SOURCE:只保留在源文件中:编译器不编译
//             RetentionPolicy.CLASS:编译器编译到字节码文件中 但虚拟机不解析 反射获取不到
//             RetentionPolicy.RUNTIME:编译器编译到字节码文件中 虚拟机解析 反射可以获取

元注解2:@Target

//@Target   //指示注释类型所适用的程序元素的种类:取值:
//           ElementType.ANNOTATION_TYPE ::只能作用于注解类上:::针对于元注解
//           ElementType.CONSTRUCTOR ::只能作用于构造方法
//  		 ElementType.FIELD ::只能作用于成员变量
//			 ElementType.METHOD ::只能作用于方法
//			 ElementType.LOCAL_VARIABLE ::只能作用于局部变量
//			 ElementType.PACKAGE ::只能作用于包
//			 ElementType.PARAMETER ::只能作用于参数列表
//           ElementType.TYPE ::只能作用于类,接口,枚举

4.5 对自定义的注解进行改进:添加元注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface MyClassAnnotation{
	String name();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyFieldAnnotation{
	String name();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyMethodAnnotation{
	String value();
	Class type();
}

4.6 重写toString方法

//return "学生 [学号=" + id + ", 名字=" + name + ", 分数=" + score + ", 性别=" + sex + "]";
public static String parseAnnotationFoToString(Object obj){
    //1 获取字节码文件对象
    Class cla=obj.getClass();
    StringBuffer stb=new StringBuffer();
    //2 获取类上的注解
    if(!cla.isAnnotationPresent(MyClassAnnotation.class)){
        throw new RuntimeException("类上没有注解!MyClassAnnotation");
    }
    MyClassAnnotation classAnno=(MyClassAnnotation)cla.getAnnotation(MyClassAnnotation.class);
    //获取name属性的值
    String classAnnoName=classAnno.name();
    stb.append(classAnnoName+"[");
    //3 获取所有属性上的注解
    Field[] fields=cla.getDeclaredFields();
    for (Field field : fields) {
        field.setAccessible(true);//暴力访问
        Object fieldValue;
        try {
            fieldValue=field.get(obj);//获取属性的值
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //获取属性上的注解
        if(!field.isAnnotationPresent(MyFieldAnnotation.class)){
            throw new RuntimeException("属性("+field.getName()+")上没有注解!MyFieldAnnotation");
        }
        MyFieldAnnotation fieldAnno=field.getAnnotation(MyFieldAnnotation.class);
        String fieldAnnoName=fieldAnno.name();
        stb.append(fieldAnnoName+"="+fieldValue+",");
    }
    //更改最后一个,为]
    stb.setCharAt(stb.length()-1, ']');
    return stb.toString();
}
  • 重写toString方法
@Override
public String toString() {
    //return "Student [id=" + id + ", name=" + name + ", score=" + score + ", sex=" + sex + "]";
    //通过反射 动态获取类元素上的注解的信息 拼凑字符串::重写toString
    //return "学生 [学号=" + id + ", 名字=" + name + ", 分数=" + score + ", 性别=" + sex + "]";
    return Demo03.parseAnnotationFoToString(this);

}
  • 测试

在这里插入图片描述

4.7 实现无参数的构造方法

public static void parseAnnotationFoConstructor(Object obj){
    //1 获取字节码文件对象
    Class cla=obj.getClass();
    //2 获取所有的方法
    Method[] methods=cla.getDeclaredMethods();
    //3 获取所有的setXxx开头的方法
    for (Method method : methods) {
        if(method.getName().startsWith("set")){
            //获取其上的注解MyMethodAnnotation
            if(!method.isAnnotationPresent(MyMethodAnnotation.class)){
                throw new RuntimeException("方法("+method.getName()+")上没有注解!MyMethodAnnotation");
            }
            MyMethodAnnotation methodAnno=method.getAnnotation(MyMethodAnnotation.class);
            //获取注解的两个属性 value和type
            String value=methodAnno.value();
            Class type=methodAnno.type();
            try {
                Object valueObj=changeType(value, type);//把字符串转化为指定的类型
                method.invoke(obj, valueObj);//执行当前方法
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}
//写一个方法:把参数字符串的值 转化为指定的类型
private static Object changeType(String value,Class type)throws Exception{
    if(type==byte.class || type==Byte.class){
        return Byte.parseByte(value);
    }
    if(type==short.class || type==Short.class){
        return Short.parseShort(value);
    }
    if(type==int.class || type==Integer.class){
        return Integer.parseInt(value);
    }
    if(type==char.class || type==Character.class){
        return value.charAt(0);
    }
    if(type==long.class || type==Long.class){
        return Long.parseLong(value);
    }
    if(type==float.class || type==Float.class){
        return Float.parseFloat(value);
    }
    if(type==double.class || type==Double.class){
        return Double.parseDouble(value);
    }
    if(type==boolean.class || type==Boolean.class){
        return Boolean.parseBoolean(value);
    }
    if(type==Date.class){
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value);
    }
    return value;
}
  • 实现无参数的构造方法
public Student() {
    //如果调用无参数的构造方法:通过反射获取set方法省的注解 并执行set方法给属性赋值	
    Demo03.parseAnnotationFoConstructor(this);
}
  • 测试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值