Java.Annotationjava
Java.Comment程序員
Java.Reflection編程
◆ Annotation是從JDK5.0開始引入的新技術c#
◆ Annotation的做用:數組
不是程序自己,能夠對程序做出解釋(這一點和註釋(comment沒什麼區別)安全
能夠被其餘程序(好比編譯器等)讀取 (這一點的咱們能夠利用,動態的寫程序)ide
◆ 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"}) 等等
測試代碼:
public class Test01 extends Object { /** * 重寫的註解 * @return */ @Override public String toString() { return "Test01{}"; } /** * 聲明過時操做 * 註解來聲明過時的不建議使用的方法 */ @Deprecated public static void test() { System.out.println("Deprecated"); } /** * 壓制警告,若是使用了不安全的操做,程序在編譯時必定會出現安全警告 * 這時可使用@SuppressWarnings壓制全部出現的警告信息 */ @SuppressWarnings("all") public void test02() { List list = new ArrayList<>(); } }
◆元註解的做用就是負責註解其餘註解,java定義了4個標準的meta- -annotation類型他們被用來提供對其餘 annotation類型做說明.
◆這些類型和它們所支持的類在java.lang. annotation包中能夠找到(@Target,@Retention,
@Documented, @Inherited
@Target:用於描述註解的使用範圍(即被描述的註解能夠用在什麼地方)
@Retention:表示須要在什麼級別保存該註釋信息,用於描述註解的生命週期
(SOURCE< CLASS< RUNTIME)
@Document:說明該註解將被包含在 javadoc中
@Inherited:說明子類能夠繼承父類中的該註解
1.@Target
@Target(ElementType.METHOD)
ElementType 裏面出現的類型
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE }
2.Retention
參數RetentionPolicy,一個枚舉類型,
runtime >> class >> source,就是咱們在定義的時候,定義在運行狀態的話,最高狀態,也能夠在其餘兩個狀態起效果
//2.表示咱們的註解在什麼地方還有效 //runtime > class > source
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, CLASS, RUNTIME }
3.@Documented
表示是否將咱們的註解生成在JAVAdoc中
4.@Inherited
子類能夠繼承父類的註解
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口
分析:
註解參數的配置,只有一個參數的時候
/** * @author jiayadong */ @interface MyAnnotation3{ String value(); }
使用的時候,咱們能夠不使用參數名字,直接輸入字符串
@MyAnnotation3("hello") public void fun() { }
多個參數的時候,咱們使用註解的時候,輸入參數的時候,能夠不按參數順序輸入.
@interface MyAnnotation{ // 註解的參數:參數類型+參數名(); String name() default ""; int age() default 0; int id() default -1; //若是默認值爲-1,表明不存在 String[] school() default {"中山大學","北京大學"}; }
@MyAnnotation(age = 12) public void test() {}
靜態語言VS動態語言
動態語言
是一類在運行時能夠改變其結構的語言例如新的函數、對象、甚至代碼能夠被引進,已有的函數能夠被刪除或是其餘結構上的變化。通俗點說就是在運行時代 碼能夠根據某些條件改變自身結構
主要動態語言: Object--c、c#、 JavaScript、PHP、 Python等
靜態語言
Java不是動態語言,但Java能夠稱之爲「動態語言」。即java有必定的動態性, 咱們能夠利用反射機制得到相似動態語言的特性。java的動態性讓編程的時候更加靈活!
Reflection(反射)是Java被視爲動態語言的關鍵,反射機制容許程序在執行期藉助於 Reflection API取得任何類的內部信息,並能直接操做任意對象的內部屬性及方法
Class c=Class forName("java.lang.String");
加載完類以後,在堆內存的方法區中就產生了一個 Class類型的對象(一個類只有一個Class對象),這個對象就包含了完整的類的結構信息,咱們能夠經過這個對象看到類的結構,這個對象就像一面鏡子,透過這個鏡子看到類的結構,因此 咱們形象的稱之爲:反射
- 在運行時判斷任意一個對象所屬的類
- 在運行時構造任意一個類的對象
- 在運行時判斷任意一個類所具備的成員變量和方法>在運行時獲取泛型信息
- 在運行時調用任意一個對象的成員變量和方法
- 在運行時處理註解
- 生成動態代理
優勢
能夠實現動態建立對象和編譯,體現出很大的靈活性
缺點
對性能有影響。使用反射基本上是一種解釋操做,咱們能夠告訴JVM,咱們但願
作什麼而且它知足咱們的要求。這類操做老是慢於直接執行相同的操做
2.2.3 反射相關的主要的API
java.lang.Class:表明一個類 java.lang.reflect.Method:表明類的方法 java.lang.reflect.Field:表明類的成員變量 java.lang.reflect.Constructor:表明類的構造器
在 Object類中定義瞭如下的方法,此方法將被全部子類繼承
public final Class getClass()
以上的方法返回值的類型是一個Class類,此類是Java反射的源頭,實際上所謂反射從程序的運行結果來看也很好理解,即:能夠經過對象反射求出類的名稱。
對象照鏡子後能夠獲得的信息:某個類的屬性方法和構造器、某個類到底實現了哪些接口 對於每一個類而言,JRE都爲其保留一個不變的 Class類型的對象。一個 Class對象包含了特 定某個結(class/interface/enum/annotation/primitive type/void []的有關信息
方法名 | 功能說明 |
---|---|
static ClassforName(String nam) | 返回指定類名name的Class對象 |
Object newInstance() | 調用缺省構造函數,返回Class對象的一個實例 |
getName() | 返回Class對象所表的實體(類.接口,數組類或void)的名稱 |
Class getSuperClass() | 返回當前Class對象的父類的Class對象 |
Class[] getInterface() | 返回當前Class對象的接口 |
ClassLoader getClassLoader() | getClassLoader() 返回類的類加載器。 |
Constructor<?>[] | getConstructors() 返回包含一個數組 Constructor對象反射由此表示的類的全部公共構造 類對象。 |
方法[] | getMethods() 返回包含一個數組 方法對象反射由此表示的類或接口的全部公共方法 類對象,包括那些由類或接口和那些從超類和超接口繼承的聲明。 |
Field[] | getFields() 返回包含一個數組 Field對象反射由此表示的類或接口的全部可訪問的公共字段 類對象。 |
a)若已知具體的類,經過類的class屬性獲取,該方法最爲安全可靠,程序性能最高。
b)已知某個類的實例,調用該實例的 getClass()方法獲取lass對象
c)已知一個類的全類名,且該類在類路徑下,可經過 Classfor類的靜態方法 Name(獲取可能拋出 ClassNotFound Exception)
d)內置基本數據類型能夠直接用類名.Type
e)還能夠利用ClassLoader咱們以後講解
測試類:測試獲取Class類的幾種方式
package com.rango.reflection; /** * @program: 註解和反射01 * @description: 測試Class類的建立方式有哪些 * @author: JiaYadong * @create: 2020-10-08 21:53 **/ public class Test02 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println("這我的是: "+person.name); // 方式一:經過對象得到 Class c1 = person.getClass(); System.out.println("getClass得到的:"+c1.hashCode()); // 方式二:forName得到 Class c2 = Class.forName("com.rango.reflection.Student"); System.out.println("Class.forName"+c2.hashCode()); // 方式三:類.class 得到 Class c3 = Student.class; System.out.println("類.class"+c3.hashCode()); // 方式四: 基本內置類型的包裝類都有一個Type屬性 Class c4 = Integer.TYPE; System.out.println(c4.getName()); // 得到父類類型 Class c5 = c1.getSuperclass(); System.out.println(c5); } } class Person { String name; public Person() { } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person { public Student() { this.name="學生"; } } class Teacher extends Person{ public Teacher() { this.name="老師"; } }
能夠實現動態建立對象和編譯,體現出很大的靈活性
缺點 >對性能有影響。使用反射基本上是一種解釋操做,咱們能夠告訴JVM,咱們但願 作什麼而且它知足咱們的要求。這類操做老是慢於直接執行相同的操做