JAVA筆記四:介面、lambda表示式與內部類
一、介面
1.1介面的概念
介面不是類,而是對類的一組需求描述 ,介面所有方法自動為public,當然在定義介面的時候加上也不違反語法規則。
java.lang.Comparable<T>1.0 int compareTo(T other) //小於other則返回負值,相等返回0,大於返回正值。 java.util.Arrays 1.2 static void sort(Object[] a)//陣列中的元素必須屬於實現了Comparable介面的類。 java.lang.Integer 1.0 static int compare(int x, int y)7 java.lang.Double 1.0 static int compare(double x, double y) 1.4
1.2 介面的特性
- 介面不是類,不能new一個介面例項物件,但是與抽象類相似,可以宣告介面的物件變數來繫結實現了該介面的類物件例項。
Comapreble x = new Employee(...);// 1
double SPEED_LIMIT = 95; // 2
default int compareTo(T other) {return 0;}
class Student implements Person, Named
{
public String getName(){return Person.super.getName();} //4.2
}
- 介面不可以包含例項域或靜態方法,但是可以包含常量。(將自動設為 public static final)
- java SE 8中允許在介面中增加靜態方法。
- 可以定義預設方法 default
預設方法衝突:超類定義方法與介面預設方法同名且引數型別相同;兩個介面的預設方法同名且引數型別相同
1)超類優先,超類定義的方法會忽略介面定義的預設方法
2)介面衝突,兩個介面中的同名方法一旦有一個定義為預設,則必須由程式設計師解決,例如在類中定義方法覆蓋。
注:不能讓介面的預設方法定義Object類中的某個方法,為什麼呢?
1.3 介面示例
- Comparator介面
按長度比較字串 class LengthComparator implements Comparator<String>{ public int compare(String first, String second){ return first.length() - second.length(); } } String [] friends = {"Perter", "Paul", "Mary"}; Arrays.sort(friends, new LengthComparator());//sort的第二個版本
二、Lambda表示式
2.1、語法
(1)Lambda無需指定返回型別
(String first, String second)
-> first.length() - second.length()
(2) 放置在花括號裡
(String first, String second) ->
{
if(first.length() < second.length()) return -1;
else if (first.length() > second.length()) return 1;
else return 0;
}
(3)即使沒有引數也需要有括號
() -> {for(int i = 100; i >= 0; i --) System.out.println(i);}
(4)如果可以推匯出引數型別,則可以省略
Comparator<String> comp
= (first, second) -> first.length() - second.length();
(5)如果只有一個引數,而且這個引數可以被推匯出,可以省略小括號
ActionListener listener = event ->
System.out.println("The time is " + new Date()");
2.2、函式式介面
對於只有一個抽象方法的介面,需要這種介面的物件時,可以提供一個lambda表示式,這種介面稱為函式式介面。lambda可以轉換為函式式介面。
2.2.1 方法引用
- object::instanceMethod
- Class::staticMethod
- Class::instanceMethod
(1)前兩種情況等價於提供引數的lambda表示式
System.out::println 等價於 x->System.out.println(x)
Math::pow 等價於 (x, y) -> Math.pow(x, y)
(2)對於第三種情況,第一個引數會成為方法的目標:
String::compareToIgnoreCase 等價於 (x, y) -> x.compareToIgnoreCase(y)
(3)在類中還可以使用this,super
this::greet, super::greet
2.2.2 構造器引用
Person::new,呼叫哪個構造器取決於上下文
Java有一個限制,無法構造泛型型別T的陣列。陣列構造器引用對於克服這個限制很有用。
Object[] people = stream.toArray();
Person[] people = stream.toArray(Person[]::new);
2.2.3 變數作用域
lambda表示式可以捕獲外部變數(但必須是最終變數:String,初始化後不會賦新值)
lambda不能有同名的區域性變數
2.2.4 Comparator
Arrays.sort(people, Comparator.comparing(Person::getName).thenComparing(Person::getFirstName));
2.3、 內部類
只有內部類可以是私有的,而常規類只可以具有包可見性或公有可見性。
內部類可訪問外部類的域,包括私有域。使用外圍類可以直接用變數名,也可以用
OuterClass.this //(TalkingClock.this.beep)
在外部類中,可以這樣呼叫構造器
this.new TimePrinter() // TimePrinter 是內部類,通常this是多餘的
但是如果TimePrinter是公有的,則任何外部主類的例項都可以構造一個TimePrinter
TalkingClock jabberer = new TalkingClock(1000, true);
TalkingClock.TimePrinter listener = jabberer.new TimePrinter();
內部類種宣告的所有靜態域都必須是final:
因為我們希望靜態域只有一個例項,不過對於每個外部物件,會分別有一個單獨的內部類例項。如果這個域不是final,它可能就不是唯一的。
內部類不能有static方法。
2.3.1 區域性內部類
在方法中可以定義區域性內部類
區域性內部類,類似於區域性變數,只存在於作用域內。
訪問外部方法的變數,實質上在內部類中宣告為final型別,注意如果是類,final的意思是繫結不可變,但值可變。
2.3.2 匿名內部類
假如只建立這個類的一個物件,就不必命名了,這種類被稱為匿名內部類。通常的語法格式
SuperType xxx = new SuperType(construction parameters)//SuperType可以是介面也可以是一個類
{
inner class methods and data
}//匿名內部類與普通構造一個SuperType的區別在於,後面跟了花括號
2.3.3 靜態內部類
有時候使用內部類知識為了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類物件,為此可以將內部類宣告為static,以便去取消產生的引用。在引入多個排序介面時可以使用。
三、代理
p258 比較難,看的有點迷糊
1、何時使用代理
假設有一個表示介面的Class物件,它的確切型別在編譯時無法知道。代理機制則是一種更好的解決方案。代理類可以在執行時建立全新的類。這樣的代理類能實現指定的介面。
java.langreflect.InvocationHandler 1.3
Object invoke(Object proxy, Method method, Object[] args)
目前為止,Java程式設計語言的繼承概念介紹完了。