}
其中的一個元素爲 a[x][y],
順時針旋轉 90度後, 該元素的座標爲 a[y][n-x]
而如果父類中的私有方法被子類調用的話,則編譯報錯。
父類的構造方法子類不可以繼承,更不存在覆蓋的問題。(非構造方法可以)
對於方法的修飾詞,子類方法要比父類的方法範圍更加的寬泛。
父類爲 public,那麼子類爲private則出現錯誤。
構造一個對象的順序:(注意:構造父類對象的時候也是這幾步)
① 遞歸地構造父類對象;
② 順序地調用本類成員屬性賦初值語句;
③ 本類的構造方法。
Super()表示調用父類的構造方法。
Super()也和this一樣必須放在第一行。
This()用於調用本類的構造方法。
如果沒有定義構造方法,那麼就會調用父類的無參構造方法,即super()。
要養成良好的編程習慣:就是要加上默認的父類無參的構造方法。
思考:可是如果我們沒有定義無參的構造方法,而在程序中構造了有參的構造方法,那麼如果方法中沒有參數,那麼系統還會調用有參的構造方法麼?應該不會。
多態分兩種:
① 編譯時多態:編譯時動態重載;
② 運行時多態:指一個對象可以具有多個類型。
對象是客觀的,人對對象的認識是主觀的。
例:
Animal a=new Dog();查看格式名稱;
Dog d=(Dog)a。聲明父類來引用子類。
(思考上面的格式)
運行時多態的三原則:(應用時爲覆蓋)
1、 對象不變;(改變的是主觀認識)
2、 對於對象的調用只能限於編譯時類型的方法,如調用運行時類型方法報錯。
在上面的例子中:Animal a=new Dog();對象a的編譯時類型爲Animal,運行時類型爲dog。
注意:編譯時類型一定要爲運行時類型的父類(或者同類型)。
對於語句:Dog d=(Dog)a。將d強制聲明爲a類型,此時d爲Dog(),此時d就可以調用運行時類型。注意:a和d指向同一對象。
23.關係運算符: instanceof
a instanceof Animal;(這個式子的結果是一個布爾表達式 )
a爲對象變量, Animal是類名。
上面語句是判定a是否可以貼 Animal標籤。如果可以貼則返回 true,否則返回false 。
在上面的題目中: a instanceof Animal返回 True ,
a instanceof Dog 也返回 True,
instanceof用於判定是否將前面的對象變量賦值後邊的類名。
靜態方法中不允許訪問類的非靜態成員,包括成員的變量和方法,因爲此時是通過類調用的,沒有對象的概念。 This.data是不可用的。
一般情況下,主方法是靜態方法,所以可調用靜態方法,主方法爲靜態方法是因爲它是整個軟件系統的入口,而進入入口時系統中沒有任何對象,只能使用類調用。
覆蓋不適用於靜態方法。
靜態方法不可被覆蓋。(允許在子類中定義同名靜態方法,但是沒有多態,嚴格的講,方法間沒有多態就不能稱爲覆蓋)
當static修飾代碼塊時(注:此代碼塊要在此類的任何一個方法之外),那麼這個代碼塊在代碼被裝載進虛擬機生成對象的時候可被裝載一次,以後再也不執行了。
一般靜態代碼塊被用來初始化靜態成員。
Static通常用於Singleton 模式開發:
final可以修飾類、屬性、方法。
當用final修飾類的時候,此類不可被繼承,即final類沒有子類。這樣可以用final保證用戶調用時動作的一致性,可以防止子類覆蓋情況的發生。
當利用final修飾一個屬性(變量)的時候,此時的屬性成爲常量。
JAVA利用final定義常量(注意在JAVA命名規範中常量需要全部字母都大寫):
Final int AGE=10;
常量的地址不可改變,但在地址中保存的值(即對象的屬性)是可以改變的。
Final可以配合static使用。 ?
Static final int age=10;
在JAVA中利用public static final的組合方式對常量進行標識(固定格式)。
對於在構造方法中利用final進行賦值的時候,此時在構造之前系統設置的默認值相對於構造方法失效。
常量(這裏的常量指的是實例常量:即成員變量)賦值:
①在初始化的時候通過顯式聲明賦值。Final int x=3;
②在構造的時候賦值。
局部變量可以隨時賦值。
利用final定義方法:這樣的方法爲一個不可覆蓋的方法。
Public final void print(){};
爲了保證方法的一致性(即不被改變),可將方法用final定義。
如果在父類中有final定義的方法,那麼在子類中繼承同一個方法。
如果一個方法前有修飾詞private或static,則系統會自動在前面加上final。即private和static方法默認均爲final方法。
Abstract(抽象)可以修飾類、方法
Abstract雖然不能生成對象,但是可以聲明,作爲編譯時類型,但不能作爲運行時類型。
Final和abstract永遠不會同時出現。
注意比較:
private void print(){};此語句表示方法的空實現。
Abstract void print(); 此語句表示方法的抽象,無實現。
如果一個類中有一個抽象方法,那麼這個類一定爲一個抽象類。
反之,如果一個類爲抽象類,那麼其中可能有非抽象的方法。
如果讓一個非抽象類繼承一個含抽象方法的抽象類,則編譯時會發生錯誤。因爲當一個非抽象類繼承一個抽象方法的時候,本着只有一個類中有一個抽象方法,那麼這個類必須爲抽象類的原則。這個類必須爲抽象類,這與此類爲非抽象衝突,所以報錯。
所以子類的方法必須覆蓋父類的抽象方法。方法才能夠起作用。
與類相似,一個文件只能有一個public接口,且與文件名相同。
在一個文件中不可同時定義一個public接口和一個public類。
一個接口中,所有方法爲公開、抽象方法;所有的屬性都是公開、靜態、常量。
類必須實現接口中的方法,否則其爲一抽象類。
實現中接口和類相同。
接口中可不寫public,但在子類中實現接口的過程中public不可省。
(如果剩去public則在編譯的時候提示出錯:對象無法從接口中實現方法。)
① 接口和接口之間可以定義繼承關係,並且接口之間允許實現多繼承。
例:interface IC extends IA,IB{};
接口實際上是定義一個規範、標準。
① 通過接口可以實現不同層次、不同體系對象的共同屬性;
通過接口實現write once as anywhere.
以JAVA數據庫連接爲例子:JDBC制定標準;數據廠商實現標準;用戶使用標準。
接口通常用來屏蔽底層的差異。
②接口也因爲上述原因被用來保持架構的穩定性。
JAVA中有一個特殊的類: Object。它是JAVA體系中所有類的父類(直接父類或者間接父類)。
此類中的方法可以使所的類均繼承。
以下介紹的三種方法屬於Object:
(1) finalize方法:當一個對象被垃圾回收的時候調用的方法。
(2) toString():是利用字符串來表示對象。
當我們直接打印定義的對象的時候,隱含的是打印toString()的返回值。
可以通過子類作爲一個toString()來覆蓋父類的toString()。
以取得我們想得到的表現形式,即當我們想利用一個自定義的方式描述對象的時候,我們應該覆蓋toString()。
字符串類爲 JAVA中的特殊類,String中爲 final類,一個字符串的值不可重複。因此在 JAVA VM(虛擬機)中有一個字符串池,專門用來存儲字符串。如果遇到 String a=”hello”時(注意沒有 NEW,不是創建新串),系統在字符串池中尋找是否有 ”hello”,此時字符串池中沒有”hello”,那麼系統將此字符串存到字符串池中,然後將 ”hello”在字符串池中的地址返回 a。如果系統再遇到String b=”hello”,此時系統可以在字符串池中找到 “hello”。則會把地址返回b,此時 a與b 爲相同。
String a=”hello”;
System.out.println(a==”hello”);
系統的返回值爲 true。
故如果要比較兩個字符串是否相同(而不是他們的地址是否相同)。可以對 a調用equal:
System.out.println(a.equal(b));
equal用來比較兩個對象中字符串的順序。
a.equal(b)是 a與b 的值的比較。
注意下面程序:
student a=new student(“LUCY”,20);
student b=new student(“LUCY”,20);
System.out.println(a==b);
System.out.println(a.equal(b));
此時返回的結果均爲false。
以下爲定義 equal(加上這個定義,返回ture或 false)
public boolean equals(Object o){
student s=(student)o;
if (s.name.equals(this.name)&&s.age==this.age)
else return false;
}如果equals() 返回的值爲
以下爲實現標準 equals的流程:
public boolean equals(Object o){
if (this==o) return trun; // 此時兩者相同
if (o==null) return false;
if (! o instanceof strudent) return false; // 不同類
studeng s=(student)o; // 強制轉換
if (s.name.equals(this.name)&&s.age==this.age) return true;
else return false;
“==”在任何時候都是比較地址,這種比較永遠不會被覆蓋。
當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換爲字節序列,即Java對象序列號,才能在網絡上傳送;接收方則需要把字節序列再恢復爲Java對象,即反序列化。
把Java對象轉換爲字節序列的過程稱爲對象的序列化。
把字節序列恢復爲Java對象的過程稱爲對象的反序列化。
對象的序列化主要有兩種用途:
1) 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;
JAVA爲每一個簡單數據類型提供了一個封裝類,使每個簡單數據類型可以被Object來裝載。
除了int和char,其餘類型首字母大寫即成封裝類。
轉換字符的方式:
int I=10;
String s=I+” ”;
String s1=String.valueOf(i);
Int I=10;
Interger I_class=new integer(I);
看javadoc的幫助文檔。
附加內容:
“==”在任何時候都是比較地址,這種比較永遠不會被覆蓋。
程序員自己編寫的類和JDK類是一種合作關係。(因爲多態的存在,可能存在我們調用JDK類的情況,也可能存在JDK自動調用我們的類的情況。)
注意:類型轉換中double\interger\string之間的轉換最多。
12.01
內部類:
(注:所有使用內部類的地方都可以不用內部類,使用內部類可以使程序更加的簡潔,便於命名規範和劃分層次結構)。
內部類是指在一個外部類的內部再定義一個類。
內部類作爲外部類的一個成員,並且依附於外部類而存在的。
內部類可爲靜態,可用PROTECTED和PRIVATE修飾。(而外部類不可以:外部類只能使用PUBLIC和DEFAULT)。
內部類的分類:
成員內部類、
局部內部類、
靜態內部類、
匿名內部類(圖形是要用到,必須掌握)。
① 成員內部類:作爲外部類的一個成員存在,與外部類的屬性、方法並列。
內部類和外部類的實例變量可以共存。
在內部類中訪問實例變量:this.屬性
在內部類訪問外部類的實例變量:外部類名.this.屬性。
成員內部類的優點:
⑴內部類作爲外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明爲PRIVATE,但是對於處於其內部的內部類還是可見的。)
⑵用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
注意:內部類是一個編譯時的概念,一旦編譯成功,就會成爲完全不同的兩類。
對於一個名爲outer的外部類和其內部定義的名爲inner的內部類。編譯完成後出現outer.class和outer$inner.class兩類。
(編寫一個程序檢驗:在一個TestOuter.java程序中驗證內部類在編譯完成之後,會出現幾個class.)
成員內部類不可以有靜態屬性。(爲什麼?)
如果在外部類的外部訪問內部類,使用out.inner.
建立內部類對象時應注意:
在外部類的內部可以直接使用inner s=new inner();(因爲外部類知道inner是哪個類,所以可以生成對象。)
而在外部類的外部,要生成(new)一個內部類對象,需要首先建立一個外部類對象(外部類可用),然後在生成一個內部類對象。
Outer.Inner in=Outer.new.Inner()。
錯誤的定義方式:
Outer.Inner in=new Outer.Inner()。
注意:當Outer是一個private類時,外部類對於其外部訪問是私有的,所以就無法建立外部類對象,進而也無法建立內部類對象。
② 局部內部類:在方法中定義的內部類稱爲局部內部類。
與局部變量類似,在局部內部類前不加修飾符public和private,其範圍爲定義它的代碼塊。
注意:局部內部類不僅可以訪問外部類實例變量,還可以訪問外部類的局部變量(但此時要求外部類的局部變量必須爲final)??
在類外不可直接生成局部內部類(保證局部內部類對外是不可見的)。
要想使用局部內部類時需要生成對象,對象調用方法,在方法中才能調用其局部內部類。
③ 靜態內部類:(注意:前三種內部類與變量類似,所以可以對照參考變量)
靜態內部類定義在類中,任何方法外,用static定義。
靜態內部類只能訪問外部類的靜態成員。
生成(new)一個靜態內部類不需要外部類成員:這是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通過生成外部類對象來生成。這樣實際上使靜態內部類成爲了一個頂級類。
靜態內部類不可用private來進行定義。例子:
對於兩個類,擁有相同的方法:
People
{
run();
}
Machine{
run();
}
此時有一個robot類:
class Robot extends People implement Machine.
此時run()不可直接實現。
注意:當類與接口(或者是接口與接口)發生方法命名衝突的時候,此時必須使用內部類來實現。
用接口不能完全地實現多繼承,用接口配合內部類才能實現真正的多繼承。
④ 匿名內部類(必須掌握):
匿名內部類是一種特殊的局部內部類,它是通過匿名類實現接口。
IA被定義爲接口。
IA I=new IA(){};
注:一個匿名內部類一定是在new的後面,用其隱含實現一個接口或實現一個類,沒有類名,根據多態,我們使用其父類名。
因其爲局部內部類,那麼局部內部類的所有限制都對其生效。
匿名內部類是唯一一種無構造方法類。
匿名內部類在編譯的時候由系統自動起名Out$1.class。
如果一個對象編譯時的類型是接口,那麼其運行的類型爲實現這個接口的類。
因匿名內部類無構造方法,所以其使用範圍非常的有限。
非Runtime exception(已檢查異常)
(注意:無論是未檢查異常還是已檢查異常在編譯的時候都不會被發現,在編譯的過程中檢查的是程序的語法錯誤,而異常是一個運行時程序出錯的概念。)
在Exception中,所有的非未檢查異常都是已檢查異常,沒有另外的異常!!
未檢查異常是因爲程序員沒有進行必要的檢查,因爲他的疏忽和錯誤而引起的異常。一定是屬於虛擬機內部的異常(比如空指針)。
應對未檢查異常就是養成良好的檢查習慣。
已檢查異常是不可避免的,對於已檢查異常必須實現定義好應對的方法。
已檢查異常肯定跨越出了虛擬機的範圍。(比如“未找到文件”)
如何處理已檢查異常(對於所有的已檢查異常都要進行處理):
首先了解異常形成的機制:
當一個方法中有一條語句出現了異常,它就會throw(拋出)一個例外對象,然後後面的語句不會執行返回上一級方法,其上一級方法接受到了例外對象之後,有可能對這個異常進行處理,也可能將這個異常轉到它的上一級。
對於接收到的已檢查異常有兩種處理方式:throws和try方法。
注意:出錯的方法有可能是JDK,也可能是程序員寫的程序,無論誰寫的,拋出一定用throw。
例:public void print() throws Exception.
對於方法a,如果它定義了throws Exception。那麼當它調用的方法b返回異常對象時,方法a並不處理,而將這個異常對象向上一級返回,如果所有的方法均不進行處理,返回到主方法,程序中止。(要避免所有的方法都返回的使用方法,因爲這樣出現一個很小的異常就會令程序中止)。
如果在方法的程序中有一行throw new Exception(),返回錯誤,那麼其後的程序不執行。因爲錯誤返回後,後面的程序肯定沒有機會執行,那麼JAVA認爲以後的程序沒有存在的必要。
Try中如果發現錯誤,即跳出try去匹配catch,那麼try後面的語句就不會被執行。
一個try可以跟進多個catch語句,用於處理不同情況。當一個try只能匹配一個catch。
我們可以寫多個catch語句,但是不能將父類型的exception的位置寫在子類型的excepiton之前,因爲這樣父類型肯定先於子類型被匹配,所有子類型就成爲廢話。JAVA編譯出錯。
在try,catch後還可以再跟一子句finally。其中的代碼語句無論如何都會被執行(因爲finally子句的這個特性,所以一般將釋放資源,關閉連接的語句寫在裏面)。
如果在程序中書寫了檢查(拋出)exception但是沒有對這個可能出現的檢查結果進行處理,那麼程序就會報錯。
Exception有一個message屬性。在使用catch的時候可以調用:
Catch(IOException e){System.out.println(e.message())};
Catch(IOException e){e.printStackTrace()};
上面這條語句回告訴我們出錯類型所歷經的過程,在調試的中非常有用。
開發中的兩個道理:
①如何控制try的範圍:根據操作的連動性和相關性,如果前面的程序代碼塊拋出的錯誤影響了後面程序代碼的運行,那麼這個我們就說這兩個程序代碼存在關聯,應該放在同一個try中。
① 對已經查出來的例外,有throw(積極)和try catch(消極)兩種處理方法。
對於try catch放在能夠很好地處理例外的位置(即放在具備對例外進行處理的能力的位置)。如果沒有處理能力就繼續上拋。
當我們自己定義一個例外類的時候必須使其繼承excepiton或者RuntimeException。
Throw是一個語句,用來做拋出例外的功能。
而throws是表示如果下級方法中如果有例外拋出,那麼本方法不做處理,繼續向上拋出。
Throws後跟的是例外類型。
斷言是一種調試工具(assert)
其後跟的是布爾類型的表達式,如果表達式結果爲真不影響程序運行。如果爲假系統出現低級錯誤,在屏幕上出現assert信息。
Assert只是用於調試。在產品編譯完成後上線assert代碼就被刪除了。
方法的覆蓋中,如果子類的方法拋出的例外是父類方法拋出的例外的父類型,那麼編譯就會出錯:子類無法覆蓋父類。
結論:子類方法不可比父類方法拋出更多的例外。子類拋出的例外或者與父類拋出的例外一致,或者是父類拋出例外的子類型。或者子類型不拋出例外。
正因爲以上的原因, TreeSet和TreeMap 的實現也有些類似的關係。
HashSet VS TreeSet:HashSet 非常的消耗空間, TreeSet因爲有排序功能,因此資源消耗非常的高,我們應該儘量少使用,而且最好不要重複使用。
基於以上原因,我們儘可能的運用 HashSet而不用TreeSet ,除非必須排序。
同理: HashMap VS TreeMap:一般使用HashMap ,排序的時候使用 TreeMap。
一致性
equals
附加
編輯本段重寫HashMap對象是根據其Key的hashCode來獲取對應的Value。
PipedOutputStream
PipedInputStream
輸出流:connect(輸入流)
RondomAccessFile類允許隨機訪問文件GetFilepoint()可以知道文件中的指針位置,使用seek()定位。Mode(“r”:隨機讀;”w”:隨機寫;”rw”:隨機讀寫)Io包的InputStreamread稱爲從字節流到字符流的橋轉換類。這個類可以設定字符轉換方式。
OutputStreamred:字符到字節
Bufferread有readline() 使得字符輸入更加方便。
在I/O流中,所有輸入方法都是阻塞方法。
Bufferwrite給輸出字符加緩衝,因爲它的方法很少,所以使用父類 printwrite,它可以使用字節流對象,而且方法很多。用流傳輸對象稱爲對象的序列化,但並不使所有的對象都可以進行序列化的。只有在實現類時必須實現一個接口:IO包下的Serializable(可序列化的)。此接口沒有任何的方法,這樣的接口稱爲標記接口。
Class Student implements Serializable
把對象通過流序列化到某一個持久性介質稱爲對象的可持久化。Transient用來修飾屬性。
Transient int num;
表示當我們對屬性序列化時忽略這個屬性(即忽略不使之持久化)。
ü Java 局部變量和方法參數在棧中分配,大小是按照變量的類型分配
ü 基本類型變量的空間大小:就是基本類型的空間大小,值是基本類型的值
ü 引用變量的值是一個對象的地址值,引用變量通過地址引用了一個堆對象
ü Java方法參數傳遞只有一種方式,基於值的傳遞,是變量值的複製
ü 基本類型就是其中值的複製
a) 爲對象開闢內存空間。
b) 調用類的構造方法。
ü 構造器丌能繼承!
ü 實例化子類,會遞歸分配所有父類的空間
ü 子類構造器一定調用父類構造器
48.多態:父類型引用子類型,編譯期丌確定什麼類型(統一都是Question的),運行期才能確定
使用super()調用父類構造器,必須寫在子類構造器第一行
ü this() 必須寫在子類構造器第一行
如果父類沒有無參數構造器,就必須在子類中明確指定調用父類的有參數構造器!
知識點:
final的局部變量,只能初始化丌能改
final的方法參數,丌能改
final的引用,引用指向丌能改,但是對象的屬性可以改
比較引用值是否相等: “ ==”
a) 構造方法不能被繼承
b) 方法和屬性可以被繼承
c) 子類的構造方法隱式地調用父類的不帶參數的構造方法
式地調用父類的構造方法, super指的是對父類的引用