第41天學習打卡(註解 內建註解 元註解 自定義註解 反射機制 )
註解Java.Annitation
什麼是註解
Annotation是從JDK5.0開始引入的新技術
Annotation的作用:
不是程式本身,可以對程式作出解釋。(這一點和註釋(comment)沒什麼區別)
可以被其他程式(比如:編譯器等)讀取。
Annotation的格式:
註解是以“@註釋名”在程式碼中存在的,還可以新增一些引數值,例如“@SuppressWarnings(value=“unchecked”).
Annotation在哪裡使用?
可以附加在package,class,method,field等上面,相當於給他們添加了額外的輔助資訊,我們可以通過反射機制程式設計實現對這些元資料的訪問。
內建註解
@Override:定義在java.lang.Override中,此註釋只適用於修辭方法,表示一個方法宣告打算重寫超類中的另一個方法宣告。
@Deprecated:定義在java.lang.Deprecated中,此註釋可以用於修辭方法,屬性,類,表示不鼓勵程式設計師使用這樣的元素,通常是因為它很危險或者存在更好的選擇。
@SuppressWarnings:定義在java.lang.SuppressWarnings中,用來抑制編譯時的警告資訊。
與前兩個註釋有所不同,你需要新增一個引數才能正確使用,這些引數都是已經定義好了的,我們選擇性的使用就好了。
@SuppressWarnings ("all")
@SuppressWarnings("unchecked")
@SuppressWarnings(value={"unchecked","deprecation"})
等等...
package com.kuang.annotation;
import javax.naming.MalformedLinkException;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("all" )
public class Test01 extends Object{
//@Override 重寫的註解
@Override
public String toString() {
return super.toString();
}
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
public void test02(){
List list = new ArrayList();
}
public static void main(String[] args) {
test();
}
}
元註解
元註解的作用就是負責註解其他註解,Java定義了4個標準的meta-annotation型別,他們被用來提供對其他annotation型別作說明。
這些型別和它們所支援的類在java.lang.annotation包中可以找到。(@Target,@Retention,@Documented,@Inherited)
Target:用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)
@Retention:表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期。
(SOURCE<CLASS<RUNTIME)
@Document:說明該註解將被包含在javadoc中
@Inherited:說明子類可以繼承父類中的該註解
package com.kuang.annotation;
import java.lang.annotation.*;
import java.util.EnumMap;
//測試元註解
//一個類裡面只能有一個public
@MyAnnotation
public class Test02 {
public void test(){
}
}
//定義一個註解
//Target 表示我們的註解可以用在哪些地方
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//Retention 表示我們的註解在什麼地方還有效
//runtime>class>sources
@Retention(value = RetentionPolicy.RUNTIME)
//Documented 表示是否將我們的註解生成在JAVAdoc中
@Documented
//Inherited 子類可以繼承父類的註解
@Inherited
@interface MyAnnotation{
}
自定義註解
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation介面
分析:
@interface用來宣告一個註解,格式:[email protected]註解名{定義內容}—>在類裡面宣告的話要把public去掉
其中的每個方法實際上是聲明瞭一個配置引數。
方法的名稱就是引數的名稱。
返回值型別就是引數的型別(返回值只能是基本型別,Class,String,enum)
可以通過default來宣告引數的預設值
如果只有一個引數成員,一般引數名為value
註解元素必須要有值,我們定義註解元素時,經常使用空字串,0作為預設值
package com.kuang.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定義註解
public class Test03 {
//去掉哪一個註解的預設值,就只用給那一個註解的預設值賦值就可以了,註解沒有順序
//註解可以顯示賦值,如果沒有預設值,我們就必須給註解賦值
@MyAnnotation2()
public void test(){
}
@MyAnnotation3("秦")
public void test2(){
}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//註解的引數:引數型別 + 引數名();
//加了default之後,@MyAnnotation()就可以不在裡面加引數 也可以賦值
String name() default"";
int age() default 0;
int id() default -1;//如果預設值為-1,代表不存在,與indexof:如果找不到就返回-1 有異曲同工之妙
String[] schools() default {"西部開源","清北"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
//如果只有一個value,那麼上面的@MyAnnotation可以省略一個value直接寫值
String value();
}
反射機制(Java.Reflection)
靜態VS動態語言
動態語言
是一類在執行時可以改變其結構的語言:例如新的函式、物件、甚至程式碼可以被引進,已有的函式可以被刪除或是其他結構上的變化。通俗點說就是在執行時程式碼可以根據某些條件改變自身結構。
主要動態語言:Object-C、C#、JavaScript、PHP、Python等
靜態語言
與動態語言相對應的,執行時結構不可變的語言就是靜態語言。如Java,C,C++,
Java不是動態語言,但Java可以稱之為”準動態語言“。即Java有一定的動態性,我們可以利用反射機制獲得類似動態語言的特性。Java的動態性讓程式設計的時候更加靈活。
Java Reflection
Reflection(反射)是Java被視為動態語言的關鍵,反射機制允許程式在執行期藉助於Reflection API取得任何類的內部訊息,並能直接操作任意物件的內部屬性及方法。
Class c = Class.forName("java.lang.String")
載入完類之後,在堆記憶體的方法區中就產生了一個Class型別的物件(一個類只用一個Class物件),這個物件就包含了完整的類的結構資訊。我們可以通過這個物件看到類的結構。這個物件就像一面鏡子,透過這個鏡子看到類的結構,所以,我們形象的稱之為:反射
Java反射機制研究及應用
Java反射機制提供的功能
在執行時判斷任意一個物件所屬的類
在執行時構造任意一個類的物件
在執行時判斷任意一個類所具有的成員變數和方法
在執行時獲取泛型資訊
在執行時呼叫任意一個物件的成員變數和方法
在執行時處理註解
生成動態代理
…
Java反射優點和缺點
優點:
可以實現動態建立物件和編譯,體現出很大的靈活性
缺點:
對效能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什麼並且它滿足我們的要求。這類操作總是慢於直接執行相同的操作。
反射相關的主要API
java.lang.Class:代表一個類
java.lang.reflect.Method:代表類的方法
java.lang.reflect.Field:代表類的成員變數
java.lang.reflect.Constructor:代表類的構造器
Class類
在Object類中定義了以下的方法,此方法將被所有子類繼承
public final Class getClass()
以上的方法返回值的型別是一個Class類,此類是Java反射的源頭,實際上所謂反射從程式的執行結果來看也很好理解,即:可以通過物件反射求出類的名稱。
package com.kuang.reflection;
//什麼叫反射
public class Test02 extends Object{
public static void main(String[] args) throws ClassNotFoundException {
//通過反射獲取類的class物件
Class c1 = Class.forName("com.kuang.reflection.User");
System.out.println(c1);
Class c2 = Class.forName("com.kuang.reflection.User");
Class c3 = Class.forName("com.kuang.reflection.User");
Class c4 = Class.forName("com.kuang.reflection.User");
//一個類在記憶體中只有一個Class物件,所以其雜湊值是一樣的
//一個類被載入後,類的整個結構都會被封裝在Clsaa物件中
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
}
}
//實體類:類裡面只有屬性叫實體類 pojo, entity
class User{
private String name;
private int id;
private int age;
public User() {
}
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
}