Java注释

Java注释

Java中的注释不会出现在可执行程序中。

Java中为我们提供了3种注释:

// 单行注释其注释内容从//开始到本行结尾。

/**/多行注释:/*注释内容在此处写*/  多行注释

/***/文档注释:注释以/**开始,以*/结束。可以用来自动生成文档。

下面注重来讲文档注释

 

文档注释

注释以/**开始,以*/结束。可以用来自动生成文档。

JDK包含一个很有用的工具,叫做javadoc,它可以生成一个HTML文档。

比如联机的API文档就是通过对标准Java类库的源代码运行javadoc生成的。

可以直接将类、方法和变量的注释放置在java源文件中,只要用/**...*/文档注释就可以。


          如果编写Java源代码时添加了合适的文档注释,然后通过JDK提供的javadoc工具可以直接将源代码里的文档注释提取成一份系统的API文档。

 

API文档

 

1,API文档是什么?

    开发一个大型软件时,需要定义上千万个类,并且可能由多个程序员来开发这个软件,每个人都会定义一些类,并在这个类里定义方法、属性提供给他人使用,但其他人怎么知道如何使用呢?这时候急需要提供一份说明文档,用于说明每个类、每个方法的用途。当其他人使用一个类或方法时,他无须关心这个类或这个方法的具体实现,只要知道这个类或这个方法的功能即可,然后使用这个类或方法来实现具体的目的,也就是通过调用应用程序接口(API)来编程。API文档就是以说明这些应用程序接口的文档。对于Java语言而言,API文档通常详细说明了每个类、每个方法的功能,用法等。

 

2,下载JDK的API文档

(1)登录:http://java.sun.com/javase/downloads/index.jsp站点,下载”Java SE 8

 Documentation“项,通过该下载项下载Java SE 6文档,这份文档里包含了JDK的

API文档。下载成功后得到一个jdk-6-doc.zip文件。

(2)将jdk-6-doc.zip文件加压到任意路径,将得到一个docs文件夹。这个文件夹内

就是JDK文档,JDK文档不仅包含API文档,还包含了JDK的其他说明文档,如果直接打开

docs文件夹下的index.xml文件

         API文档页面被分成3个部分,左上角部分是API文档“包列表区”,在该区域内可以查看Java基类的所有包;左下角是API稳定啊的“类列表区”,用于查看Java基类的所有类;右边页面是“详细说明区”,默认显示的是各包空间的说明信息。

         我们在开发中定义类、方法时也可以先添加文档注释,然后使用javadoc工具来生成自己的API文档。

 

3,我们要掌握查看API文档的方法的原因?

         API是Java提供的基库编程接口,当使用Java语言进行编程时,不可能把所有的Java类、所有的方法全部记录下来,那么当我们遇到不确定的地方时,必须通过API文档来查看某个类、某个方法的功能和用法。掌握查看API文档是学习Java的一个最基本的技能。


    由于文档注释是用于生成API文档,而API文档主要用于说明类、方法、属性的功能。

javadoc工具默认只处理以public或protected修饰的类、接口、方法、属性、构造器

之前的文档注释,忽略其他地方的文档注释。

    如果开发者希望javadoc工具可以提取private的内容,则可以在使用javadoc工具时

增加-private选项。

 

4,javadoc的常用选项:

 

-d<directory>:

该选项指定一个路径,用于将生成的API文档放到指定目录下。

 

-windowtitle<text>:

该选项指定一个字符串,用于设置API文档的浏览器窗口标题。

 

doctitle<html-code>:

该选项制定一个HTML格式文本,用于指定概述页面的标题。

注意:一定要对处于多个包下的源文件来生成API文档,才有概述页面。

 

-header<html-code>:该选项指定一个HTML格式的文本,包含每个页面的页眉。

读者可以使用javadoc-help来查看javadoc命令的所有选项。

 

6,常用的javadoc标记:


@author:指定Java程序的作者



@version:指定源文件的版本



@deprecated:不推荐使用的方法



@param:方法的参数的说明信息



@return:方法的返回值的说明信息



@see:“参见”,用于指定交叉参考的内容



@exception:抛出异常的类型



@throws:抛出异常,和exception同义。





标记的使用是有位置限制的



可以出现在类或借口文档注释中的有:


@see、@deprecated、@author、@version等。



可以出现在方法或构造器中的:


@see、@deprecated、@param、@return、@throws和@exception等。


可以出现在属性文档注释的有:

@see、@deprecated等。

文档注释注重点

1,注释的插入:

公有类与接口

公有的的和受保护的方法

公有的和受保护的域

注意:

每个/**...*/文档注释在标记之后紧跟着自由格式(free-form-text)。

标记由@开始,如@author或@param

自由格式文本的第一句应该是一个概要性的句子。javadoc实用程序自动地将这些句子抽取出来形成概要页。

在自由格式文本中可以使用HTML修饰符。

如果文档中有到其他文件的链接,例如图片,就应该将这些文件放到子目录doc-files中。javadoc实用程序将从源目录拷贝这些目录以及其中的文件到文档目录中。如:<img src="doc-files/uml.png" alt="UML diagram">


2,类注释:

类注释必须放在import语句之后,类定义之前。

注释没有必要在每一行的开始用星号*,


3,方法注释:

每一个方法注释必须放在所描述的方法之前。除了通用标记之外,还可以使用以下标记:

@param variable description

这个标记将对当前方法的“param”(参数)部分添加一个条目。这个描述可以占据多行,并使用HTML标记。一个方法的所有@param标记必须放在一起。

 

@return description

这个标记将对当前方法添加“return”(返回)部分。这个描述可以跨越多行,并可以使用HTML标记。

 

@throws class description

这个标记将添加一个注释,用于表示这个方法有可能抛出异常。


4,域注释

只需要对公有域(通常指的是静态常量)建立文档


5,通用注释:

@author name

这个标记将产生一个“author”(作者)条目。可以使用多个@author标记,

每个@author标记对应一名作者

 

@version text

这个标记将产生一个“version”(版本)条目。

text:可以是对当前版本的任何描述

 

@since text

这个标记将产生一个“since”(始于)条目

text:可以是对引入特性的版本描述。

例如:@since version 1.7.1

 

@deprecated test

这个标记将对类、方法或变量添加一个不再使用的注释。

text:给出了取代的建议

例如:@deprecated Use <code>SetVisible(true)</code> instead

 

@see reference

这个标记将在“see also”部分增加一个超级链接。它可以用于类中,也可以用于方法中。

(1)只要提供类、方法或变量的名字,javadoc就会在文档中插入一个超链接,例如:@see com.gaiwu.javanote.MyNoteUseing#raiseSalary(double),

建立一个链接到com.gaiwu.javanote.MyNoteUseing类的raiseSalary(double)

方法的超链接。

注意:当在当前包或当前类时,可以省略包名或包名和类名都省略掉。

(2)指定一个可选的标签作为锚链接,例如:@see <a href="www.horstan.com/corejava.html">The Core Java home page</a>

注意:也可以省略标签,用户看到的锚的名称就是目标代码名或URL

(3)如果@see 标记后面有一个双引号字符,文本就会显示在“see also”部分,

例如:@see “Core java 2volume 2”,可以为这特性添加多个@see标记,

但必须将他们放在一起。

(4)可以在注释中的任何位置放置指向其他类或方法的超级链接,

以及插入一个专用的标记,例如:@link package.class#feature label

 

6,包注释:

若需要产生包注释,就需要在每一个包目录中添加一个单独的文件。有两个选择:

(1)提供一个以package.html命名的HTML文件,在标记<body>...</body>

之间的所有文本都会被抽取出来。

(2)提供一个以package-info.java命名的Java文件。这个文件必须包含一个

初始的以/**和*/界定的javadoc注释,跟随在一个包语句之后。它不应该包含更多的代码或注释。

         为所有的源文件提供一个概述性的注释。这个注释将被放置在一个名为overview.html的文件中,这个文件位于包含所有源文件的父目录中。标记<body></body>之间的所有文本将被抽取出来。当用户从导航栏中选择“Overview”时,就会显示出这些注释内容。


7,注释抽取:

假设将HTML文件将被存放在目录docDirectory下,执行如下命令:

(1)切换到包含想要生成文档的源文件目录。如果有嵌套的包要生成文档,例如com.horsetmann.core.java,就必须切换到包含子目录com的目录。

(2)如果是一个包,

运行命令:javadoc -d docDirectory nameOfPackage

或对于多个包生成文档,

运行:javadoc -d docDirectory nameOfPackage1 nameOfPackage2...

若文件在默认包中,

运行:javadoc -d docDirectory *.java

若省略了-d docDirectory 选项,那么HTML文件就会被提取到当前目录下。

这样有可能产生混乱,不提倡这样做,

http://java.sun.com/j2se/javadoc 联机文档


代码示例:

package com.gaiwu.javanote;

//类文档注释

/**

 * 

 * 

 * 

 * */

public class MyNoteUseing {

    //域文档注释

    /**

     * The "Hearts" card suit

     * */

    public static final int HEARTS = 1;



    //方法文档注释

    /**

     * Raises the salary of an employee

     * @param byPercent the percentage by with to raise the salary(e.g. 10=10%)

     * @retuen the amount of the raise

     * */

    public double raiseSalary(double byPercent)

    {

        double salary = 0;

        salary++;

        double raise=salary*byPercent/100;

        salary+=raise;

        return raise;

    }


    /*

     * 多行文本注释

     * */

    public static void main(String[] args) {


    }

}

 

Annotation(注释)

         Annotation必须使用工具来处理,工具负责提取Annotation里包含的元素,还可以根据这些元素增加额外的功能。

 

Java提供的三个基本Annotation的用法:

1,限定重写父类方法:@Override

@Override就是用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。

@Override只能作用于方法,不能作用于其他程序元素。

代码示例:

public class Fruit

{

    public void foo()

    {

        System.out.println("水果的info方法...");

    }

}

class Apple extends Fruit

{

    //使用@override指定下面方法必须重写父类方法

    @Override

    public void foo()

    {

        System.out.println("苹果重写水果的foo方法...");

    }

}

从以上中可能丝毫看不出程序中的@Override有何作用,因为@Override Annotation的

作用是告诉编译器检查这个方法,并从弗雷查找是否包含一个被该方法重写的方法,否

则就编译出错。它主要是帮助我们避免一些低级错误,例如,我们把Apple类中的foo方

法不小心写成fio,这样的“低级错误”可能导致后期排错时的巨大障碍。


2,标记已过时:@Deprecated

@Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类

、方法时,编译器将会出现警告。

代码示例:

public class Fruit

{

    //定义info方法已过时

    @Deprecated

    public void foo()

    {

        System.out.println("水果的info方法...");

    }

    public static void main(String[] args)

    {

        //下面使用info方法时将会被编译器警告

        new Apple().info();

    }

}

@Deprecatted Annotation与文档注释中的@deprecated标记的作用基本相同,但它们的

用法不同,前者是JDK1.5才支持的注释,无须放在文档注释语法(/**...*/部分)中,

而是直接用于修饰程序中的程序单元,如类、方法、接口等。

3,抑制编译器警告:@SuppressWarnings

@SuppressWarnings指示被Annotation表示的程序元素取消显示指定的编译器警告。

代码示例:

//关闭整个类里的编译器警告

@SuppressWarnings(value="unchecked")

public class SuppressWarningsTest

{

    public static void main(String[] args)

    {

        List<String> myList=new ArrayList();

    }

}

 

自定义注释

代码示例:

//定义一个简单的Annotation类型

public @interface Test

{

}

使用Annotation时的语法非常类似于public、final这样的修饰符。通常可用于修饰程

序中的类、方法、变量、接口等定义,通常我们会把Annotation放在所有修饰符之前,

而且由于使用Annotation时可能还需要为其成员变量指定值,因而Annotation的长度可

能较长,所以通常把Annotation另放一行,如下程序所示:

//使用@Test修饰类dingyi

@Test

public class MyClass

{

    ...

}

默认情况下,Annotation可用于修饰任何程序元素,包括类、接口、方法等,如下程序

使用@TestAnnotation来修饰方法。

public class MyClass

{

    //使用@testAnnotation修饰方法

    @Test

    public void info()

    {

        ...

    }

    ...

}

Annotation可以带成员变量,Annotation定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。如下代码所示:

public @interface MyTag

{

    //定义了两个成员变量的Annotation

    //Annotation中的成员变量以方法的形式来定义

  //以defauly为两个成员变量指定初始值。

    String name() default "lili";

    int age() default 32;

}

public class Test

{

    //使用带成员变量的Annotation时,需要为成员变量赋值

    @MyTag(name="xx",age=6)

    public void info()

    {

    }

}


根据Annotation是否可以包含成员变量,我们可以把Annotation分为两类:

1,标记Annotation:

一个没有成员定义的Annotation类型被称为标记。这种Annotation仅使用自身的存在与否来为我们提供信息。

2,元数据Annotation:

那些包含成员变量的Annotation,因为它们可接受更多元数据,所以被称为元数据Annotation。

提取Annotation的信息

         java在java.lang.reflect包下新增了AnnotatedElement接口,该接口代表程序中可以接受注释的程序元素,该接口主要有如下几个实现类:

1,Class:类定义

2,Constructor:构造器定义

3,Field:类的成员变量定义。

4,Method:类的方法定义。

5,Package:类的包定义。

AnnotationElement接口是所有程序元素(如Class、Method、Constructor)的父接口程序通过反射获取了某个类的AnnotationElement对象(如Class、Method、Constructor)之后,程序就可以调用该对象的如下三个方法来访问Annotation信息:

getAnnotation(Class<T> annotationClass):

返回改程序元素上存在的、指定类型的注释,如果该类型的注释不存在,则返回null。

 

Annotation[] getAnnotations():

返回该程序元素上存在的所有注释

boolean isAnnotationPresent(Class<? extends Annotation>annotationClass):

判断改程序元素上是否包含指定类型的注释,存在则返回true,否则返回false。


获取Test类的info方法里的所有注释,并将这些注释打印出来。

//获取Test类的info方法的所有注释

Annotation[] aArray=Class.forName("Test").getMethod("info").getAnnotations();

//遍历所有注释

for(Anotation an:aArray)

{

    System.out.println(an);

}

如果我们需要获取某个注释里的元数据,则可以将注释强制类型转换成所需的注释类型,然后通过注释对象的抽象方法来访问这些元数据,代码如下所示:

//获取tt对象的info方法所包含的所有注释

Annotation[] annotation=tt.getClass().getMethod("info").getAnnotations();

//遍历每个注释对象

for(Annotation tag:annotation)

{

    //如果注释类型是MyTagl类型

    if(tag instanceof MyTag1)

    {

        System.out.println("Tag is:"+tag);

        //将tag强制类型转换为MyTag1

        //并调用tag对象的method1和method2两个方法

        System.out.println("tag.name():"+(MyTag1)tag.method1);

        System.out.println("tag.name():"+(MyTag1)tag.method2);

    }

    //如果注释类型是MyTag2

    if(tag instanceof MyTag2)

    {

        System.out.println("Tag is:"+tag);

        //将tag强制类型转换为MyTag2

        //并调用tag对象的method1和method2两个方法

        System.out.println("tag.name():"+(MyTag2)tag.method1);

        System.out.println("tag.name():"+(MyTag2)tag.method2);

    }

}

 

使用Annotation例子

 

JDK元Annotation

JDK在java.lang.annotation包下提供了四个Meta Annotation(元 Annotation),这四个Annotation都是用于修饰其他Annotation定义。

1,使用@Retention

@Retention只能用于修饰一个Annotation定义,用于指定该Annotation可以保罗多长时间。@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention必须为该value成员变量指定值,值只有如下三个:

RetentionPolicy.CLASS:编译器将把注释记录在class文件中。当运行Java程序时,JVM不再保留注释。这是默认值。

RetentionPolicy.RUNTIME:编译器将把注释记录在class文件中。当运行Java程序时,JVM也会保留注释,程序可以通过反射获取该注释。

Ret.SOUREC:编译器直接丢弃这种策略的注释。

代码示例:

//定义下面的Testable Annotation的保留到运行时

@Retention(value=RetentionPolicy.RUNTIME)

public @interface Testable{}

//定义下面的Testable Annotation将被编译器直接丢弃

@Retention(RetentionPolicy.SOURCE)

public @interface Testable{}

注意:若我们定义的Annotation类型里只有一个value成员变量,使用该Annotation时可以直接在Annotation后的括号里指定value成员变量的值,无须使用name=value的形式。

 

2,使用@Target

@Target用于指定被修饰的Annotation能用于修饰哪些程序元素。@Target Annotation包含一个名为value的成员变量,成员变量的值只能是下面的几个:

ElementType.ANNOTATION_TYPE:

指定该策略的Annotation只能修饰Annotation。

 

ElementType.CONSTRUCTOR:

指定该策略的Annotation能修饰构造器。

 

ElementType.FIELD:

指定该策略的Annotation只能修饰成员变量。

 

ElementType.LOCAL_VARIABLE:

指定该策略的Annotation只能修饰局部变量。

 

ElementType.METHOD:

指定该策略的Annotation只能修饰方法定义。

 

ElementType.PACKAGE:

指定该策略的Annotation只能修饰包定义。

 

ElementType.PARAMETER:

指定该策略的Annotation可以修饰参数。

 

ElementType.TYPE:

指定该策略的Annotation可以修饰类、接口(包括注释类型)或枚举定义。

代码示例:

@Target(ElementType.FIELD)

public @interface ActionListenerFor{}

@Target(ElementType.METHOD)

public @interface Testable{}

 

3,使用@Documented

@Documented用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档,如果定义Annotation类时使用了@Documented修饰,则所有使用该Annotation修饰的程序元素的API文档中将会包含该Annotation说明。

代码定义:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

//定义Testable Annotation将被javadoc工具提取

@Documented

public @interface Testable{}

public class MyTest

{

    //使用@Test修饰info方法

    @Test

    public void info()

    {

        System.out.println("info方法...");

    }

}

4,使用@Inherited

@Inherited元Annotation指定被它修饰的Annotation将具有继承性:如果某个类使用了Annotation(定义该Annotation时使用了@Inherited修饰)修饰,则其子类将自动具有A注释。

代码示例:

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Inherited

public @interface Inheritable{}


//使用@Inheritable修饰的Base类

@Inheritable

class Base

{


}

//TestInheritable类只是继承了Base类。

//并未直接使用@Inheritable Annotation修饰

public class TestInheritable extends Base

{

    public static void main(String[] args)

    {

        //打印TestInheritable类是否具有Inheritable Annotation

        System.out.println(TestInHeritable.class.isAnnotationPresent(Inheritable.class));

    }

}

输出结果为:true

 

 

你可能感兴趣的:(java,注释)