zoukankan      html  css  js  c++  java
  • 注解

    注解,或者叫元数据,可以让我们在代码中添加一些java无法表达的信息,而且可以由编译器验证和检查. Java SE5预定义了一些 ,但一般还是需要自己添加新的注解 ,并且按自己的方式使用 .

    Java内置注解:

    • @Override 表示方法定义会覆盖超类方法,如果有拼写错误或方法签名对不上,编译器会发出错误提示
    • @Deprecated 如果使用了该元素 编译器发出警告
    • @SuppressWarnings 关闭编译器警告信息

    基本语法

    使用注解的方式与修饰符基本一样

    @Test
    public class XXX{
        @test
        public void testExcue(){
            //doSomething
        }
    }

    定义注解

    package xx.xx;
    import java.lang.annotation.*;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Test{}

    注解定义类似接口,而且注解也会被编译为class文件

    定义注解时需要一些元注解

    • @Target :定义注解应用于什么地方,如方法或是字段
    • @Retention: 定义注解在哪一级别可用,在源代码(source),类文件中(class),或是运行时(Runtime)
    • @Documented :将此注解放在javaDoc中
    • @Inherited: 允许子类继承父类中的注解

    注解中可以包含一些元素表示某些值,当分析处理注解时可以使用,元素类似于接口中的方法,并且可以指定默认值.

    标记注解: 没有元素的注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface useCase{
        public int id();
        public String description() default "no description";
    }

    编写注解处理器

    注解比注释更有用体现在我们可以为注解编写注解处理器.

    class PasswordUtils {
        @useCase(id = 47 , description = "password mast have a number")
        public boolean validatePassword(String password){
            return (password.matches("\w*\d\w*"));
        }
    
        @useCase(id = 48 )
        public String encryptPassword(String password){
            return new StringBuilder(password).reverse().toString();
        }
    
        @useCase(id =49 ,description = "new password need be different")
        public boolean checkForNewPassbwordb(List<String> prePasswords , String password){
            return !prePasswords.contains(password);
        }
    }
    
    public class UseCaseTracker {
        public static void main(String[] args){
            List<Integer> useCases = new ArrayList<>();
            Collections.addAll(useCases,47,48,49,50);
            trackUseCases(useCases,PasswordUtils.class);
        }
    
        public static void trackUseCases(List<Integer> useCases,Class<?> cl){
            for(Method m : cl.getDeclaredMethods()){
                useCase uc = m.getAnnotation(useCase.class);
                if(uc != null){
                    System.out.println("Found Use Case :"+uc.id()+""+uc.description());
                    useCases.remove(new Integer(uc.id()));
                }
            }
            for(int i:useCases){
                System.out.println("warning :miss use case "+i);
            }
        }
    
    }
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface useCase{
        public int id();
        public String description() default "no description";
    }

    这里使用到的方法:

    • getDeclaredMethods() :返回方法列表
    • getAnnotations() : 返回指定类型的注解对象,如果没有指定类型注解返回null

    他们都属于AnnotatedElement接口 , Class,Method,Field类都实现了该接口

    注解元素

    可用的注解元素类型如下

    • 所有基本类型
    • string
    • class
    • enum
    • annotation
    • 以上类型的数组
      由于注解也是可用类型,因此注解可以嵌套,这将是很有用的特性

    默认值限制

    编译器限制 , 注解的元素除基本类型之外不能由不确定的值,也就是说要么有默认值要么使用时提供值,其次,定义默认值时不能用null.

    因此通常要自己定义-1或者空字符串""表示元素不存在.

    注解代替外部文件

    有些框架需要一些额外信息才能与代码协同工作 , 在有注解之前 , 普遍使用的时XML , 程序员必须忍受沉闷 , 将在源代码中已经提供过的信息再次提供 . 而且使用外部文件时 , 同一个类将会有两个信息源 , 这往往会导致代码同步问题 , 并且程序员需要同时能够编写Java和描述文件

    这里写一个小例子

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DBTable {
        public String name() default "";
    }
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Constraints {
        boolean primaryKey() default false;
    
        boolean allowNull() default true;
    
        boolean unique() default false;
    }
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SQLString {
        int value() default 0;
    
        String name() default "";
    
        Constraints constraints() default @Constraints;
    }
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SQLInteger {
        String name() default "";
    
        Constraints constraints() default @Constraints;
    }

    注解处理器

    public static void main(String[] args) throws ClassNotFoundException {
        if(args.length<1){
            System.out.println("arguments: annotated classes");
            System.exit(0);
        }
        for(String className : args){
            Class<?> cl = Class.forName(className);
            DBTable dbTable = cl.getAnnotation(DBTable.class);
            if(dbTable == null){
                System.out.println("no dbTable annotations in class "+className);
                continue;
            }
            String tableName = dbTable.name();
    
            if(tableName.length()<1){
                tableName = cl.getName().toUpperCase();
            }
            List<String> columnDefs = new ArrayList<>();
            for(Field field : cl.getDeclaredFields()){
                String columnName = null;
                Annotation[] anns = field.getDeclaredAnnotations();
                if(anns.length<1)
                    continue;
                if(anns[0] instanceof SQLInteger){
                    SQLInteger sInt = (SQLInteger)anns[0];
                    if(sInt.name().length()<1){
                        columnName = field.getName().toUpperCase();
                    }
                    else
                        columnName = sInt.name();
                    columnDefs.add(columnName + " INT" +
                    getConstraints(sInt.constraints()));
                }
                if(anns[0] instanceof SQLString){
                    SQLString sstring = (SQLString)anns[0];
                    if(sstring.name().length()<1){
                        columnName = field.getName().toUpperCase();
                    }
                    else
                        columnName = sstring.name();
                    columnDefs.add(columnName + "VARCHAR(" +
                            sstring.value() +")" +
                            getConstraints(sstring.constraints()));
                }
                StringBuilder createCommand = new StringBuilder("CREATE TABLE " +
                        tableName +"(");
                for(String columnDef :columnDefs){
                    createCommand .append("
         " +
                            columnDef +".");
                }
                String tableCreate  = createCommand.substring(0,createCommand.length()-1)+");";
                System.out.println("table creation sql for "+ className + " is :" +
                        "
    " +tableCreate);
            }
        }
    }
    
    private static String getConstraints(Constraints con){
        StringBuilder constraints = new StringBuilder();
        if(!con.allowNull())
            constraints .append( " NOT NULL ");
        if(con.primaryKey())
            constraints .append(" PRIMARY KEY ");
        if(con.unique())
            constraints.append(" UNIQUE ");
        return constraints.toString();
    }
    

    注解不支持继承

    注解并不支持继承.





  • 相关阅读:
    Win10 企业版ltsc 无法访问samba网络共享问题及解决!(转)
    内核发送uevent的API,用户空间解析uevent(转)
    修改kile工程名字(转)
    gdb调试
    当usbnet打印 kevent * may have been dropped(转)
    收藏一份devmem源码
    Linux Performance
    控制 input框只输入数字
    springboot环境中,可能会出现使用font-Awesome结果图标不显示的问题,在webService的pom文件中添加如下配置代码
    js防止页面抖动(按钮,请求等重复提交)
  • 原文地址:https://www.cnblogs.com/renluxiang/p/cfab0af16b6db58ad7845cd599f224dd.html
Copyright © 2011-2022 走看看