萬州做網站多少錢東莞seo公司
10.1 注解概述
10.1.1 什么是注解
注解(Annotation)是從JDK5.0
開始引入,以“@注解名
”在代碼中存在。例如:
@Override
@Deprecated
@SuppressWarnings(value=”unchecked”)
Annotation 可以像修飾符一樣被使用,可用于修飾包、類、構造器、方法、成員變量、參數、局部變量的聲明。還可以添加一些參數值,這些信息被保存在 Annotation 的 “name=value” 對中。
注解可以在類編譯、運行時進行加載,體現不同的功能
10.1.2 注解與注釋
注解也可以看做是一種注釋,通過使用 Annotation,程序員可以在不改變原有邏輯的情況下,在源文件中嵌入一些補充信息。但是,注解,不同于單行注釋和多行注釋。
-
對于單行注釋和多行注釋是給程序員看的。
-
而注解是可以被編譯器或其他程序讀取的。程序還可以根據注解的不同,做出相應的處理。
10.1.3 注解的重要性
在JavaSE中,注解的使用目的比較簡單,例如標記過時的功能,忽略警告等。在JavaEE/Android中注解占據了更重要的角色
,例如用來配置應用程序的任何切面,代替JavaEE舊版中所遺留的繁冗代碼
和XML配置
等。
未來的開發(fā)模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,Struts2有一部分也是基于注解的了。注解是一種趨勢
,一定程度上可以說:框架 = 注解 + 反射 + 設計模式
。
10.2 常見的Annotation作用
示例1:生成文檔相關的注解
@author 標明開發(fā)該類模塊的作者,多個作者之間使用,分割
@version 標明該類模塊的版本
@see 參考轉向,也就是相關主題
@since 從哪個版本開始增加的
@param 對方法中某參數的說明,如果沒有參數就不能寫
@return 對方法返回值的說明,如果方法的返回值類型是void就不能寫
@exception 對方法可能拋出的異常進行說明 ,如果方法沒有用throws顯式拋出的異常就不能寫
package com.annotation.javadoc;
/**
?* @author 尚硅谷-宋紅康
?* @version 1.0
?* @see Math.java
?*/
public class JavadocTest {
?? ?/**
?? ? * 程序的主方法,程序的入口
?? ? * @param args String[] 命令行參數
?? ? */
?? ?public static void main(String[] args) {
?? ?}
?? ?
?? ?/**
?? ? * 求圓面積的方法
?? ? * @param radius double 半徑值
?? ? * @return double 圓的面積
?? ? */
?? ?public static double getArea(double radius){
?? ??? ?return Math.PI * radius * radius;
?? ?}
}
?
示例2:在編譯時進行格式檢查(JDK內置的三個基本注解)
@Override
: 限定重寫父類方法,該注解只能用于方法
@Deprecated
: 用于表示所修飾的元素(類,方法等)已過時。通常是因為所修飾的結構危險或存在更好的選擇
@SuppressWarnings
: 抑制編譯器警告
package com.annotation.javadoc;
?
public class AnnotationTest{
?
?? ?public static void main(String[] args) {
?? ??? ?@SuppressWarnings("unused")
?? ??? ?int a = 10;
?? ?}
?? ?@Deprecated
?? ?public void print(){
?? ??? ?System.out.println("過時的方法");
?? ?}
?
?? ?@Override
?? ?public String toString() {
?? ??? ?return "重寫的toString方法()";
?? ?}
}
?
示例3:跟蹤代碼依賴性,實現替代配置文件功能
-
Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中進行Servlet的部署。
?@WebServlet("/login")
public class LoginServlet extends HttpServlet {
? ? private static final long serialVersionUID = 1L;
? ??
? ? protected void doGet(HttpServletRequest request, HttpServletResponse response) { }
?? ?
? ? protected void doPost(HttpServletRequest request, HttpServletResponse response) {
? ? ? ? doGet(request, response);
?? ?} ?
}
?<servlet>
? ? <servlet-name>LoginServlet</servlet-name>
? ? <servlet-class>com.servlet.LoginServlet</servlet-class>
? </servlet>
? <servlet-mapping>
? ? <servlet-name>LoginServlet</servlet-name>
? ? <url-pattern>/login</url-pattern>
? </servlet-mapping>
?
Spring框架中關于“事務”的管理
@Transactional(propagation=Propagation.REQUIRES_NEW,isolation=Isolation.READ_COMMITTED,readOnly=false,timeout=3)
public void buyBook(String username, String isbn) {
?? ?//1.查詢書的單價
? ? int price = bookShopDao.findBookPriceByIsbn(isbn);
? ? //2. 更新庫存
? ? bookShopDao.updateBookStock(isbn);?? ?
? ? //3. 更新用戶的余額
? ? bookShopDao.updateUserAccount(username, price);
}
?
<!-- 配置事務屬性 -->
<tx:advice transaction-manager="dataSourceTransactionManager" id="txAdvice">
? ? ? ?<tx:attributes>
? ? ? ?<!-- 配置每個方法使用的事務屬性 -->
? ? ? ?<tx:method name="buyBook" propagation="REQUIRES_NEW"?
?? ? isolation="READ_COMMITTED" ?read-only="false" ?timeout="3" />
? ? ? ?</tx:attributes>
</tx:advice>
?
10.3 三個最基本的注解
10.3.1 @Override
-
用于檢測被標記的方法為有效的重寫方法,如果不是,則報編譯錯誤!
-
只能標記在方法上。
-
它會被編譯器程序讀取。
10.3.2 @Deprecated
-
用于表示被標記的數據已經過時,不推薦使用。
-
可以用于修飾 屬性、方法、構造、類、包、局部變量、參數。
-
它會被編譯器程序讀取。
10.3.3 @SuppressWarnings
-
抑制編譯警告。當我們不希望看到警告信息的時候,可以使用 SuppressWarnings 注解來抑制警告信息
-
可以用于修飾類、屬性、方法、構造、局部變量、參數
-
它會被編譯器程序讀取。
-
可以指定的警告類型有(了解)
-
all,抑制所有警告
-
unchecked,抑制與未檢查的作業(yè)相關的警告
-
unused,抑制與未用的程式碼及停用的程式碼相關的警告
-
deprecation,抑制與淘汰的相關警告
-
nls,抑制與非 nls 字串文字相關的警告
-
null,抑制與空值分析相關的警告
-
rawtypes,抑制與使用 raw 類型相關的警告
-
static-access,抑制與靜態(tài)存取不正確相關的警告
-
static-method,抑制與可能宣告為 static 的方法相關的警告
-
super,抑制與置換方法相關但不含 super 呼叫的警告
-
...
-
示例代碼:
package com.atguigu.annotation;
import java.util.ArrayList;
public class TestAnnotation {
? ? @SuppressWarnings("all")
? ? public static void main(String[] args) {
? ? ? ? int i;? ? ? ? ArrayList list = new ArrayList();
? ? ? ? list.add("hello");
? ? ? ? list.add(123);
? ? ? ? list.add("world");? ? ? ? Father f = new Son();
? ? ? ? f.show();
? ? ? ? f.methodOl();
? ? }
}class Father{
? ? @Deprecated
? ? void show() {
? ? ? ? System.out.println("Father.show");
? ? }
? ? void methodOl() {
? ? ? ? System.out.println("Father Method");
? ? }
}class Son extends Father{
/*?? ?@Override
?? ?void method01() {
?? ??? ?System.out.println("Son Method");
?? ?}*/
}
10.4 元注解
JDK1.5在java.lang.annotation包定義了4個標準的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。
(1)@Target:用于描述注解的使用范圍
-
可以通過枚舉類型ElementType的10個常量對象來指定
-
TYPE,METHOD,CONSTRUCTOR,PACKAGE.....
(2)@Retention:用于描述注解的生命周期
-
可以通過枚舉類型RetentionPolicy的3個常量對象來指定
-
SOURCE(源代碼)、CLASS(字節(jié)碼)、RUNTIME(運行時)
-
唯有RUNTIME階段才能被反射讀取到
。
(3)@Documented:表明這個注解應該被 javadoc工具記錄。
(4)@Inherited:允許子類繼承父類中的注解
示例代碼:
package java.lang;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
? ? String[] value();
}
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
拓展:元數據
String name = "Tom";
10.5 自定義注解的使用
一個完整的注解應該包含三個部分: (1)聲明 (2)使用 (3)讀取
10.5.1 聲明自定義注解
【元注解】
【修飾符】 @interface 注解名{
? ? 【成員列表】
}?
-
自定義注解可以通過四個元注解@Retention,@Target,@Inherited,@Documented,分別說明它的聲明周期,使用位置,是否被繼承,是否被生成到API文檔中。
-
Annotation 的成員在 Annotation 定義中以無參數有返回值的抽象方法的形式來聲明,我們又稱為配置參數。返回值類型只能是八種基本數據類型、String類型、Class類型、enum類型、Annotation類型、以上所有類型的數組
-
可以使用 default 關鍵字為抽象方法指定默認返回值
-
如果定義的注解含有抽象方法,那么使用時必須指定返回值,除非它有默認值。格式是“方法名 = 返回值”,如果只有一個抽象方法需要賦值,且方法名為value,可以省略“value=”,所以如果注解只有一個抽象方法成員,建議使用方法名value。
package com.atguigu.annotation;
import java.lang.annotation.*;
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
? ? String value();
}
package com.atguigu.annotation;
import java.lang.annotation.*;
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
? ? String columnName();
? ? String columnType();
}
10.5.2 使用自定義注解
package com.atguigu.annotation;
@Table("t_stu")
public class Student {
? ? @Column(columnName = "sid",columnType = "int")
? ? private int id;
? ? @Column(columnName = "sname",columnType = "varchar(20)")
? ? private String name;? ? public int getId() {
? ? ? ? return id;
? ? }? ? public void setId(int id) {
? ? ? ? this.id = id;
? ? }? ? public String getName() {
? ? ? ? return name;
? ? }? ? public void setName(String name) {
? ? ? ? this.name = name;
? ? }? ? @Override
? ? public String toString() {
? ? ? ? return "Student{" +
? ? ? ? ? ? ? ? "id=" + id +
? ? ? ? ? ? ? ? ", name='" + name + '\'' +
? ? ? ? ? ? ? ? '}';
? ? }
}
?
10.5.3 讀取和處理自定義注解
自定義注解必須配上注解的信息處理流程才有意義。
我們自己定義的注解,只能使用反射的代碼讀取。所以自定義注解的聲明周期必須是RetentionPolicy.RUNTIME。
具體的使用見《尚硅谷_宋紅康_第17章_反射機制.md》
。
10.6 JUnit單元測試
10.6.1 測試分類
黑盒測試:不需要寫代碼,給輸入值,看程序是否能夠輸出期望的值。
白盒測試:需要寫代碼的。關注程序具體的執(zhí)行流程。
10.6.2 JUnit單元測試介紹
JUnit 是由 Erich Gamma 和 Kent Beck 編寫的一個測試框架(regression testing framework),供Java開發(fā)人員編寫單元測試之用。
JUnit測試是程序員測試,即所謂白盒測試,因為程序員知道被測試的軟件如何(How)完成功能和完成什么樣(What)的功能。
要使用JUnit,必須在項目的編譯路徑中引入JUnit的庫
,即相關的.class文件組成的jar包。jar就是一個壓縮包,壓縮包都是開發(fā)好的第三方(Oracle公司第一方,我們自己第二方,其他都是第三方)工具類,都是以class文件形式存在的。
10.6.3 引入本地JUnit.jar
第1步:在項目中File-Project Structure中操作:添加Libraries庫
其中,junit-libs包內容如下:
第2步:選擇要在哪些module中應用JUnit庫
第3步:檢查是否應用成功
注意Scope:選擇Compile,否則編譯時,無法使用JUnit。
第4步:下次如果有新的模塊要使用該libs庫,這樣操作即可
10.6.4 編寫和運行@Test單元測試方法
JUnit4版本,要求@Test標記的方法必須滿足如下要求:
-
所在的類必須是public的,非抽象的,包含唯一的無參構造器。
-
@Test標記的方法本身必須是public,非抽象的,非靜態(tài)的,void無返回值,()無參數的。
package com.atguigu.junit;
import org.junit.Test;
public class TestJUnit {
? ? @Test
? ? public void test01(){
? ? ? ? System.out.println("TestJUnit.test01");
? ? }? ? @Test
? ? public void test02(){
? ? ? ? System.out.println("TestJUnit.test02");
? ? }? ? @Test
? ? public void test03(){
? ? ? ? System.out.println("TestJUnit.test03");
? ? }
}
0.6.5 設置執(zhí)行JUnit用例時支持控制臺輸入
1. 設置數據:
默認情況下,在單元測試方法中使用Scanner時,并不能實現控制臺數據的輸入。需要做如下設置:
在idea64.exe.vmoptions配置文件
中加入下面一行設置,重啟idea后生效。
-Deditable.java.test.console=true
?2. 配置文件位置:
添加完成之后,重啟IDEA即可。
3. 如果上述位置設置不成功,需要繼續(xù)修改如下位置
修改位置1:IDEA安裝目錄的bin目錄(例如:D:\develop_tools\IDEA\IntelliJ IDEA 2022.1.2\bin
)下的idea64.exe.vmoptions文件。
修改位置2:C盤的用戶目錄C:\Users\用戶名\AppData\Roaming\JetBrains\IntelliJIdea2022.1
下的idea64.exe.vmoptions`件。
10.6.6 定義test測試方法模板
選中自定義的模板組,點擊”+”(1.Live Template)來定義模板。