寫一個(gè)使用該注解的類:

創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元山陽做網(wǎng)站,已為上家服務(wù),為山陽各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
import java.io.IOException;
/**
* Created by Administrator on 2015/1/18.
*/
@TestAnnotation(count = 0x7fffffff)
public class TestMain {
public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException {
TestAnnotation annotation = TestMain.class.getAnnotation(TestAnnotation.class);
System.out.println(annotation.count());
System.in.read();
}
}
反編譯一下這段代碼:
Classfile /e:/workspace/intellij/SpringTest/target/classes/TestMain.class
Last modified 2015-1-20; size 1006 bytes
MD5 checksum a2d5367ea568240f078d5fb1de917550
Compiled from "TestMain.java"
public class TestMain
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#34 // java/lang/Object."init":()V
#2 = Class #35 // TestMain
#3 = Class #36 // TestAnnotation
#4 = Methodref #37.#38 // java/lang/Class.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
#5 = Fieldref #39.#40 // java/lang/System.out:Ljava/io/PrintStream;
#6 = InterfaceMethodref #3.#41 // TestAnnotation.count:()I
#7 = Methodref #42.#43 // java/io/PrintStream.println:(I)V
#8 = Fieldref #39.#44 // java/lang/System.in:Ljava/io/InputStream;
#9 = Methodref #45.#46 // java/io/InputStream.read:()I
#10 = Class #47 // java/lang/Object
#11 = Utf8 init
#12 = Utf8 ()V
#13 = Utf8 Code
#14 = Utf8 LineNumberTable
#15 = Utf8 LocalVariableTable
#16 = Utf8 this
#17 = Utf8 LTestMain;
#18 = Utf8 main
#19 = Utf8 ([Ljava/lang/String;)V
#20 = Utf8 args
#21 = Utf8 [Ljava/lang/String;
#22 = Utf8 annotation
#23 = Utf8 LTestAnnotation;
#24 = Utf8 Exceptions
#25 = Class #48 // java/lang/InterruptedException
#26 = Class #49 // java/lang/NoSuchFieldException
#27 = Class #50 // java/lang/IllegalAccessException
#28 = Class #51 // java/io/IOException
#29 = Utf8 SourceFile
#30 = Utf8 TestMain.java
#31 = Utf8 RuntimeVisibleAnnotations
#32 = Utf8 count
#33 = Integer 2147483647
#34 = NameAndType #11:#12 // "init":()V
#35 = Utf8 TestMain
#36 = Utf8 TestAnnotation
#37 = Class #52 // java/lang/Class
#38 = NameAndType #53:#54 // getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
#39 = Class #55 // java/lang/System
#40 = NameAndType #56:#57 // out:Ljava/io/PrintStream;
#41 = NameAndType #32:#58 // count:()I
#42 = Class #59 // java/io/PrintStream
#43 = NameAndType #60:#61 // println:(I)V
#44 = NameAndType #62:#63 // in:Ljava/io/InputStream;
#45 = Class #64 // java/io/InputStream
#46 = NameAndType #65:#58 // read:()I
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/InterruptedException
#49 = Utf8 java/lang/NoSuchFieldException
#50 = Utf8 java/lang/IllegalAccessException
#51 = Utf8 java/io/IOException
#52 = Utf8 java/lang/Class
#53 = Utf8 getAnnotation
#54 = Utf8 (Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
#55 = Utf8 java/lang/System
#56 = Utf8 out
#57 = Utf8 Ljava/io/PrintStream;
#58 = Utf8 ()I
#59 = Utf8 java/io/PrintStream
#60 = Utf8 println
#61 = Utf8 (I)V
#62 = Utf8 in
#63 = Utf8 Ljava/io/InputStream;
#64 = Utf8 java/io/InputStream
#65 = Utf8 read
{
public TestMain();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."init":()V
4: return
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestMain;
public static void main(java.lang.String[]) throws java.lang.InterruptedException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.io.IOException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: ldc #2 // class TestMain
2: ldc #3 // class TestAnnotation
4: invokevirtual #4 // Method java/lang/Class.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
7: checkcast #3 // class TestAnnotation
10: astore_1
11: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
14: aload_1
15: invokeinterface #6, 1 // InterfaceMethod TestAnnotation.count:()I
20: invokevirtual #7 // Method java/io/PrintStream.println:(I)V
23: getstatic #8 // Field java/lang/System.in:Ljava/io/InputStream;
26: invokevirtual #9 // Method java/io/InputStream.read:()I
29: pop
30: return
LineNumberTable:
line 10: 0
line 11: 11
line 12: 23
line 13: 30
LocalVariableTable:
Start Length Slot Name Signature
0 31 0 args [Ljava/lang/String;
11 20 1 annotation LTestAnnotation;
Exceptions:
throws java.lang.InterruptedException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.io.IOException
}
SourceFile: "TestMain.java"
RuntimeVisibleAnnotations:
0: #23(#32=I#33)
最后一行的代碼說明,注解`TestAnnotation`的屬性設(shè)置是在編譯時(shí)就確定了的。(對(duì)屬性的說明在[這里][1])。
然后,運(yùn)行上面的程序,通過CLHSDB在eden區(qū)找到注解實(shí)例,
hsdb scanoops 0x00000000e1b80000 0x00000000e3300000 TestAnnotation
0x00000000e1d6c360 com/sun/proxy/$Proxy1
類型`com/sun/proxy/$Proxy1`是jdk動(dòng)態(tài)代理生成對(duì)象時(shí)的默認(rèn)類型,其中
`com.sun.proxy`是默認(rèn)的包名,定義于`ReflectUtil`類的`PROXY_PACKAGE`字段中。代理類名`$PROXY1`
包含兩部分,其中前綴`$PROXY`是jdk種默認(rèn)的代理類類名前綴(參見`java.lang.reflect.Proxy`類的javadoc),
后的1是自增的結(jié)果。
多注了些控制流程,希望我的注釋能夠?qū)δ阌袔椭?/p>
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GoodLucky extends JFrame implements ActionListener{
JTextField tf = new JTextField(); //實(shí)例化一個(gè)文本域
//設(shè)置兩個(gè)按鈕
JButton b1 = new JButton("開始");
JButton b2 = new JButton("停止");
boolean isGo = false;
//構(gòu)造函數(shù)
public GoodLucky(){
b1.setActionCommand("start");//在開始按鈕上設(shè)置一個(gè)動(dòng)作監(jiān)聽 start
JPanel p = new JPanel(); //實(shí)例化一個(gè)可視化容器
//將兩個(gè)按鈕添加到可視化容器上面,用add方法
p.add(b1);
p.add(b2);
//在兩個(gè)按鈕上增加監(jiān)聽的屬性,自動(dòng)調(diào)用下面的監(jiān)聽處理方法actionPerformed(ActionEvent e),如果要代碼有更好的可讀性,可用內(nèi)部類實(shí)現(xiàn)動(dòng)作
//監(jiān)聽處理。
b1.addActionListener(this);
b2.addActionListener(this);
//將停止按鈕設(shè)置為不可編輯(即不可按的狀態(tài))
b2.setEnabled(false);
this.getContentPane().add(tf,"North"); //將上面的文本域放在面板的北方,也就是上面(上北下南左西右東)
this.getContentPane().add(p,"South"); //將可視化容器pannel放在南邊,也就是下面
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //設(shè)置用戶在此窗體上發(fā)起 "close" 時(shí)默認(rèn)執(zhí)行的操作,參數(shù)EXIT_ON_CLOSE是使用 System exit 方法退出應(yīng)用程序。僅在應(yīng)用程序中使用
this.setSize(300,200); //設(shè)置面板大小,寬和高
this.setLocation(300,300); //設(shè)置面板剛開始的出現(xiàn)的位置
Cursor cu = new Cursor(Cursor.HAND_CURSOR); //用指定名稱創(chuàng)建一個(gè)新的定制光標(biāo)對(duì)象,參數(shù)表示手狀光標(biāo)類型
this.setCursor(cu); //為指定的光標(biāo)設(shè)置光標(biāo)圖像,即設(shè)置光標(biāo)圖像為上面所創(chuàng)建的手狀光標(biāo)類型
this.setVisible(true); //將面板可視化設(shè)置為true,即可視,如果為false,即程序運(yùn)行時(shí)面板會(huì)隱藏
tf.setText("welcome you! "); //設(shè)置面板的標(biāo)題為歡迎
this.go(); //調(diào)用go方法
}
public void go(){
while(true){ //這里是死循環(huán),也就是說用戶不點(diǎn)擊停止按鈕的話他一直循環(huán)出現(xiàn)隨機(jī)數(shù),直到用戶點(diǎn)擊停止按鈕循環(huán)才能推出,具體流程在actionPerformed方法中控制。
if(isGo == true){ //上面所定義的isGo的初始值為false,所以程序第一次到此會(huì)跳過
String s = ""; //設(shè)置空字符串
for(int j = 1; j = 7;j++){ //產(chǎn)生7個(gè)隨機(jī)數(shù)
int i = (int)(Math.random() * 36) + 1;//每個(gè)隨機(jī)數(shù)產(chǎn)生方式,這里定義靈活,可以自由定義隨機(jī)數(shù)產(chǎn)生的方式
if(i 10){
s = s + " 0" + i; //如果產(chǎn)生的隨機(jī)數(shù)小于10的話做處理:這里就牽扯到一個(gè)重要的概念,簡單敘述一下:
/*
當(dāng)一個(gè)字符串與一個(gè)整型數(shù)項(xiàng)相加的意思是連接,上面的s = s + " 0" + i的意思是字符串s鏈接0再連接整型i值,而不會(huì)導(dǎo)致0和整型的i相加,
產(chǎn)生的效果為s0i,由于s為空字符串(上面定義過的),所以當(dāng)i小于零時(shí),在個(gè)位數(shù)前面加上0,比如產(chǎn)生的隨機(jī)數(shù)i為7的話,顯示效果為 07.
*/
}else{
s = s + " " + i; //如果產(chǎn)生的隨機(jī)數(shù)比10打的話,那么加上空格顯示,即數(shù)字和數(shù)字之間有個(gè)空格
}
//以上循環(huán)循環(huán)七次,以保證能出現(xiàn)7個(gè)隨機(jī)數(shù)
}
tf.setText(s); //將產(chǎn)生的隨機(jī)數(shù)全部顯示在文本域上,用文本域?qū)ο髏f調(diào)用它的設(shè)置文本的方法setText(String)實(shí)現(xiàn)。
}
//以下為線程延遲
try{
Thread.sleep(10); //線程類同步方法sleep,睡眠方法,括號(hào)里的單位為ms。
}catch(java.lang.InterruptedException e){
e.printStackTrace(); //異常捕獲,不用多說。
}
}
}
//以下是上面設(shè)置的事件監(jiān)聽的具體處理辦法,即監(jiān)聽時(shí)間處理方法,自動(dòng)調(diào)用
public void actionPerformed(ActionEvent e){ //傳入一個(gè)動(dòng)作事件的參數(shù)e
String s = e.getActionCommand(); //設(shè)置字符串s來存儲(chǔ)獲得動(dòng)作監(jiān)聽,上面的start
/*
以下這個(gè)條件語句塊的作用為:用戶點(diǎn)擊開始后(捕獲start,用方法getActionCommand()),將命令觸發(fā)設(shè)置為true,從而執(zhí)行上面的go方法中的循環(huán)體(因?yàn)檠h(huán)體中要求isGo參數(shù)為true,而初始為false)。
執(zhí)行循環(huán)快產(chǎn)生隨機(jī)數(shù),并將開始按鈕不可編輯化,而用戶只可以使用停止按鈕去停止。如果用戶按下停止時(shí),也就是沒有傳入?yún)?shù)“start”的時(shí)候,
執(zhí)行else語句塊中的語句,isGo設(shè)置為false,將不執(zhí)行上面go中的循環(huán)語句塊,從而停止產(chǎn)生隨機(jī)數(shù),并顯示,并且把開始按鈕設(shè)置為可用,而把
停止按鈕設(shè)置為不可用,等待用戶按下開始再去開始新一輪循環(huán)產(chǎn)生隨機(jī)數(shù)。
*/
if(s.equals("start")){ //如果捕獲到start,也就是用戶觸發(fā)了動(dòng)作監(jiān)聽器,那么下面處理
isGo = true; //設(shè)置isGo為true
b1.setEnabled(false); //將開始按鈕設(shè)置為不可用
b2.setEnabled(true); //將停止按鈕設(shè)置為可用
}else{
isGo = false; //將isGo設(shè)置為false,isGo為循環(huán)標(biāo)志位
b2.setEnabled(false); //設(shè)置停止按鈕為不可用(注意看是b2,b2是停止按鈕)
b1.setEnabled(true); //設(shè)置開始按鈕為可用
}
}
public static void main(String[] args){
new GoodLucky(); //產(chǎn)生類的實(shí)例,執(zhí)行方法
}
}
圣誕平安夜了,祝朋友開心快樂!
好像和另外一個(gè)一樣,貼一下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GoodLucky extends JFrame implements ActionListener{
JTextField tf = new JTextField(); //實(shí)例化一個(gè)文本域
//設(shè)置兩個(gè)按鈕
JButton b1 = new JButton("開始");
JButton b2 = new JButton("停止");
boolean isGo = false;
//構(gòu)造函數(shù)
public GoodLucky(){
b1.setActionCommand("start");//在開始按鈕上設(shè)置一個(gè)動(dòng)作監(jiān)聽 start
JPanel p = new JPanel(); //實(shí)例化一個(gè)可視化容器
//將兩個(gè)按鈕添加到可視化容器上面,用add方法
p.add(b1);
p.add(b2);
//在兩個(gè)按鈕上增加監(jiān)聽的屬性,自動(dòng)調(diào)用下面的監(jiān)聽處理方法actionPerformed(ActionEvent e),如果要代碼有更好的可讀性,可用內(nèi)部類實(shí)現(xiàn)動(dòng)作
//監(jiān)聽處理。
b1.addActionListener(this);
b2.addActionListener(this);
//將停止按鈕設(shè)置為不可編輯(即不可按的狀態(tài))
b2.setEnabled(false);
this.getContentPane().add(tf,"North"); //將上面的文本域放在面板的北方,也就是上面(上北下南左西右東)
this.getContentPane().add(p,"South"); //將可視化容器pannel放在南邊,也就是下面
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //設(shè)置用戶在此窗體上發(fā)起 "close" 時(shí)默認(rèn)執(zhí)行的操作,參數(shù)EXIT_ON_CLOSE是使用 System exit 方法退出應(yīng)用程序。僅在應(yīng)用程序中使用
this.setSize(300,200); //設(shè)置面板大小,寬和高
this.setLocation(300,300); //設(shè)置面板剛開始的出現(xiàn)的位置
Cursor cu = new Cursor(Cursor.HAND_CURSOR); //用指定名稱創(chuàng)建一個(gè)新的定制光標(biāo)對(duì)象,參數(shù)表示手狀光標(biāo)類型
this.setCursor(cu); //為指定的光標(biāo)設(shè)置光標(biāo)圖像,即設(shè)置光標(biāo)圖像為上面所創(chuàng)建的手狀光標(biāo)類型
this.setVisible(true); //將面板可視化設(shè)置為true,即可視,如果為false,即程序運(yùn)行時(shí)面板會(huì)隱藏
tf.setText("welcome you! "); //設(shè)置面板的標(biāo)題為歡迎
this.go(); //調(diào)用go方法
}
public void go(){
while(true){ //這里是死循環(huán),也就是說用戶不點(diǎn)擊停止按鈕的話他一直循環(huán)出現(xiàn)隨機(jī)數(shù),直到用戶點(diǎn)擊停止按鈕循環(huán)才能推出,具體流程在actionPerformed方法中控制。
if(isGo == true){ //上面所定義的isGo的初始值為false,所以程序第一次到此會(huì)跳過
String s = ""; //設(shè)置空字符串
for(int j = 1; j = 7;j++){ //產(chǎn)生7個(gè)隨機(jī)數(shù)
int i = (int)(Math.random() * 36) + 1;//每個(gè)隨機(jī)數(shù)產(chǎn)生方式,這里定義靈活,可以自由定義隨機(jī)數(shù)產(chǎn)生的方式
if(i 10){
s = s + " 0" + i; //如果產(chǎn)生的隨機(jī)數(shù)小于10的話做處理:這里就牽扯到一個(gè)重要的概念,簡單敘述一下:
/*
當(dāng)一個(gè)字符串與一個(gè)整型數(shù)項(xiàng)相加的意思是連接,上面的s = s + " 0" + i的意思是字符串s鏈接0再連接整型i值,而不會(huì)導(dǎo)致0和整型的i相加,
產(chǎn)生的效果為s0i,由于s為空字符串(上面定義過的),所以當(dāng)i小于零時(shí),在個(gè)位數(shù)前面加上0,比如產(chǎn)生的隨機(jī)數(shù)i為7的話,顯示效果為 07.
*/
}else{
s = s + " " + i; //如果產(chǎn)生的隨機(jī)數(shù)比10打的話,那么加上空格顯示,即數(shù)字和數(shù)字之間有個(gè)空格
}
//以上循環(huán)循環(huán)七次,以保證能出現(xiàn)7個(gè)隨機(jī)數(shù)
}
tf.setText(s); //將產(chǎn)生的隨機(jī)數(shù)全部顯示在文本域上,用文本域?qū)ο髏f調(diào)用它的設(shè)置文本的方法setText(String)實(shí)現(xiàn)。
}
//以下為線程延遲
try{
Thread.sleep(10); //線程類同步方法sleep,睡眠方法,括號(hào)里的單位為ms。
}catch(java.lang.InterruptedException e){
e.printStackTrace(); //異常捕獲,不用多說。
}
}
}
//以下是上面設(shè)置的事件監(jiān)聽的具體處理辦法,即監(jiān)聽時(shí)間處理方法,自動(dòng)調(diào)用
public void actionPerformed(ActionEvent e){ //傳入一個(gè)動(dòng)作事件的參數(shù)e
String s = e.getActionCommand(); //設(shè)置字符串s來存儲(chǔ)獲得動(dòng)作監(jiān)聽,上面的start
/*
以下這個(gè)條件語句塊的作用為:用戶點(diǎn)擊開始后(捕獲start,用方法getActionCommand()),將命令觸發(fā)設(shè)置為true,從而執(zhí)行上面的go方法中的循環(huán)體(因?yàn)檠h(huán)體中要求isGo參數(shù)為true,而初始為false)。
執(zhí)行循環(huán)快產(chǎn)生隨機(jī)數(shù),并將開始按鈕不可編輯化,而用戶只可以使用停止按鈕去停止。如果用戶按下停止時(shí),也就是沒有傳入?yún)?shù)“start”的時(shí)候,
執(zhí)行else語句塊中的語句,isGo設(shè)置為false,將不執(zhí)行上面go中的循環(huán)語句塊,從而停止產(chǎn)生隨機(jī)數(shù),并顯示,并且把開始按鈕設(shè)置為可用,而把
停止按鈕設(shè)置為不可用,等待用戶按下開始再去開始新一輪循環(huán)產(chǎn)生隨機(jī)數(shù)。
*/
if(s.equals("start")){ //如果捕獲到start,也就是用戶觸發(fā)了動(dòng)作監(jiān)聽器,那么下面處理
isGo = true; //設(shè)置isGo為true
b1.setEnabled(false); //將開始按鈕設(shè)置為不可用
b2.setEnabled(true); //將停止按鈕設(shè)置為可用
}else{
isGo = false; //將isGo設(shè)置為false,isGo為循環(huán)標(biāo)志位
b2.setEnabled(false); //設(shè)置停止按鈕為不可用(注意看是b2,b2是停止按鈕)
b1.setEnabled(true); //設(shè)置開始按鈕為可用
}
}
public static void main(String[] args){
new GoodLucky(); //產(chǎn)生類的實(shí)例,執(zhí)行方法
}
}
我看動(dòng)力節(jié)點(diǎn)的java基礎(chǔ)大全301集教中的三種注釋方法:
1、單行注釋?? //注釋的內(nèi)容
2、多行注釋??/*......*/
3、/**......*/,這種方式和第二種方式相似。這種格式是為了便于javadoc程序自動(dòng)生成文檔。
下面介紹一下Javadoc的標(biāo)記:
特別聲明:
(1)javadoc針對(duì)public類生成注釋文檔
(2)javadoc只能在public、protected修飾的方法或者屬性之上
(3)javadoc注釋的格式化:前導(dǎo)*號(hào)和HTML標(biāo)簽
(4)javadoc注釋要僅靠在類、屬性、方法之前
下面主要舉例說明第三種注釋的應(yīng)用:
(1)首先編寫.java文件
(2)在命令行中執(zhí)行以下dos命令:
javadoc *.java //根據(jù)相應(yīng)的Java源代碼及其說明語句生成HTML文檔
//javadoc標(biāo)記:是@開頭的,對(duì)javadoc而言,特殊的標(biāo)記。
(3)在當(dāng)前目錄下就會(huì)產(chǎn)生doc文件夾,里面有一系列的.html文件
附上代碼:
[java]?view plain?copy
span?style="font-size:18px;"*/
/**javadoc注釋的內(nèi)容
*/
public?class?Hello{
/**屬性上的注釋*/
public?String?name;
/**這是main方法,是程序的入口
*@param?args?用戶輸入?yún)?shù)
*/
public?static?void?main(String[]?args){
System.out.println("Hello?World!");
f1();
}
/**?這是第1個(gè)方法,其作用是...*/
public?static?void?f1(){
System.out.println("f1()!");
}
}/span
[java]?view plain?copy
span?style="font-size:18px;"import?java.io.IOException;
/**javadoc注釋內(nèi)容
*@since?1.0
*@version?1.1
*@author?Blue?Jey
*br鏈接到另一個(gè)文檔{@link?Hello},就這些
*see?Hello
*/
public?class?HelloWorld{
/**非public,protected?屬性上的注釋不生成*/
public?String?name;
/**這是main方法,是程序的入口
*@param?args?用戶輸入的參數(shù),是數(shù)組
*@throws?IOException?main方法io異常
*/
public?static?void?main(String?args[])?throws?IOException{
System.out.println("hello?World!");
f1();
f2(1);
}
/**這是第一個(gè)方法,其作用是....
*@deprecated?從版本1.2開始,不再建議使用此方法
*/
public?static?void?f1(){
System.out.println("fl()!");
}
/**這是第二個(gè)方法,其作用是....
*@return?返回是否OK
*@param?i?輸入?yún)?shù)i
*@see?Hello
*@throws?IOException?io異常
*/
public?static?String?f2(int?i)throws?IOException{
System.out.println("f1()!");
return?"OK";
}
}?/span
注意:
如果源文件中有用到@version,@author標(biāo)記,則在執(zhí)行javadoc命令時(shí),要加-version?-author
javadoc?-version?-author?-d?doc?*.java
(其中用-version用于提取源文件中的版本信息?-author用于提取源文件中的作者信息)
1、單行(single-line)--短注釋://…… 單獨(dú)行注釋:在代碼中單起一行注釋, 注釋前最好有一行空行,并與其后的代碼具有一樣的縮進(jìn)層級(jí)。如果單行無法完成,則應(yīng)采用塊注釋。 注釋格式:/* 注釋內(nèi)容 */ 行頭注釋:在代碼行的開頭進(jìn)行注釋。主要為了使該行代碼失去意義。 注釋格式:// 注釋內(nèi)容 行尾注釋:尾端(trailing)--極短的注釋,在代碼行的行尾進(jìn)行注釋。一般與代碼行后空8(至少4)個(gè)格,所有注釋必須對(duì)齊。 注釋格式:代碼 + 8(至少4)個(gè)空格 + // 注釋內(nèi)容 2、塊(block)--塊注釋:/*……*/ 注釋若干行,通常用于提供文件、方法、數(shù)據(jù)結(jié)構(gòu)等的意義與用途的說明,或者算法的描述。一般位于一個(gè)文件或者一個(gè)方法的前面,起到引導(dǎo)的作用,也可以根據(jù)需要放在合適的位置。這種域注釋不會(huì)出現(xiàn)在HTML報(bào)告中。注釋格式通常寫成: /* * 注釋內(nèi)容 */ 3、文檔注釋:/**……*/ 注釋若干行,并寫入javadoc文檔。每個(gè)文檔注釋都會(huì)被置于注釋定界符 /**......*/ ...
用一個(gè)詞就可以描述注解,那就是元數(shù)據(jù),即一種描述數(shù)據(jù)的數(shù)據(jù)。所以,可以說注解就是源代碼的元數(shù)據(jù)。比如,下面這段代碼:
@Override
public String toString() {
return "This is String Representation of current object.";
}
上面的代碼中,我重寫了toString()方法并使用了@Override注解。但是,即使我不使用@Override注解標(biāo)記代碼,程序也能夠正常執(zhí)行。那么,該注解表示什么?這么寫有什么好處嗎?事實(shí)上,@Override告訴編譯器這個(gè)方法是一個(gè)重寫方法(描述方法的元數(shù)據(jù)),如果父類中不存在該方法,編譯器便會(huì)報(bào)錯(cuò),提示該方法沒有重寫父類中的方法。如果我不小心拼寫錯(cuò)誤,例如將toString()寫成了toStrring(){double r},而且我也沒有使用@Override注解,那程序依然能編譯運(yùn)行。但運(yùn)行結(jié)果會(huì)和我期望的大不相同。現(xiàn)在我們了解了什么是注解,并且使用注解有助于閱讀程序。
Annotation是一種應(yīng)用于類、方法、參數(shù)、變量、構(gòu)造器及包聲明中的特殊修飾符。它是一種由JSR-175標(biāo)準(zhǔn)選擇用來描述元數(shù)據(jù)的一種工具。
為什么要引入注解?
使用Annotation之前(甚至在使用之后),XML被廣泛的應(yīng)用于描述元數(shù)據(jù)。不知何時(shí)開始一些應(yīng)用開發(fā)人員和架構(gòu)師發(fā)現(xiàn)XML的維護(hù)越來越糟糕了。他們希望使用一些和代碼緊耦合的東西,而不是像XML那樣和代碼是松耦合的(在某些情況下甚至是完全分離的)代碼描述。如果你在Google中搜索“XML vs. annotations”,會(huì)看到許多關(guān)于這個(gè)問題的辯論。最有趣的是XML配置其實(shí)就是為了分離代碼和配置而引入的。上述兩種觀點(diǎn)可能會(huì)讓你很疑惑,兩者觀點(diǎn)似乎構(gòu)成了一種循環(huán),但各有利弊。下面我們通過一個(gè)例子來理解這兩者的區(qū)別。
假如你想為應(yīng)用設(shè)置很多的常量或參數(shù),這種情況下,XML是一個(gè)很好的選擇,因?yàn)樗粫?huì)同特定的代碼相連。如果你想把某個(gè)方法聲明為服務(wù),那么使用Annotation會(huì)更好一些,因?yàn)檫@種情況下需要注解和方法緊密耦合起來,開發(fā)人員也必須認(rèn)識(shí)到這點(diǎn)。
另一個(gè)很重要的因素是Annotation定義了一種標(biāo)準(zhǔn)的描述元數(shù)據(jù)的方式。在這之前,開發(fā)人員通常使用他們自己的方式定義元數(shù)據(jù)。例如,使用標(biāo)記interfaces,注釋,transient關(guān)鍵字等等。每個(gè)程序員按照自己的方式定義元數(shù)據(jù),而不像Annotation這種標(biāo)準(zhǔn)的方式。
目前,許多框架將XML和Annotation兩種方式結(jié)合使用,平衡兩者之間的利弊。
Annotation是如何工作的?怎么編寫自定義的Annotation?
在講述這部分之前,建議你首先下載Annotation的示例代碼AnnotationsSample.zip 。下載之后放在你習(xí)慣使用的IDE中,這些代碼會(huì)幫助你更好的理解Annotation機(jī)制。
編寫Annotation非常簡單,可以將Annotation的定義同接口的定義進(jìn)行比較。我們來看兩個(gè)例子:一個(gè)是標(biāo)準(zhǔn)的注解@Override,另一個(gè)是用戶自定義注解@Todo。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
對(duì)于@Override注釋你可能有些疑問,它什么都沒做,那它是如何檢查在父類中有一個(gè)同名的函數(shù)呢。當(dāng)然,不要驚訝,我是逗你玩的。@Override注解的定義不僅僅只有這么一點(diǎn)代碼。這部分內(nèi)容很重要,我不得不再次重復(fù):Annotations僅僅是元數(shù)據(jù),和業(yè)務(wù)邏輯無關(guān)。理解起來有點(diǎn)困難,但就是這樣。如果Annotations不包含業(yè)務(wù)邏輯,那么必須有人來實(shí)現(xiàn)這些邏輯。元數(shù)據(jù)的用戶來做這個(gè)事情。Annotations僅僅提供它定義的屬性(類/方法/包/域)的信息。Annotations的用戶(同樣是一些代碼)來讀取這些信息并實(shí)現(xiàn)必要的邏輯。
當(dāng)我們使用Java的標(biāo)注Annotations(例如@Override)時(shí),JVM就是一個(gè)用戶,它在字節(jié)碼層面工作。到這里,應(yīng)用開發(fā)人員還不能控制也不能使用自定義的注解。因此,我們講解一下如何編寫自定義的Annotations。
我們來逐個(gè)講述編寫自定義Annotations的要點(diǎn)。上面的例子中,你看到一些注解應(yīng)用在注解上。
J2SE5.0版本在 java.lang.annotation提供了四種元注解,專門注解其他的注解:
@Documented –注解是否將包含在JavaDoc中
@Retention –什么時(shí)候使用該注解
@Target? –注解用于什么地方
@Inherited – 是否允許子類繼承該注解
@Documented–一個(gè)簡單的Annotations標(biāo)記注解,表示是否將注解信息添加在java文檔中。
@Retention– 定義該注解的生命周期。
RetentionPolicy.SOURCE – 在編譯階段丟棄。這些注解在編譯結(jié)束之后就不再有任何意義,所以它們不會(huì)寫入字節(jié)碼。@Override, @SuppressWarnings都屬于這類注解。
RetentionPolicy.CLASS – 在類加載的時(shí)候丟棄。在字節(jié)碼文件的處理中有用。注解默認(rèn)使用這種方式。
RetentionPolicy.RUNTIME– 始終不會(huì)丟棄,運(yùn)行期也保留該注解,因此可以使用反射機(jī)制讀取該注解的信息。我們自定義的注解通常使用這種方式。
@Target – 表示該注解用于什么地方。如果不明確指出,該注解可以放在任何地方。以下是一些可用的參數(shù)。需要說明的是:屬性的注解是兼容的,如果你想給7個(gè)屬性都添加注解,僅僅排除一個(gè)屬性,那么你需要在定義target包含所有的屬性。
ElementType.TYPE:用于描述類、接口或enum聲明
ElementType.FIELD:用于描述實(shí)例變量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一個(gè)注釋
ElementType.PACKAGE 用于記錄java文件的package信息
@Inherited – 定義該注釋和子類的關(guān)系
那么,注解的內(nèi)部到底是如何定義的呢?Annotations只支持基本類型、String及枚舉類型。注釋中所有的屬性被定義成方法,并允許提供默認(rèn)值。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Todo {
public enum Priority {LOW, MEDIUM, HIGH}
public enum Status {STARTED, NOT_STARTED}
String author() default "Yash";
Priority priority() default Priority.LOW;
Status status() default Status.NOT_STARTED;
}
下面的例子演示了如何使用上面的注解。
@Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)
public void incompleteMethod1() {
//Some business logic is written
//But it’s not complete yet
}
如果注解中只有一個(gè)屬性,可以直接命名為“value”,使用時(shí)無需再標(biāo)明屬性名。
@interface Author{
String value();
}
@Author("Yashwant")
public void someMethod() {
}
但目前為止一切看起來都還不錯(cuò)。我們定義了自己的注解并將其應(yīng)用在業(yè)務(wù)邏輯的方法上。現(xiàn)在我們需要寫一個(gè)用戶程序調(diào)用我們的注解。這里我們需要使用反射機(jī)制。如果你熟悉反射代碼,就會(huì)知道反射可以提供類名、方法和實(shí)例變量對(duì)象。所有這些對(duì)象都有g(shù)etAnnotation()這個(gè)方法用來返回注解信息。我們需要把這個(gè)對(duì)象轉(zhuǎn)換為我們自定義的注釋(使用 instanceOf()檢查之后),同時(shí)也可以調(diào)用自定義注釋里面的方法。看看以下的實(shí)例代碼,使用了上面的注解:
Class businessLogicClass = BusinessLogic.class;
for(Method method : businessLogicClass.getMethods()) {
Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);
if(todoAnnotation != null) {
System.out.println(" Method Name : " + method.getName());
System.out.println(" Author : " + todoAnnotation.author());
System.out.println(" Priority : " + todoAnnotation.priority());
System.out.println(" Status : " + todoAnnotation.status());
}
標(biāo)題名稱:java代碼實(shí)現(xiàn)類注釋 Java代碼注釋
文章網(wǎng)址:http://chinadenli.net/article28/doopojp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、商城網(wǎng)站、云服務(wù)器、全網(wǎng)營銷推廣、自適應(yīng)網(wǎng)站、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)