java 類 介面
面向物件設計:將一個應用分解成多個物件,將問題分解成多個易處理和維護的小問題
java語言的5個特點
- 萬物皆為物件
- 程式是物件的集合 它們通過傳送訊息來告知彼此所要做的
- 每個物件都有自己的由其他物件所構成的儲存 可以通過將其建立包含現有物件的包的方式來建立新型別的物件 複雜性隱藏在物件的簡單性背後
- 每個物件都擁有其型別 "每個物件都是某個類的一個例項"
- 某一特定型別的所有物件都可以接受同樣的訊息 "圓形"同時也是"幾何形"型別的物件 所以"圓形"能夠接受''幾何形''的物件的訊息 這樣意味著可以編寫與"幾何形"互動並自動處理所有與幾何形性質相關的事物的程式碼 這種可替代性 是OOP中最強有力的概念
java中物件分配在系統"堆"記憶體中
final
- final 修飾變數 -->常量 不能被修改
- 1.宣告時初始化
- 2.建構函式內初始化(例項變數) 靜態變數(初始化程式碼塊內進行賦值)
- final修飾方法 -->該方法實現是穩定不變的,不允許覆蓋,但可以被過載
- final修飾類 -->該類不能被繼承
- final 避免了動態繫結
- 在探查式系統中可以確定哪些方法是未被覆蓋的 並且可以 "最優先地"將其內聯 就像是對待final修飾的一樣、
static
在static方法內部
JVM只為靜態分配一次記憶體,在載入類的過程中完成 只要類被載入了 就可以通過類名進行訪問(不推薦使用this進行訪問)
靜態方法內不能用this super關鍵字 不能直接訪問例項變數和例項方法
不能用靜態方法覆蓋例項方法,可以用例項方法的過載可以是靜態的
main()方法在頂端類 則必須宣告為static 若不在則不能宣告為 static
一 類
類可以包含 變數(欄位) 方法(函式) 其他類 程式碼塊
只有public, protected, private, static, final, transient 和 volatile 能修飾成員變數
class Test{
public int num; //例項變數: 每個物件例項都有其自己的一組例項變數
public static int count = 0; //靜態變數(類變數): 由一個物件的全體例項共享static 修飾
Test(int i){
this.num = i;
count++;
}
//當該類的物件建立以後,例項方法才分配了入口地址,該類的所有物件共享例項方法的入口地址
protected void printf(){
System.out.println("count is "+this.count+" "+"num="+this.num);
}
public class InteriorClass{ //內部類
{
this.SayHello(); //程式碼塊
}
public static SayHello(){ //靜態方法(類方法)
//靜態方法通過類名呼叫
System.out.println("Hello")
}
}
}
1.1訪問欄位和方法
1.同一類中,
- 可以直接通過名字訪問和呼叫類方法 (注意當方法中的變數與例項變數重名,則區域性變數會在方法中遮蔽 例項變數的名字,可以通過this指標顯示的引用當前物件的例項變數)
- 使用 this 顯示的引用當前物件或當前物件的一個成員
`2.其他類 可以通過引用來訪問物件的成員 點號 ( . )
對於靜態方法(類方法)可以直接通過類名進行呼叫 不用建立例項
對於例項方法 必須通過例項或物件呼叫
1.2 修改static final 組合在一起修飾的變數,則可能重新編譯使用了該類的所有程式碼
因為編譯器允許在引用這些值得類中對其"內聯"
1.3 靜態方法
關鍵字 static
可以通過類名由名字直接呼叫它,在此無需任何物件
1.4 初始化塊
定義:在類的範圍中直接宣告一個程式碼塊 {使用大括號 擴起的一些語句}
可以用static修飾 宣告為靜態即 靜態程式碼塊(靜態初始化塊),不能存在方法體中
構造程式碼塊(初始化塊):直接在類中宣告 ,位於所有成員、構造器以及宣告之外,構造塊會在建立物件時被呼叫,每次建立時都會被呼叫,優先於類建構函式執行。只有當所有的構造器都宣告某個檢查型異常時,初始化塊才可以丟擲該異常
在方法體中 區域性程式碼塊,在程式碼塊中宣告的變數,在程式碼塊結束時銷燬
區域性程式碼塊可以用synchronize(同步監視器)修飾 表示在同一時間只能有一個執行緒進入到該方法快中,是一種多執行緒保護機制 同步程式碼塊需要寫在方法中
載入:此程式碼塊不屬於任何方法,會在構造物件時執行一次;若標明程式碼塊為static 則會在類載入時執行一次
作用:為類或一個物件例項完成額外的準備工作
- 靜態初始化塊的優先順序最高,最先執行,並且僅在類第一次被載入時執行
- 靜態程式碼塊不能存在於任何方法體內。
- 靜態程式碼塊不能直接訪問例項變數和例項方法,需要通過類的例項物件來訪問
- 非靜態初始化塊和建構函式後執行,並且在每次生成物件時執行一次;
- 非靜態初始化塊的程式碼會在類建構函式之前執行。因此若要使用,應當養成把初始化塊寫在建構函式之前的習慣,便於除錯;
- 靜態初始化塊既可以用於初始化靜態成員變數,也可以執行初始化程式碼;
- 非靜態初始化塊可以針對多個過載建構函式進行程式碼複用。即將過載的建構函式 相同部分寫在程式碼塊中
- )當所有必要的類靜態變數和靜態程式碼塊 初始化程式碼塊載入完畢,開始執行main()方法體
2.1關於方法
宣告: 修飾符 返回值 方法名( 引數列表 );
實現: 修飾符 返回值 方法名( 引數列表 ) { //.... }
1 區域性變數的初始化
要確保使用到的區域性變數,在執行路徑上一定會存在賦值語句
2 引數的傳遞
基本型別值傳遞,物件傳引用
1.通常引用的相關操作將會影響到實際物件例項
2.若將引用指向另一個物件 則只會影響區域性變數的引用 ---->避免這樣的情況的方法: 將obj包裝在某類物件之中 例:可以將物件包裝起來作為某陣列中的獨立元素 TestObj [] test = new TestObj[]{ obj };
3.可變長度的引數列表
variable length argument lists 或 varargs
例子 :printf()
宣告: Object ... list (類似於陣列,使用同陣列)
在宣告varags之前也可以新增普通形參
void printObj (Object ... list ){
for(Object o : list)
System.out.println( o );
}
2.2建構函式
- 要求: 1.建構函式名必須與類名相同
- 2.必須,若自己沒有定義則編譯器會提供一個空的預設建構函式
- 3.不能宣告為 abstract synchronized final
- 4.沒有返回型別
- 5..若一個建構函式要呼叫另一個建構函式 則必須 將該呼叫語句 作為第一條
- 6.super() this() 該建構函式 this()可以使用類名字首呼叫 類名.this()
- 允許過載 不允許覆蓋
- 類的靜態員在類首次載入即得到初始化 ,在建構函式中呼叫靜態成員是安全的
3.1派生子類
使用 extends 關鍵字在宣告 為另一個類的子類 例如:class ArrayTest extends Arrays ;
子類可以從超類中繼承未指定private方法和變數,就如同自己宣告的變數和方法
子型別可以賦值給父類 反之不行
單繼承性
介面實現多繼承
1).遮蔽父類變數:
實現:子類可以宣告與父類同名的例項變數,引用該變數時 由其作用域決定到底引用的是哪個變數
作用: 通過遮蔽可以實現修改其型別或可見性 ,但若將子類賦值給父類,在呼叫其變數,將得到該變數在父類中的形式
2).覆蓋方法
- 物件: 父類中的方法 如:實現介面的抽象方法
- 要求: 1. 必須擁有完全相同的引數數目 順序 和型別
- 2.返回值可以將其修改為原型別的子型別,否則不能修改其型別
- 3.不可降低方法的可見性
- 作用 : 改變物件的行為 實現子型別多型性
- 覆蓋方法 "派生層次最低的類的方法總會覆蓋其他的方法" 與遮蔽變數不同
- 超類中的靜態方法由子類中的靜態方法所遮蔽,(用final標記除外) 不能用非靜態方法覆蓋靜態方法
- @Override 標記,告訴編譯器 該方法為覆蓋,非必須
- 覆蓋方法發生在執行時,即動態繫結
- 新的方法可選擇丟擲與被覆蓋的方法完全相同的受查異常,也可以丟擲更為具體的子型別 新的方法可以重定義throws子句,使其更具體,這種技術稱為協變.
3)方法過載
- 意義:實現特別多型性
- 物件: 本類中的方法或父類中的方法
- 要求:必須 引數數目 引數順序 或引數型別 不同
- 返回值和可見修飾符不同則不能算過載 編譯的時候直接報方法名重複錯
- 方法過載由編譯器來選定過載方法,不是在執行時發生的工作
4 強制型別轉換
1).條件: java中 只有同一體系結構中的物件之間進行的強制型別轉換才是合法的
強制型別轉換需通過編譯器和執行時系統的檢查,
2).影響: 會影響引用的處理,會影響編譯時元素(如變數和過載方法的選擇)
不會改變覆蓋方法,不會改變實際物件的形式,僅改變編譯器的"看法"
3).通過使用泛型減少前值型別轉換
5.內部類
本質 每個內部類最後都將被編譯成一個獨立的類,生成一個被編譯為一個獨立的類。內部類是java編譯器的概念
內部類方便地訪問外部類的私有變數
內部類可以宣告為 private 從而對外完全隱蔽
1. 頂級類 : 在檔案和包一級獨立地進行宣告 不能被修飾成靜態
2. 內部類 : 宣告在大括號內,屬於 方法 或 類 內部類可以直接訪問外部類 外部類訪問內部類必須通過建立內部類例項訪問
3. 靜態內部類 (巢狀類) 和靜態變數 靜態方法的位置一樣 修飾符為static
- 限定名為 外部類名.靜態內部類名
- 外部 >使用> 非private靜態內部類 方式: 外部類名.靜態內部類名
- 外部類 >使用> 靜態內部類 外部類名.靜態內部類名 或 靜態內部類名
建立 範圍 外部類名.靜態內部類名 引用名 = new 外部類名.靜態內部類名 (); 同包下的其他類 外包 外部類名.靜態內部類名 引用名 = new 靜態內部類名(); 外部類 靜態內部類名 引用名 = new 內部類名(); 外部類 - 靜態內部類 >使用> 外部類
- 可以訪問外部類的私有成員或方法
- (類名.靜態變數或靜態方法 或者直接使用變數名或方法名)訪問靜態變數和方法
- 不能訪問例項變數和方法
4 成員內部類:和靜態內部類相比 沒有static修飾符 除了靜態變數和靜態方法 還可以訪問外部類的成員變數和成員方法
- 成員內部類 >訪問> 外部類 1. 無重名情況 : 直接通過名字訪問外部類的變數及成員
- 2. 有重名情況 : 外部類.this.xxx 訪問外部類變數和成員
- 限制: 內部類的變數和方法 不允許用static修飾 (唯一例外用 static final修飾變數)
- 建立: 內部類物件: 成員內部類物件總是和一個外部類物件相連的
- 1.建立外部類物件 2. 外部類.內部類 物件名 = 外部類物件名.new 內部類( );
5. 方法內部類 :只能在定義的方法中使用 可以訪問方法中的被final修飾的引數和區域性變數
靜態方法中的內部類: 能訪問外部類中靜態變數和靜態常量 方法中的被final修飾的引數和區域性變數
例項方法中的內部類: 能訪問外部類的例項/靜態 變數和方法
public class Test{
private static int i = 1;
private static char c ='A';
private static void print_i(){
System.out.println("外部類 :i "+i);
}
public void t() {
inner t = new inner();
t.innerMethod();
}
public void inner
static class inner{
public int i=10101; // 1.可以重名
inner(){
System.out.println("通過類名.靜態成員訪問和本類有重名的 i="+Test.i);
System.out.println("通過 私有靜態成員的名字 訪問c="+c);
print_i();//通過 私有靜態方法的名字呼叫
}
public void innerMethod(){
System.out.println("我是靜態內部類的例項方法");
}
}
}
//實質
public class Test{
private static int i = 1;
private static char c ='A';
private static void print_i(){
System.out.println("外部類 :i "+i);
}
public void t() {
inner t = new inner();
t.innerMethod();
}
public void t() {
Test$inner t = new Test$inner();
t.innerMethod();
}
static int access$0(){
return i;
}
。。。。
}
static class Test$inner{
public int i=10101; // 1.可以重名
inner(){
System.out.println("通過類名.靜態成員訪問和本類有重名的 i="+Test.i);
System.out.println("通過 私有靜態成員的名字 訪問c="+c);
print_i();//通過 私有靜態方法的名字呼叫
}
6 匿名內部類
在建立物件的同時,定義內部類 new 父類(引數){//內部類的實現 };
new 介面 ( ){//內部類的實現 };
匿名內部類是唯一一種沒有構造器的類。大部分匿名內部類用於介面回撥。匿名內部類在編譯的時候由系統自動起名為外部類$1.class 同一外部類編號從1開始。一般來說,匿名內部類用於繼承其他類或是實現介面,並不需要增加額外的方法,只是對繼承方法的實現或是重寫,通常寫在 方法內 或引數列表 --->方法中的被final修飾的引數和區域性變數
//2. 內部類
class Animal{ //Animal中任何位置都可以直接通過名字來直接飲用Brain和performBehavior()
class Brain{ //可以值訪問Animal中宣告的所有變數和方法
//內部類Brain總包含在Animal的一個例項中,稱此例項為 包圍例項
...
}
void performBehavior()//可以處理Brain類並建立Brain例項
{...}
}
//訪問內部類
Animal monkey = new Animal();
Animal.Brain monkeyBrain = monkey.new Brain();
//6.匿名內部類
iterator getIterator(){
return new Iterator(){
int element =0;
boolean hasNext(){
return elemnt< employees.length;
}
Object next(){
if( hasNext() )
return employess[ element++ ];
else
throw new UnsupportedOperationException();
}
}; //
}
用途 1 作為介面卡 匿名內部類的介面卡特別適合與事件處理
內部類的工作原理
編譯器 將內部類建立為一個正常的頂級類 為之命名: 將類名與美元符號嘉禾 Animal$Brain
可以在同一檔案中 頂層類外建立類 該類僅頂層類可見
可用於建立該頂層類專用的資料結構等
//檔名 Test.java
class DateType{ //不能被宣告為static 與 public protected private 無可見修飾符
String name ;
int age ;
DateType(String a , int v){
this.name =a ;
age = v;
}
}
public class Test{
DateType newA = new DateType("Y",12);
//....
public static void main(String[] agrs){
Test a = new Test();
//...
}
}
二 抽象與介面
抽象類與介面之間可以相互巢狀
abstract
- 僅能修飾類和方法
- abstract方法 僅能存在與 abstract 類中
- abstract類中可以沒有abstract方法
1.1抽象方法
宣告: abstract 返回型別 方法名 ( 引數列表 ); // 僅有宣告無實現
1.2抽象類
0).宣告 abstract class Test{ //用abstract修飾類即可 }
1).內容:1.包含零個抽象方法, 抽象方法要被實現,所以不能是靜態的,也不能是私有的。
2.可以包含非抽象方法和變數,可以有靜態的main 方法
2).不能被例項化
3).對於子類的要求:
- 若子類實現一部分抽象方法,則它也必須宣告為abstract
- 子類將所有抽象方法覆蓋
4)抽象類可以繼承實體類 但實體類的建構函式,必須有明確的建構函式
5) 可以 實現介面 ,對於介面內的方法抽象類可以實現全部.部分.0. 個方法
6)如果要例項化,抽象類變數必須指向實現所有抽象方法的子類物件,介面變數必須指向實現所有介面方法的類物件。
2.介面interface
頂層類 可見性 預設(預設) public
宣告在類內部 時 可public protected default(預設) private
宣告在介面 public
0).用interface關鍵字 定義介面
interface Animal{ //僅允許也是預設的 : public abstract boolean live(); void eat(); }
1).用implement子句宣告實現介面
class dog implement Animal { String name; boolean dogLive; boolean live(){ if(this.dogLive == true) return true; else return false; } void eat(){ if(dogLive == fasle) return ; else{ System.out.println("Hi"+this.name+"eat"); } } }
3).介面定義了類 必須實現的一組方法
4).一個類可以實現多個介面 (多個介面之間逗號間隔)
5).可以宣告變數為一種介面型別,也可以宣告方法的引數wei 介面型別 可指定一個方法返回一個介面型別
6).屬性的預設(也僅允許)是public static final 通過介面的名稱來引用它
方法是預設(也僅允許)public abstract
7).空介面 作為標記,表示一個類由特殊性 如java,io.Serializable 希望得到串型化的類
8).java8中 介面可以有實現方法 使用default修飾
2.1子介面
1).定義: 介面型別繼承另一個或多個介面型別 (用逗號分隔 ,)
2).方法的衝突與覆蓋
衝突: 存在方法具有相同的名稱
覆蓋: 若具有完全相同的簽名和返回型別,則無問題 (ps: 方法的簽名 與名稱和引數列表有關)
若它們在過載方式有所不同,則必須對不同方法簽名的一一覆蓋
若具有相同的名稱,但返回型別或異常型別有區別,則該類無法將兩個方法都實現,並且會發生編譯錯誤
3.
如果要例項化,抽象類變數必須指向實現所有抽象方法的子類物件,介面變數必須指向實現所有介面方法的類物件。
接口裡定義的變數只能是公共的靜態的常量,抽象類中的變數是普通變數
抽象方法只能申明,不能實現,介面是設計的結果 ,抽象類是重構的結果
普通類不能有抽象方法
三 包
1. 編譯單元
java類的原始碼被組織為編譯單元,一個簡單的編譯單元僅包含一個類定義,並以類名來命名
將類劃分至各自的編譯單元中是非常重要的
2.package
- 包名 採用以點號分隔的命名約定,按層次體系來構造(包的名稱空間實際上是平坦的)
- 預設下,包名的各部分對應目錄名,充當唯一的路徑,以供編譯器和執行時系統定位java原始檔和類
- package語句宣告一個類屬於一個特定的包 必須作為檔案的第一條語句 作用於整個檔案
3.匯入類
import 語句 應用於整個編譯單元
完全限定名 : 包名.類名
簡單名(短名): 類名
宣告: import 類的完全限定名 ;
import 包名.*; //匯入該包內的所有類
4.未命名包
若一個類定義與某個編譯單元 而此編譯單元未指定包,則該類將落入 未命名包
為命名包內的類可以通過簡單名相互引用
編譯和執行時 這些類的路徑即認為當前路徑
四 訪問修飾符
private | 僅自身類的例項可以訪問 |
default | 包中的類 |
protected | 包中的類 子類(包括其他包中的子類) |
public | 所有類 |
基本翻譯
n. 介面;<計>介面;交介面
v. (使通過介面或介面)接合,連線;[計算機]使聯絡
vi. 相互作用(或影響);交流,交談
網路釋義
Interface: 介面
pattern interface: 介面模式