Java注解介绍

JAVA注解

一、注解和注释区别:

1.1 注释:comment

给程序员看的,对程序做出解释。用于描述代码的作用和一些关键性的知识点,使用文字描述程序。

1.2 注解:annotation

  • JDK5.0后引入的新技术,他不是程序本身,但可以对程序做出解释。(这一点和注释没有区别)

  • 给程序员看,但主要目的是给程序看(多的这个“解”字)

二、注解详细定义

叫元数据,一种代码级别的说明,它是JDK1.5及以后版本引入的一个特性,与类、接口(注解本质上是一种特殊的接口)、枚举在同一个层次,它可以声明在包、类、字段、局部变量、方法参数等的前面,用来对这些元素进行说明、注释。很多框架的底层都是通过注解实现,比如spring boot,spring cloud。(框架的底层就是注解和反射)

2.1 注解的作用分类

编写文档:

通过代码里表示的元数据生成文档【生成doc文档】

代码分析:

通过代码里表示的元数据进行分析【使用反射】

编译检查:

通过代码里表示的元数据让编译器能够实现基本的编译检查【Override】

2.2 注解按照运行机制分类

源码注解:

注解只在源码中存在,编译成.class文件之后就不存在了。常见的注解为@Override,@SuppressWarnings

编译时注解:

注解在源码存在的基础上,也会在.class文件中存在,但是在运行阶段中就不存在了

这是默认的注解保留策略。这种策略下,注解将存在与.class文件,但是不能被运行时访问。通常这种注解策略用来处于一些字节码级别的操作。

运行时注解:

注解在运行阶段依然存在,且能够影响程序的运行过程,例如:@Autowired

通常情况下,我们都会结合反射来做一些事情。

2.3 注解的作用

  • 不是程序本身,可以对程序做出解释(这一点和注释一样)

  • 可以被其他程序(比如:编译器)读取,注解+反射。

  • 可以附加在package,class,method,field等上面,相当于给他们额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。

2.4 注解的格式

注解是以“@注解名”在代码中存在的;还可以添加一些参数值,例如:@suppressWarning(value=“unchecked”)

三、注解入门

分为内置注解和自定义注解

3.1 内置注解示例:

@Override:重写Object的toString()

@Override表示重写父类方法,在编译时存在

package com.happy;

//什么是注解
public class AnnotationStudy extends Object {

    //@Override 重写的注解
    @Override
    public String toString() {
        return super.toString();

    }


    public void testTread(){
        Thread thread=new Thread();

    }
}

@FunctionalInterface:Runnable接口用

线程接口Runnable的@FunctionalInterface,表示该接口是一个函数式编程接口(即只有一个待实现方法),不定义也没有影响程序执行。

package java.lang;

/**
 * The <code>Runnable</code> interface should be implemented by any
 * class whose instances are intended to be executed by a thread. The
 * class must define a method of no arguments called <code>run</code>.
 * <p>
 * This interface is designed to provide a common protocol for objects that
 * wish to execute code while they are active. For example,
 * <code>Runnable</code> is implemented by class <code>Thread</code>.
 * Being active simply means that a thread has been started and has not
 * yet been stopped.
 * <p>
 * In addition, <code>Runnable</code> provides the means for a class to be
 * active while not subclassing <code>Thread</code>. A class that implements
 * <code>Runnable</code> can run without subclassing <code>Thread</code>
 * by instantiating a <code>Thread</code> instance and passing itself in
 * as the target.  In most cases, the <code>Runnable</code> interface should
 * be used if you are only planning to override the <code>run()</code>
 * method and no other <code>Thread</code> methods.
 * This is important because classes should not be subclassed
 * unless the programmer intends on modifying or enhancing the fundamental
 * behavior of the class.
 *
 * @author  Arthur van Hoff
 * @see     java.lang.Thread
 * @see     java.util.concurrent.Callable
 * @since   JDK1.0
 */
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

destroy():Thread类的方法用@Deprecated

表示该方法废弃,在调用该方法时,IDE会以删除线标志该方法,不推荐程序员使用,但可以使用。

如下

@Deprecated
public void destroy() {
    throw new NoSuchMethodError();
}
package com.happy;

//什么是注解
public class AnnotationStudy extends Object {

    //@Override 重写的注解
    @Override
    public String toString() {
        return super.toString();

    }


    public void testTread(){
        Thread thread=new Thread();
        thread.destroy();
    }
}

@suppressWarnings

镇压警告,用来抑制编译时的警告信息,与前面的注释不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好的,我们选择性使用就好了。平时不建议镇压,

@SuppressWarnings("all")

@SuppressWarnings("unchecked")

@SuppressWarnings(value={"unchecked","deprecation"})
package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * Indicates that the named compiler warnings should be suppressed in the
 * annotated element (and in all program elements contained in the annotated
 * element).  Note that the set of warnings suppressed in a given element is
 * a superset of the warnings suppressed in all containing elements.  For
 * example, if you annotate a class to suppress one warning and annotate a
 * method to suppress another, both warnings will be suppressed in the method.
 *
 * <p>As a matter of style, programmers should always use this annotation
 * on the most deeply nested element where it is effective.  If you want to
 * suppress a warning in a particular method, you should annotate that
 * method rather than its class.

 */
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@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();
}

注意:上面value()看似方法,实际为属性,而Sring为属性的类型,这是注解特殊的地方。

另外注意@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE) 这两个注解,为元注解,将在下面讲解。

加入镇压告警前:

加入压制后,idea不再暗黑提示

3.2 元注解

元注解的作用就是负责注解其他注解,就是解释其他注解的注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型做说明。也是内置注解。

这些类型和他们所支持的类在java.lang.annotation包中可以找到,分别是:

@Target:(重点)

用于描述注解的使用范围

(即:被描述的注解可以用在什么地方)

@Retention:(重点)

表示需要在什么级别保存该注释信息,用于描述注解的生命周期:SOURCE<CLASS<RUNTIME

一般我们使用定义为RUNTIME,即运行的时候依然存在有用,重点记忆。

例如:

Runtime定义的,将会在Runtime,Class和Source都存在和生效

而Class定义的,会在Class和Source生效

@Document:

说明该注解将包含在javadoc中

@Inherited:

说明子类可以继承父类中的该注解

测试元注解:

自定义注解,使用元注解,示例如下:

下图Target方法指定用在Method,固注解在类上时报错。

用数组引入多个Target范围后,不再报错

四、自定义注解

使用@ interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,注意前面有@,如果没有@就是普通接口

要点如下:

  • @interface用来声明一个注解,格式public @interface 注解名{定义内容}。

    如果是内部类方式申明注解,就省去public

  • 其中每一个方法实际上是声明了一个配置参数(或者理解为属性),方法的名称就是参数的名称。返回值的类型就是参数的类型

    返回值类型只能是基本类型、class、String、enum

  • 可以通过default类声明参数的默认值

  • 如果只有一个参数成员,一般为参数取名为value,使用时还可以起取消掉

  • 注解元素必须要有值,我们定义注解元素时,通常使用空字符串、0作为默认值

package com.happy;

import java.lang.annotation.*;

@MyAnnotation
public class MetaAnnotationUseStudy {


    @MyAnnotation
    public void test() {

    }

    //    注解可以显示赋值,如果没有默认值,我们必须显示赋值
    @MyAnnotation2(name = "happytest",schools = {"哈佛"})
    public void test2() {

    }
}


@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
@interface MyAnnotation {
}


@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Inherited
//作用范围为到运行时
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2 {

    //        注解的参数,注意这里不是方法
    String name() default "";

    int age() default 0;

    int id() default -1;//如果默认值为-1,代表不存在

    String[] schools() default {"北郵","清華"};

}

后面会介绍反射,注解必须+反射,才能读取注解里的东西,才能发挥最大功效,是框架的基础。

posted @ 2022-04-01 14:39  高兴518  阅读(98)  评论(0)    收藏  举报