Java學習常見的易錯點、難點(一)

1、作用域public,private,protected, 以及不寫時的區別
 答:區別如下:
 作用域     當前類      同一 package  子孫類       其他package
    public            √                                     
    protected                                              ×
    friendly                                  ×              ×
    private           √               ×        ×              × 
不寫時默認爲 friendly

2Anonymous Inner Class ( 匿名內部類) 是否可以 extends繼承 )其它類,是否可以 implements(實現)interface( 接口)
答:匿名的內部類是沒有名字的內部類。不能 extends(繼承 ) 其它類,但一個內部類可以作
爲一個接口,由另一個內部類實現

3.Collection Collections 的區別
答:Collection是集合類的上級接口,繼承與他的接口主要有 Set  List.Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作

4.String s=new String("jzy");創建了幾個對象

5.抽象類不一定包含抽象方法,覆蓋方法拋出的異常不能比原方法多,子類中訪問權限不能比原方法更嚴格。

6.不能在靜態方法中使用this。

7.編譯MyClass.java之後,得到了三個字節碼文件:MyClass.class , MyClasslittle$.class MyClass$1.class.這表明什麼
答: MyClass類中有兩個內部類:一個是命名的little,另一個是匿名的1

8.當方法遇到異常又不知如何處理時,應該怎麼做拋出異常

9.類的加載和構造方法的調用順序  
類的加載的順序:先遞歸地加載父類的靜態成員/代碼塊(object的最先);再依次加載
到本類的靜態成員。  調用構造方法:先遞歸地調用父類的構造方法;默認調用父類空參的同,也可在第一行寫明調用用父類某個帶參的。再依次到本類的構造方法;  先初始化父類的靜態代碼--->初始化子類的靜態代碼-->                 == ==(創建實例時,如果不創建實例,則後面的不執行)初始化父類的非靜態代碼---> == ==初始化父類構造函數--->初始化子類非靜態代碼--->初始化子類構造函數    ==

10.在異常處理中若try中的代碼可能產生多種異常則可以對應多個catch語句,若catch中的參數類型有父類子類關係,此時應該將父類放在後面,子類放在前面。

11.while循環判斷條件一般是程序結果,for循環的判斷條件一般是非程序結果

12.一個接口實現多個接口用extends
如:
public interface 新接口 extends 交通工具, 金屬製品 {

}

13.數組旋轉90°座標變換
假設該數組爲 a[n][n], 
其中的一個元素爲  a[x][y],
順時針旋轉 90度後, 該元素的座標爲  a[y][n-x]
14.所有類的對象其實都是Class的實例
15.Annotation(註解)是JDK5.0及以後版本引入的。它可以用於創建文檔,跟蹤代碼中的依賴性,甚至執行基本編譯時檢查。註解是以‘@註解名’在代碼中存在的,根據註解參數的個數,我們可以將註解分爲:標記註解、單值註解、完整註解三類。它們都不會直接影響到程序的語義,只是作爲註解(標識)存在,我們可以通過反射機制編程實現對這些元數據的訪問。另外,你可以在編譯時選擇代碼裏的註解是否只存在於源代碼級,或者它也能在class文件中出現。
16.方法和屬性的繼承(方法屬性子類和父類都聲明瞭)
        Parent a=new Child();
        a.showData();      //調用的是子類的方法
        System. out.println(a. i);      //調用的是父類的屬性
17.實例變量:定義在類中但在任何方法之外。(New出來的均有初值)
局部變量:定義在方法之中的變量。
局部變量要先賦值,再進行運算,而實例變量均已經賦初值。這是局部變量和實例變量的一大區別。
18.構造方法
注意:構造方法在生成對象的時候會被調用,但並不是構造方法生成了對象。
構造方法是在對象生成的過程中自動調用,不可能利用指令去調用。
在一個對象的生成周期中構造方法只用一次,一旦這個對象生成,那麼這個構造方法失效。
可以構造多個構造方法,但多個構造方法的參數表一定不同,參數順序不同即屬於不同的構造方法:
public student(string name,int a){
}
public student(int a,string name){
}
爲兩個不同的構造方法。
在構造方法中, this表示本類的其他構造方法:
student(){};
student(string n){
  this();// 表示調用student()
}
如果調用 student(int a)則爲this(int a)
特別注意 this調用其他構造方法時,this必須爲第一條語句,然後纔是其他語句
19.this
This表示當前對象。

Public  void  printNum(){
  Int number=40 
  System.out.println(this.number);
}
此時打印的是實例變量,而非局部變量,即定義在類中而非方法中的變量。
This.number表示實例變量。
誰調用 this.number那麼誰即爲當前(this)對象的number 方法。
如果不指明誰調用方法,則默認爲 this 。
區分實例變量和局部變量時一定要寫 this 。
20.封裝:使對象的屬性儘可能私有,對象的方法儘可能的公開。用 private表示此成員屬性爲該類的私有屬性。
Public表示該屬性(方法)公開;
Private表示該屬性(方法)爲只有本類內部可以訪問(類內部可見)。
(想用 private還要用setget方法供其他方法調用,這樣可以保證對屬性的訪問方式統一,並且便於維護訪問權限以及屬性數據合法性)
如果沒有特殊情況,屬性一定私有,方法該公開的公開。
21.繼承

而如果父類中的私有方法被子類調用的話,則編譯報錯。

父類的構造方法子類不可以繼承,更不存在覆蓋的問題。(非構造方法可以)

如果子類訪問父類的構造方法,則在編譯的時候提示訪問不到該方法。

對於方法的修飾詞,子類方法要比父類的方法範圍更加的寬泛。

父類爲 public,那麼子類爲private則出現錯誤。

之所以構造方法先運行父類再運行子類是因爲構造方法是無法覆蓋的。
當構造一個對象的時候,系統先構造父類對象,再構造子類對象。
構造一個對象的順序:(注意:構造父類對象的時候也是這幾步)
①     遞歸地構造父類對象;
②     順序地調用本類成員屬性賦初值語句;
③     本類的構造方法。

Super()表示調用父類的構造方法。
Super()也和this一樣必須放在第一行。
This()用於調用本類的構造方法。
如果沒有定義構造方法,那麼就會調用父類的無參構造方法,即super()。

要養成良好的編程習慣:就是要加上默認的父類無參的構造方法。
思考:可是如果我們沒有定義無參的構造方法,而在程序中構造了有參的構造方法,那麼如果方法中沒有參數,那麼系統還會調用有參的構造方法麼?應該不會。
22.多態
多態:多態指的是編譯時類型變化,而運行時類型不變。
多態分兩種:
①     編譯時多態:編譯時動態重載;
②     運行時多態:指一個對象可以具有多個類型。

對象是客觀的,人對對象的認識是主觀的。
例:
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用於判定是否將前面的對象變量賦值後邊的類名。

Instanceof一般用於在強制類型轉換之前判定變量是否可以強制轉換。
24.static

靜態方法中不允許訪問類的非靜態成員,包括成員的變量和方法,因爲此時是通過類調用的,沒有對象的概念。 This.data是不可用的。

一般情況下,主方法是靜態方法,所以可調用靜態方法,主方法爲靜態方法是因爲它是整個軟件系統的入口,而進入入口時系統中沒有任何對象,只能使用類調用。

覆蓋不適用於靜態方法。

靜態方法不可被覆蓋。(允許在子類中定義同名靜態方法,但是沒有多態,嚴格的講,方法間沒有多態就不能稱爲覆蓋)

static修飾代碼塊時(注:此代碼塊要在此類的任何一個方法之外),那麼這個代碼塊在代碼被裝載進虛擬機生成對象的時候可被裝載一次,以後再也不執行了。

一般靜態代碼塊被用來初始化靜態成員。

Static通常用於Singleton 模式開發:

Singleton是一種設計模式,高於語法,可以保證一個類在整個系統中僅有一個對象。
25.final

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定義的方法,那麼在子類中繼承同一個方法。

如果一個方法前有修飾詞privatestatic,則系統會自動在前面加上final。即privatestatic方法默認均爲final方法。

注:final並不涉及繼承,繼承取決於類的修飾符是否爲privatedefaultprotected還是public。也就是說,是否繼承取決於這個方法對於子類是否可見。
final修飾基本數據類型表示該屬性不能被改寫,修飾引用數據類型表示該應用不能再指向其他對象,但對象的內容可以發生變化。
26.abstract

Abstract(抽象)可以修飾類、方法

Abstract雖然不能生成對象,但是可以聲明,作爲編譯時類型,但不能作爲運行時類型。

Finalabstract永遠不會同時出現。

注意比較:

private void print(){};此語句表示方法的空實現。

Abstract void print(); 此語句表示方法的抽象,無實現。

如果一個類中有一個抽象方法,那麼這個類一定爲一個抽象類。

反之,如果一個類爲抽象類,那麼其中可能有非抽象的方法。

如果讓一個非抽象類繼承一個含抽象方法的抽象類,則編譯時會發生錯誤。因爲當一個非抽象類繼承一個抽象方法的時候,本着只有一個類中有一個抽象方法,那麼這個類必須爲抽象類的原則。這個類必須爲抽象類,這與此類爲非抽象衝突,所以報錯。

所以子類的方法必須覆蓋父類的抽象方法。方法才能夠起作用。

Abstractstatic不能放在一起,否則便會出現錯誤。(這是因爲static不可被覆蓋,而abstract爲了生效必須被覆蓋。
27.interface
JAVA的核心概念:接口(interface)
與類相似,一個文件只能有一個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()。
28.String

字符串類爲 JAVA中的特殊類,String中爲 final類,一個字符串的值不可重複。因此在 JAVA VM(虛擬機)中有一個字符串池,專門用來存儲字符串。如果遇到 String a=”hello”時(注意沒有 NEW,不是創建新串),系統在字符串池中尋找是否有 ”hello”,此時字符串池中沒有”hello”,那麼系統將此字符串存到字符串池中,然後將 ”hello”在字符串池中的地址返回 a。如果系統再遇到String b=”hello”,此時系統可以在字符串池中找到  “hello”。則會把地址返回b,此時 ab 爲相同。

String a=”hello”;

System.out.println(a==”hello”);

系統的返回值爲 true

故如果要比較兩個字符串是否相同(而不是他們的地址是否相同)。可以對 a調用equal:

System.out.println(a.equal(b));

equal用來比較兩個對象中字符串的順序。

a.equal(b) ab 的值的比較。


注意下面程序:

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;

}

==”在任何時候都是比較地址,這種比較永遠不會被覆蓋。


以上過程爲實現 equals的標準過程。
29.Java序列化

當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換爲字節序列,即Java對象序列號,才能在網絡上傳送;接收方則需要把字節序列再恢復爲Java對象,即反序列化。

把Java對象轉換爲字節序列的過程稱爲對象的序列化

把字節序列恢復爲Java對象的過程稱爲對象的反序列化

對象的序列化主要有兩種用途:

1) 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;

2) 在網絡上傳送對象的字節序列。
30.內部類
封裝類:
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。

如果一個對象編譯時的類型是接口,那麼其運行的類型爲實現這個接口的類。
因匿名內部類無構造方法,所以其使用範圍非常的有限。
31Exception
Exception有兩個子類:Runtime exception(未檢查異常)
非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後跟的是例外類型。
32.斷言

斷言是一種調試工具(assert

其後跟的是布爾類型的表達式,如果表達式結果爲真不影響程序運行。如果爲假系統出現低級錯誤,在屏幕上出現assert信息。

Assert只是用於調試。在產品編譯完成後上線assert代碼就被刪除了。

 

方法的覆蓋中,如果子類的方法拋出的例外是父類方法拋出的例外的父類型,那麼編譯就會出錯:子類無法覆蓋父類。

結論:子類方法不可比父類方法拋出更多的例外。子類拋出的例外或者與父類拋出的例外一致,或者是父類拋出例外的子類型。或者子類型不拋出例外。

如果父類型無throws時,子類型也不允許出現throws。此時只能使用try catch

33.HashMap 
底層也是用數組,HashSet底層實際上也是 HashMapHashSet 類中有HashMap屬性(我們如何在 API中查屬性)。HashSet實際上爲 (key.null)類型的HashMap 。有key值而沒有 value值。

正因爲以上的原因, TreeSetTreeMap 的實現也有些類似的關係。


注意: TreeSetTreeMap 非常的消耗時間,因此很少使用。

HashSet VS TreeSetHashSet 非常的消耗空間, TreeSet因爲有排序功能,因此資源消耗非常的高,我們應該儘量少使用,而且最好不要重複使用。

基於以上原因,我們儘可能的運用 HashSet而不用TreeSet ,除非必須排序。

同理: HashMap  VS  TreeMap:一般使用HashMap ,排序的時候使用 TreeMap


HashMap VS Hashtable(注意在這裏table的第一個字母小寫)之間的區別有些類似於 ArrayListVector Hashtable是重量級的組件,在考慮併發的情況,對安全性要求比較高的時候使用。
34.hashcode

一致性

在 Java 應用程序執行期間,在對同一對象多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。

equals

如果根據 equals(Object) 方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用 hashCode 方法都必須生成相同的整數結果,注:這裏說的equals(Object) 方法是指Object類中未被子類重寫過的equals方法。
如果兩個hashCode()返回的結果相等,則兩個對象的equals方法不一定相等。

附加

如果根據equals(java.lang.Object)方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不一定生成不同的整數結果。但是,程序員應該意識到,爲不相等的對象生成不同整數結果可以提高哈希表的性能。

編輯本段重寫HashMap對象是根據其Key的hashCode來獲取對應的Value。

在重寫父類的equals方法時,也重寫hashcode方法,使相等的兩個對象獲取的HashCode也相等,這樣當此對象做Map類中的Key時,兩個equals爲true的對象其獲取的value都是同一個,比較符合實際。
1:Object類的hashCode.返回對象的內存地址經過處理後的結構,由於每個對象的內存地址都不一樣,所以哈希碼也不一樣。
2:String類的hashCode.根據String類包含的字符串的內容,根據一種特殊算法返回哈希碼,只要字符串內容相同,返回的哈希碼也相同。
3:Integer類,返回的哈希碼就是Integer對象裏所包含的那個整數的數值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。由此可見,2個一樣大小的Integer對象,返回的哈希碼也一樣。


35.io流
 在流中close()方法由程序員控制。因爲輸入輸出流已經超越了VM的邊界,所以有時可能無法回收資源。原則:凡是跨出虛擬機邊界的資源都要求程序員自己關閉,不要指望垃圾回收。以Stream結尾的類都是字節流。(非重點)管道流:也是一種節點流,用於給兩個線程交換數據。

PipedOutputStream

PipedInputStream

輸出流:connect(輸入流) 

RondomAccessFile類允許隨機訪問文件GetFilepoint()可以知道文件中的指針位置,使用seek()定位。Mode(“r”:隨機讀;”w”:隨機寫;”rw”:隨機讀寫)Io包的InputStreamread稱爲從字節流到字符流的橋轉換類。這個類可以設定字符轉換方式。

OutputStreamred:字符到字節

Bufferreadreadline() 使得字符輸入更加方便。

I/O流中,所有輸入方法都是阻塞方法。

Bufferwrite給輸出字符加緩衝,因爲它的方法很少,所以使用父類 printwrite,它可以使用字節流對象,而且方法很多。用流傳輸對象稱爲對象的序列化,但並不使所有的對象都可以進行序列化的。只有在實現類時必須實現一個接口:IO包下的Serializable(可序列化的)。此接口沒有任何的方法,這樣的接口稱爲標記接口。

Class Student implements Serializable

把對象通過流序列化到某一個持久性介質稱爲對象的可持久化。Transient用來修飾屬性。

 Transient int num;

表示當我們對屬性序列化時忽略這個屬性(即忽略不使之持久化)。

所有屬性必須都是可序列化的,特別是當有些屬性本身也是對象的時候,要尤其注意這一點。判斷是否一個屬性或對象可序列化: SerialverSerialver TestObjectTestObject 必須爲已經編譯)
36.toString()

toString方法是一個“自我描述"的方法,要輸出自我有用的信息,要重寫該方法。
37.SuppressWarnings
取消編譯時的警告
38.線程
一般用Runnable接口,不用Thread類,Runnable可以實現數據共享

39.靜態方法只能繼承,不能重寫
接口成員變量必須賦初值

40.float類型
共32位(不int相同),其中1位爲符號位, 指數8位, 尾數23位。需要強調的是float的精度是23位(即能精確表達23位的數,超過就被截叏了)。小數是以尾數長度來表示精確度的,比如pi=3.14,它的精度是2位,pi=3.1415,它的精度就爲4位。 比較有趣的是int的精度比float要大,因爲int的精度是31位,大於float。因爲int類型的範圍是(-2^31)~(2^31-1),而float的範圍是(-2^128)~(-2^128-1),所以記住: int類型的數據能表示的範圍比float類型小,int類型數據表示的精度比float大。 double類型能表示64位,其中1位符號位,11位指數,52位尾數.double精度比int精確,但是丌如long;double範圍進進大於long。 需要注意的是,浮點數的字面量 默認是double, D d 後綴是double, f F 是float。如下 圖-20所示會出現編譯錯諢,原理同int和long
字符類型是一個16位無符號整數, 是一個2迚制數,這個數值是一個字符的 unicode編碼值。

41. 取模的規律:取模的結果符號永遠與被除數的符號相同
int a = 5;
int b = -3;
int c = a % b;
被除數是5,那麼取模的結果是 2
int a = -5;
int b = 3;
int c = a % b;
被除數是-5,那麼取模的結果是-2

42.棧,
Java中所有的局部變量都是在棧內存中分配的(包括方法中聲明的變量、方法的參數) 。 
Java方法調用使用棧實現, 遞歸調用就是棧實現的。遞歸時候要按照遞歸深度分配全部臨時變量 , 棧開銷很大, 性能不好, 要注意不要超過棧的大小 , 幵且一定要給出結束條件 , 否則會造成棧溢出錯諢。
棧存儲方式會有風險,以這種"對柴火"的方式存儲數據會造成 棧溢出windows平臺下,JVM默認的棧空間爲64M字節,也可以通過優化參數修改,此處不做詳解。 
棧內存空間的存儲特點是後迕先出”,堆內存空間的存儲特點和棧丌同,類似於一盤散沙,隨處可以“堆放”



局部變量與堆對象空間分配

ü Java 局部變量和方法參數在棧中分配,大小是按照變量的類型分配

ü 對象在堆中分配,按照類中聲明屬性( 實例變量)分配空間 

ü 基本類型變量的空間大小:就是基本類型的空間大小,值是基本類型的值

ü 引用變量的值是一個對象的地址值,引用變量通過地址引用了一個堆對象

ü 引用類型變量的佔用空間大小和值管理是“透明的(丌可看見)”由Java系統管理:變量佔用空間以及值的管理,都是透明的 
this是局部變量,構造方法調用結束後和參數一樣消失 

43.java方法參數的傳遞規則:基於值的傳遞

ü Java方法參數傳遞只有一種方式,基於值的傳遞,是變量值的複製

ü 基本類型就是其中值的複製

ü 引用類型是引用值(地址)的複製 

44.靜態導入:(靜態方法調用時可省略掉靜態方法的類名)
import static +路徑名+類名+方法名或成員變量名;

 
45.局部變量使用前必須要聲明並賦初值;成員變量使用前必須要聲明,但可以不賦初值。 
 
引用類型是用在對象上的。一個對象可以被多個引用所指向,但同一時刻,每個引用只能指向唯一的一個對象。如果一個對象被多個引用所指向,那麼無論哪個引用對對象的屬性進行了修改,都會反映到其他的引用當中。 

46  new關鍵字在生成對象時完成了三件事情:

a) 爲對象開闢內存空間。

b) 調用類的構造方法。

c) 將生成的對象的地址返回。 
e) 不能顯式調用類的構造方法,構造方法通常是通過 new關鍵字隱式調用。 

47.構造器

ü 構造器丌能繼承!

ü 實例化子類,會遞歸分配所有父類的空間

ü 子類構造器一定調用父類構造器

ü 類一定有構造器(父類、子類) 

48.多態:父類型引用子類型,編譯期丌確定什麼類型(統一都是Question的),運行期才能確定

ü q和check()方法都是通過”對象的勱態綁定“ 實現的多態現象 

Java引用變量有兩種類型:一個 編譯期類型,一個 運行時類型。編譯時類型由該聲明該變量時使用的類型決定,運行時類型由實際賦給該變量的對象決定,如果編譯時類型和運行時類型丌一致,就會出現“多態”現象 

使用super()調用父類構造器,必須寫在子類構造器第一行

ü this() 必須寫在子類構造器第一行

ü 有super()就丌能有this(),兩者互斥 
this編譯時不存在,運行時纔出現 

如果父類沒有無參數構造器,就必須在子類中明確指定調用父類的有參數構造器!

ü 編程建議:所有的類都提供無參數構造器!減少繼承時候的麻煩 

理解Java中對象實例化過程是很重要的 ,實例化過程主要步驟如下: 第1步: 在創建類乊前,檢查類是否 加載(是將硬盤上的.class文件加載到內存中),如果沒有加 載就加載這個類,在這個類加載乊前要加載所有父類。 Java運行時採用的策略:懶惰式加載(按需加載):如果第一次用到就加載,只加載一 次。通過CLASSPATH指定的路徑尋找類文件(.class),加載以後是一個對象,類型是 Class。 第2步: 在內存堆中分配對象空間。遞歸分配所有父類和子類屬性空間。 達內 IT 培訓集團 33

屬性默認自勱初始化。自勱初始化爲“0”值。 第3步: 迚行屬性的賦值。 第4步: 遞歸調用父類構造器。(默認調用父類無參數構造器!) 第5步: 調用本類構造器。 


49.方法的覆蓋是由方法動態綁定實現的
是Java虛擬機運行時候確定執行哪個對象哪個方法,java最終執行子類的方法 
在實際項目開發中,原則上丌允許使用final類!
Spring, Hibernate,Struts 2, 這些框架使用了"動態繼承代理"技術,使用final的類會影響"動態代理技術" 的實現. 
final修飾屬性表示“丌能改”,static修飾屬性表示屬於類的“僅此一份”,注意區分
 知識點:
 final的局部變量,只能初始化丌能改
 final的方法參數,丌能改
 final的引用,引用指向丌能改,但是對象的屬性可以改

比較引用值是否相等: “ ==

u 比較對象的內容是否相等: xxx.equals()方法 
默認的hashCode()值是當前堆對象地址轉換的一個整數,這個整數 不是內存地址 ! 
50. 關於繼承的注意事項

a) 構造方法不能被繼承

b) 方法和屬性可以被繼承

c) 子類的構造方法隱式地調用父類的不帶參數的構造方法

d) 當父類沒有不帶參數的構造方法時,子類需要使用 super來顯


式地調用父類的構造方法, super指的是對父類的引用

e) super關鍵字必須是構造方法中的第一行語句。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章