1. 程式人生 > 其它 >17Java進階——反射、程序、Java11新特性

17Java進階——反射、程序、Java11新特性

1.Java反射機制

Java反射(Reflection)概念:在執行時動態獲取類的資訊以及動態呼叫物件方法的功能。

1.1反射的應用——通過全類名獲取類物件及其方法

package two.reflection;
import java.util.Scanner;
import  java.lang.reflect.Method;
public class Test1 {
}
​
class TestRef {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print(
"請輸入一個Java類全名:"); String cName = input.next(); showMethods(cName); } ​ public static void showMethods(String name) { try { //使用Class.forName()獲得Class物件 //Class類存在於java.lang.Class Class c = Class.forName(name); //獲得該類宣告的方法,返回一個Method集合
//Method類位於java.lang.reflect包下 Method m[] = c.getDeclaredMethods(); System.out.print("該Java類的方法有:"); for (int i = 0; i < m.length; i++) { //將方法名、修飾符、引數列表輸出 System.out.println(m[i].toString()); } } catch (Exception e) { e.printStackTrace(); } } }
請輸入一個Java類全名:two.reflection.TestRef
該Java類的方法有:public static void two.reflection.TestRef.main(java.lang.String[])
public static void two.reflection.TestRef.showMethods(java.lang.String)

eclipse等開發環境中,使用物件會顯示其方法和屬性,就利用了java的反射機制。

1.2 java.lang包中的 Class 類和 java.lang.reflect 包中的 Method 類、Field 類、Constructor 類、Array

常用方法:類名:

Class.forName(全類名):獲得類物件

類名.class:獲取Class物件

包裝類.TYPE:獲得Class物件

物件.getClass():獲取Class物件

class.getSuperClass():通過class物件獲取父類物件

class.getName():獲取類的全類名

欄位:

class.getFields():獲取所有public屬性(含繼承來的屬性)

class.getDeclaredFields():獲取所有訪問許可權的屬性(不含繼承來的屬性)

方法:

class.getMethods():獲取所有public修飾的方法,除建構函式(含繼承來的方法)

class.getDeclaredMethods():獲取所有訪問許可權的方法,除建構函式(不含繼承來的方法)

class.getMethods(String name,Class[] args):獲取特定的方法

class.getDeclaredMethods(String name,Class[] args):獲取特定的方法

構造方法:(返回型別是Constructor)

class.getConstructors():獲取公共的建構函式

class.getConstructors(Class[] args):獲取指定引數列表的建構函式

介面:

class.getInterfaces():獲取該類或者介面實現的介面陣列

class.newInstance():使用無參構造方法建立該類的一個新例項

方法名、引數列表、返回值:

m.getName():獲取方法名

m.getDeclaringClass():獲取呼叫方法的類/介面

m.getParameterTypes():獲取形參列表的Class陣列

m.getReturnType():獲取返回值型別

m.getModifiers():獲取修飾符

1.3 利用反射構造物件

獲得一個類的Class物件,使用class.newInstance()的方法得到Object物件,再強制轉型獲得例項物件。

就可以呼叫物件的公開方法,獲得物件的公開屬性。

如果類中沒有預設的無參構造方法,會報InstantiationException異常。

1.4利用反射獲得的構造方法例項化

無參構造:getDeclaredConstructor()獲得無參構造Constructor物件,呼叫newInstance()方法。得到Object物件後強制型別轉換。

帶參構造:getDeclaredConstructor((Class[] args))獲得帶參構造Constructor物件,呼叫newInstance(Object[] o)方法,輸入傳入的引數。得到Object物件後強制型別轉換。

1.5使用反射修改屬性訪問許可權

Field f = c.getDeclaredField(name);

f.setAccessible(true); //取消屬性的訪問許可權控制,即使private屬性也可以進行訪問

f.get(sup));獲取欄位值

f.set(sup,20));設定欄位值

1.6使用反射呼叫特定方法

Method m = c.getDeclaredMethod(name,params);

m.invoke(Object o,Object[] args):呼叫物件o對應方法,物件o是呼叫方法的物件

1.7使用反射包下Array類構造動態陣列

Array.newInstance(Class componentType, int length):返回一個Object型別的陣列

Array.getXxx(Object array, int index):返回下標元素,為xxx型別

Array.setXxx(Object array, int index,xxx val):將下標為index的元素修改為xxx型別的值

int dim[] = {8, 10};

Object arr = Array.newInstance(Integer.TYPE, dim);:建立一個8*10的二維陣列

沒有賦值的情況下,和陣列沒有賦值的情況是相同的。

2 執行緒補充知識

2.1執行緒的三大優勢

系統開銷小

方便通訊和資源共享

簡化程式結構

2.2執行緒的其他常用方法

void interrupt():中斷執行緒的阻塞狀態(而非中斷執行緒)

boolean isAlive():判定該執行緒是否處於活動狀態,處於就緒、執行和阻塞狀態的都屬於活動狀態。

boolean isDaemon():判斷一個執行緒是否是守護執行緒

3 註解

註解是 Java 程式碼中的特殊標記,這些標記可以在編譯、類載入、執行時被讀取,並執行相應的處理。

註解以@開頭,註解有不帶引數的,一個引數的和多個引數的。

內建註解:@Override @Deprecated @SuppressWarnings

@Override:重寫方法

@Deprecated:已過時

@SuppressWarnings:抑制警告。可以將value設定為以下值

deprecation:使用了過時的程式元素。 unchecked:執行了未檢查的轉換。 unused:有程式元素未被使用。 fallthrough:switch 程式塊直接通往下一種情況而沒有 break。 path:在類路徑中有不存在的路徑。 serial:在可序列化的類上缺少 serialVersionUID 定義。 finally:任何 finally 子句都不能正常完成。 all:所有情況。

元註解:@Target @Retention @Documented @Inherited

@Target:指定被修飾的註解能修飾哪些元素。value可以設定為以下值

ElementType.ANNOTATION_TYPE:註解型別宣告 ElementType.CONSTRUCTOR:構造方法宣告 ElementType.FIELD:欄位宣告(包括列舉常量) ElementType.LOCAL_VARIABLE:區域性變數宣告 ElementType.METHOD:方法宣告 ElementType.PACKAGE:包宣告 ElementType.PARAMETER:引數宣告 ElementType.TYPE:類、介面(包括註解型別)或列舉宣告

@Retention:指定被修飾的註解可以保留多長時間

RetentionPolicy.CLASS:編譯器將把註解記錄在 class 檔案中,當執行 Java 程式時,虛擬機器不再保留註解 RetentionPolicy.RUNTIME:編譯器將把註解記錄在 class 檔案中,當執行 Java 程式時,虛擬機器保留註解,程式可以通過反射獲取該註解 RetentionPolicy.SOURCE:編譯器將直接丟棄被修飾的註解

@Documented:如果新增該註解,那麼所有被該註解修飾的註解出現在使用的類的javadoc中。

@Inherited:修飾的註解是可以被繼承的

3.1 自定義註解並完成賦值

4 Java11新特性

4.1Lambda表示式

lambda表示式用法:簡化函式式介面的實現。

lambda表示式格式:()->語句

()是形參列表,沒有引數為(),一個引數為(s),兩個引數為(s1,s2)。可以省略形參的型別,也可以全部寫上。形參列表的變數需要提前定義好。

語句可以是一條,不需要寫大括號,可以有返回值也可以沒有。如果寫上return ,必須要有大括號。如果是多條,需要寫大括號。

lambda表示式可以作為引數傳入。

A b = (z,x)->z+x; A ccc = (int z,int x)->z+x;//都是正確實現

interface A{ int add(int a,int b); }

函式式介面:介面中只有一個抽象方法。可以用@FunctionalInterface修飾,也可以不修飾

四大函式式介面:

Consumer<T>{void consume(T t);}

Predicate<T>{boolean test(T t);}

Function<T,R>{R apply(T t);}

Supplier<T> {T get();}

Comparable的lambda表示式:Arrays.sort(a,((o1, o2) -> o2-o1));

4.2 方法引用

引用某個物件的例項方法:物件名 :: 非靜態方法

引用類中的例項方法:類名 :: 非靜態方法

引用構造方法:類名:: new

引用陣列:元素型別[] :: new

4.2.介面的預設方法

jdk11後允許方法中有預設方法。修飾符是public default,default不能省略。

實現類可以重寫介面中的抽象方法,但是同時實現多個介面且預設方法重名,重寫方法會引起編譯錯誤。

解決方法:實現類重寫重名方法,內部使用介面名.super.方法名(),讓重名方法轉化為一個介面的實現。

4.3重複註解

4.4Stream流

4.5其它特性