JAVA -註解

JAVA SE-註解

一個專心致志思索的人並不是在虛度光陰。雖然有些勞動是有形的,但也有一種勞動是無形的。 —— 雨果

什麼是註解?註解有什麼用?

  • 註解就是 @xxx 這樣的東西就是註解.
    • 註釋:給程序員看的.
    • 註解:給程序看。
    • 使用註解的目的: 其實將來使用註解目的就是爲了代替傳統配置文件.

@Override

public class Demo1 implements Person {

    @Override
    //向編譯器描述,該方法是被重寫的.
    //幫你檢查,被註解修飾方法是否是被重寫的,如果不是編譯報錯!
    //@Override 1.5版本只接受繼承性質的重寫.  1.6版本也接受實現接口性質的重寫
    public void eat() {

    }
    //@Override
    public void eat2() {

    }

}

@Deprecated

public class Demo2 {
    @Deprecated
    //該註解告訴編譯器,被修飾的方法是過時方法
    public static void show(){
        System.out.println("hello world!");
    }

    public static void main(String[] args) {
        Demo2.show();
    }
}

@SuppressWarnings

public class Demo3 {

    //@SuppressWarnings({"null","rawtypes", "unchecked"})
    @SuppressWarnings("all")
    //告訴編譯器,不要檢查什麼錯誤!
    //如果填寫all,那麼什麼錯誤都不檢查.
    public static void main(String[] args) {
        String str = null;
        str.substring(0);

        //@SuppressWarnings("unused")
        String str2 = null;

        List list = new ArrayList();
        list.add("abc");
    }
}

如何自定義一個註解?

public @interface MyAnnotation {

    //聲明屬性=> 抽象方法


    //聲明一個名爲name的屬性  類型是String
    String value();


    //如果註解中,必填屬性只有一個. 這個屬性的名字是"value".那麼在賦值時不需要加屬性的鍵.
}
    分析一下註解的本質:
        將其.class文件找到,反編譯.

        @interface MyAnnoation{}

        反編譯後的結果
        interface MyAnnotation  extends Annotation
        {
        }

       結論:註解本質上就是一個接口。它擴展了java.lang.annotation.Annotation接口;

       在java中所有註解都是Annotation接口的子接口。

      註解也是jdk1.5的一個新特性.

註解的屬性

註解的成員

        註解本質上就是一個接口,那麼它也可以有屬性和方法。
        但是接口中的屬性是  static final的,在註解中註解沒有什麼意義。

        在開發中註解中經常存在的是方法。而在註解中叫做註解的屬性.

    註解的屬性的類型:
        1.基本類型
        2.String
        3.枚舉類型
        4.註解類型
        5.Class類型
        6.以上類型的一維數組類型
public @interface MyAnnotation2 {
    //註解的屬性都支持那些類型?
    // 八大基本數據類型
    // String 
    // Array
    // Enum枚舉

    //可以使用default關鍵字,添加屬性的默認值
    byte a() default 10;
    short b();
    int c();
    long d();
    float e();
    double f();
    char g();
    boolean h();

    String i();

    String[] j();

    ElementType k();

}
    關於註解的屬性聲明後的使用:

        1.如果一個註解有屬性,那麼在使用註解時,要對屬性進行賦值操作.
            例如:@MyAnnotation3(st = "aaa")

        2.如果一個註解的屬性有多個,都需要賦值,使用","分開屬性.
            @MyAnnotation3(st = "aaa",i=10)

        3.也可以給屬性賦默認值
            double d() default 1.23;
            如果屬性有默認值,在使用註解時,就可以不用爲屬性賦值。

        4.如果屬性是數組類型

            1.可以直接使用   屬性名={值1,值2,。。。}方式,例如

                @MyAnnotation3(st = "aaa",i=10,sts={"a","b"})
            2.如果數組的值只有一個也可以寫成下面方式
                @MyAnnotation3(st = "aaa",i=10,sts="a")
                注意sts屬性它是數組類型,也就是說,只有一個值時,可以省略"{}"

        5.對於屬性名稱 value的操作.
            1.如果屬性名稱叫value,那麼在使用時,可以省略屬性名稱
                @MyAnnotation3("hello")

            2.如果有多個屬性,都需要賦值,其中一個叫value,這時,必須寫屬性名稱
                @MyAnnotation3(value="hello",i=10)

            3.如果屬性名稱叫value,它的類型是數組類型.
                    1.只有這個value屬性
                        可以直接賦值,不能寫屬性名稱,但是,如果只有一個值
                            @MyAnnotation3({"abc"})或  @MyAnnotation3("abc")
                        但是如果有多個值
                            @MyAnnotation3({"abc","def"})                           

                    2.如果有多個屬性,屬性名稱叫value
                        所有屬性都需要賦值,那麼必須寫屬性名稱.

關於元註解

元註解是指註解的註解。包括 @Retention @Target @Document @Inherited四種。

//元註解 (4個)
//修飾註解的註解
// @Retention 註解是給誰看的=> 永遠選擇RUNTIME
    //RetentionPolicy.SOURCE  註解會保留到編譯期 (給編譯器看)
    //RetentionPolicy.CLASS 註解會保留到加載期(給類加載器)
    //RetentionPolicy.RUNTIME 註解會保留到運行期(給虛擬機看)
//
@Retention(RetentionPolicy.RUNTIME)
//@Target 註解支持加在什麼位置
    @Target(ElementType.TYPE)   //接口、類、枚舉、註解
    @Target(ElementType.FIELD) //字段、枚舉的常量
    @Target(ElementType.METHOD) //方法
    @Target(ElementType.PARAMETER) //方法參數
    @Target(ElementType.CONSTRUCTOR)  //構造函數
    @Target(ElementType.LOCAL_VARIABLE)//局部變量
    @Target(ElementType.ANNOTATION_TYPE)//註解
    @Target(ElementType.PACKAGE) ///包   
@Target({ElementType.CONSTRUCTOR,ElementType.METHOD,ElementType.TYPE})
//@Inherited描述 註解可否被繼承
@Inherited
//@Documented 描述註解是否用於生成java文檔
@Documented
public @interface MyAnnotation3 {

}

註解與銀行取款的實例

首先自定義一個註解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BankInfo {
    double value();

}

實現的銀行業務類

public class BankService {

    @BankInfo(20000)
    public static void zz(String name1,String name2,double money) throws Exception{
        // 在使用註解的方法中獲得註解上填寫的屬性值.
            //1 獲得註解所在的反射對象 
    Method m =  BankService.class.getMethod("zz",String.class,String.class,double.class);
            //2 判斷方法是否被@BankInfo 所修飾
            if(m.isAnnotationPresent(BankInfo.class)){
                //被修飾
                //3 獲得註解的屬性值
                BankInfo info = m.getAnnotation(BankInfo.class);
                double maxmoney = info.value();
                if(money>maxmoney){
                    throw new RuntimeException("單次轉賬不能超過"+maxmoney+"元!");
                }

                System.out.println(name1+"給"+name2+"轉了"+money+"元!");
            }else{
                //沒被註解修飾
                throw new RuntimeException("系統異常,不能轉賬!");
            }


    }

    public static void main(String[] args) throws Exception {
        zz("tom", "jerry", 10000);
    }

}

下一個事例:JDBCUtils

在以往的實例當中,我們選擇以配置文件的方式來控制參數,現在我們可以用註解來完成相關參數的配置工作。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)//加到類上
public @interface JDBCInfo {

    //驅動名稱
    String driver();
    //url地址
    String url();
    //用戶名
    String name();
    //密碼
    String password();

}

重寫JDBC的工具類

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

@JDBCInfo(driver = "com.mysql.jdbc.Driver", name = "root", password = "1234", url = "jdbc:mysql://localhost:3306/day05")
public class JDBCUtils {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;



    static{

        try {
            //獲得註解中配置的屬性
            //1 獲得註解所在的反射對象
            Class clazz = JDBCUtils.class;
            //2 獲得註解的實現類
            JDBCInfo info = (JDBCInfo) clazz.getAnnotation(JDBCInfo.class);
            //3 獲得4個屬性值
            driver = info.driver();
            url=info.url();
            user=info.name();
            password=info.password();


            //1 註冊驅動
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //1 獲得連接
    public static Connection getConnection(){
        Connection conn = null;
        try {
            //2 獲得連接
            conn = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("創建連接失敗!");
        }

        return conn;
    }

    //2 釋放資源
        //1> 參數可能爲空
        //2> 調用close方法要拋出異常,確保即使出現異常也能繼續關閉
        //3>關閉順序,需要從小到大
    public  static void  close(Connection conn , Statement st , ResultSet rs){

        try {
            if(rs!=null){
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(st!=null){
                st.close(); 
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }finally{
                try {
                    if(conn!=null){
                        conn.close();   
                        }
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }


    public static void main(String[] args) {
        System.out.println(getConnection());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章