在循環中檢測2個浮點數是否相等,要格外小心,由於舍入誤差,最終可能得不到精確的值。
類名:字母開頭,後跟字母或數字的任意組合(不能使用保留字)【通常以大寫字母開頭】
定義枚舉類:
enum Size{S,M,L,XL}
Size s1 = Size.S;
Size s2 = Size.L;
一個字符串與一個非字符串憑藉,後者被轉換成字符串,Java對字符串中的代碼單元和代碼點從0開始。
equalsIgnoreCase()方法,不區分大小寫
定義類,讀取密碼的時候,使用Console類
運算符 | 描述 |
---|---|
>> |
高位補符號 |
>>> |
高位補0 |
類型轉換:
轉換方式 | 描述 |
---|---|
強制類型轉換 | double->float->long->int |
自動轉換 | int->long->float->double |
2個數值進行二元操作,先將2個操作數轉換爲同一種類型,採用自動轉換方式
switch語句:
int choice = 0;
switch (choice){
case 1:
do something
break;
case 2:
do something
break;
default:
do something
break;
}
case標籤可以是char,byte,short,int,枚舉常量,字符串字面量
關於break語句:
帶標籤的break語句,標籤必須放在希望跳出的最外層循環之前,且必須緊跟冒號
here:
while (true){
do something
break here;
}
//跳出後在這裏繼續執行
標籤可以放在任何位置,如if語句外等。
java.math包:
類 | 描述 |
---|---|
BigDecimal | 人員精度的浮點數運算 |
BigInteger | 任意精度的整數運算 |
數組:
數組類型 | 初始化值 |
---|---|
數字數組 | 0 |
boolean數組 | false |
對象數組 | null |
數值型數組排序,可以使用Arrays.sort(),這是優化的快速排序
一旦數組創建,就不能在改變它的大小了
初始化匿名數組的方式:new int[]{1,2,3,4}
不規則數組:每一行的個數都不同,要單獨創建每一行的數組
數組的拷貝:
- 淺拷貝(引用),2個變量將引用同一個數組
- 深拷貝(內容),
int[] a = Arrays.copyof(b,b.length);
b.length 是新數組的長度。通常深拷貝用來增加數組的大小
對象的拷貝:
- 淺拷貝,還是指向同一段空間
- 深拷貝:克隆,但是默認的對象克隆還是淺拷貝,並沒有克隆包含在對象中的內部對象
不要編寫返回引用可變對象的訪問器方法(這是淺拷貝,原來的對象會跟這返回的對象一起改變)
如果需要返回一個可變對象的引用,應該首先對它進行克隆(對象包含可變對象,必須進行深拷貝)
如果需要返回一個可變數據域的拷貝,應使用clone
對象
- 對用戶公開特定的功能部分
- 隱藏實現部分
final實例域必須在構造時初始化,後面的操作中不能再修改
構造一個final的數組,數組的引用不可變,但數組中的值可變:
final int[] a = new int[1];
//a[0]的值可以改變
封裝:
將數據和行爲組合在一個包中並對對象的使用隱藏了數據的實現方式
關鍵:絕對不能讓類中的方法直接方法訪問其他類的實例域
Tips:如果不經過方法調用就能夠改變對象狀態,說明封裝性被破壞了
類間關係
- 依賴(uses-a):一個類的方法操作另一個類的對象,這個類依賴另一個類
- 聚合(has-a):類A的對象包含類B的對象
- 繼承(is-a):特殊與一般的關係
繼承的子類具有父類的全部屬性和方法
對象變量和對象的區別:一個對象變量(存儲的只是引用)並沒有實際包含一個對象,而僅僅引用一個對象
文件名必須與public類的名字相匹配,在一個源文件中只能有一個公有類,但可以有任意數目的非公有類
參數傳遞
Java程序設計語言總是採用按值調用,即方法得到的是所以參數的一個拷貝
方法不能修改傳遞給它的任何參數變量的內容
編譯器如何確定重載的方法?重載解析
通過各個方法各處的參數類型與特定方法調用所使用的值類型匹配
方法的簽名:
- 方法名
- 參數類型
僅當類沒有提供任何構造器,系統纔會提供一個默認的構造器(啥也沒有的構造器,哈哈哈哈),如果類中提供了至少一個構造器,但沒提供午餐的構造器,則在構造新對象時,如果沒有提供參數就會被認爲是不合法的。
類在第一次加載的時候,會對靜態域進行初始化。所有的靜態初始化語句和靜態初始化塊都依照類定義的順序執行
import 導入靜態方法和靜態域的功能:
import static java.lang.System.*;
public class StaticImport {
public static void main(String[] args) {
out.println("Hello!");//這樣就不需要使用類名進行靜態方法的調用了
exit(0);//這樣就不需要使用類名進行靜態方法的調用了
}
}
關於javadoc(/** 後內內容),它會從下面的這幾個特性中抽取信息:
- 包
- 公有類和接口
- 共有的和受保護的構造器和方法
- 共有的和受保護的域
應該爲上面這幾個部分寫註釋,註釋應該放在所描述的特性前面
自定義類設計技巧
- 數據私有
- 數據初始化
- 不要在類中使用過多的基本類型
- 不是所有的域都要獨立的域訪問器和更改器
- 將職責過多的類分解
- 類名和方法名能夠體現它們的職責
繼承
- 繼承已存在的類就是複用這些類的方法和數據域,在此基礎上添加新的方法和域
- 在通過擴展超類定義子類的時候,僅需要指出子類與超類的不同之處
子類不能訪問父類的私有域,所以必須在父類的構造器對這部分私有域進行初始化
- 使用super調用構造器的語句必須是子類構造器的第一句、
- 如果子類構造器沒有顯式調用超類構造器,則自動調用超類默認的無參構造器
- 如果超類沒有無參構造器,並且在子類的構造器中沒有顯式調用超類的其他構造器,則編譯器會報錯
this & super
名稱 | 描述 |
---|---|
this | 隱式參數、調用該類其他的構造器 |
super | 調用超類方法,調用超類構造器 |
多態
一個對象變量可以指示多種實際類型的現象稱爲多態
在運行時能夠自動地選擇調用哪個方法的現象稱爲動態綁定:
- 獲取所有可訪問的同名方法
- 重載解析不確定的方法
調用的方法用來於隱式參數的實際類型,並在運行時實現動態綁定
靜態綁定:private static final 的方法或構造器, 編譯器可以準確的調用
如果一個方法沒有被覆蓋並且很短,編譯器可以優化爲內聯,例如:e.getName()
被優化爲e.name
域
置換法則:程序中出現超類的任何地方都可以用子類對象置換
在Java中對象變量是多態的,父類變量可以引用父類對象也可以引用任何一個子類對象,不能將父類對象的引用賦值給子類
在Java中,每個對象變量都屬於一個類型,類型描述了這個變量所引用的以及能夠引用的對象類型
對象進行類型轉換的唯一原因:暫時忽視對象的實際類型使用對象的全部功能
- 對象進行類型轉換隻能在繼承層次內進行類型的轉換(即父類轉換爲子類)
- 在轉換前使用instanceof進行檢查
對象中的equals方法具有如下特性:
- 自反性
- 對稱性
- 傳遞性
- 一致性
- 對於任意非空引用x,x.equals(null)爲false
基本類型和包裝類
所有基本類型都有一個與之對應的包裝類(包裝器)
Number->(Integer、Long、Float、Double、Short、Byte)
Void包裝類型是什麼鬼,之後研究一下
對象的包裝器類時不可變的,一旦構造了包裝器,就不允許更改包裝器在其中的值,包裝器類是final,不能定義它們的子類
操作 | 內部實現 |
---|---|
自動裝箱 | list.add(s); ==> list.add(Integer.valueof(s)); |
自動拆箱 | int n = list.get(i); ==> int n = list.get(i).intValue(); |
在算術表達式中也能夠自動裝箱/拆箱
參數數量可變的方法:
public PrintStream printf(String fmt, Object... args){
return format(fmt,args);
}
其中Object… args,表示Object[]數組,如果調用的對象提供的是整型數組或基本類型的值,自動裝修功能把它轉換成對象
運行將一個數組傳遞給可變參數方法的最後一個參數
自定義參數可變的方法:
public double max(double... values){
do something
return
}
枚舉
枚舉類型的實例固定,不構造新對象,在比較2個枚舉類型時,永遠不需要調用equals方法,直接使用“==”
枚舉類型定義如下:
public enum classname {enmuA,enumB};
在枚舉類型中可定義構造器方法和域,如下
private enum Size {
SMALL("S"),MEDIUM("M"), LARGE("L"), EXTRA_LARGE("Xl");
private String abbreviation;
private Size(String abbreviation){
this.abbreviation = abbreviation;
}
public String getAbbreviation(){
return abbreviation;
}
}
內部類
- 接口:主要用來描述具體數目功能,而並不提供每個功能具體的實現
接口中的域自動爲public static final
接口中的方法自動爲public不必提供關鍵字
接口中能定義常量,但不能有實例域
不能實現方法,只能定義
在實現接口時,必須把方法聲明爲public,接口不是類,不能用new運算符實例化,但可以聲明接口類型的變量(這和抽象類很像)
- 內部類:定義在另一個類的內部,其中的方法可以訪問包含它們的外部類
- 代理:實現任意接口的對象
內部類是定義在另一個類中的類:
- 內部類方法可以訪問該類定義所在的作用域中的數據,包括私有數據
- 內部類可以對同一個包中的其他類隱藏起來
- 當想要定義一個回調函數且不想編寫大量代碼,使用匿名內部類比較便捷
內部類即可以訪問自身的數據域也可以訪問創建他們的外圍類對象的數據域
內部類對象總有一個隱式引用它指向了創建它的外圍類對象,這個引用在內部類的定義中是不可見的
外圍類的引用在構造器中設置,編譯器修改了所有內部類的構造器添加一個外圍引用的參數
編譯器爲類生成一個默認的構造器:
public Inner(Outer out){
Outer = out;//Outer不是Java的關鍵字,它相當於OuterClass.this
}
- 將內部類聲明爲privated這樣只有外圍類才能夠構造內部類對象
- 只有內部類可以是私有的,常規類只可以具有包可見性或公有可見性
- 在外圍類的作用域之外,引用內部類:
OuterClass.InnerClass
在方法中定義局部內部類:
- 局部類不能用public 或private訪問說明符聲明,它的作用域被限定在聲明這個局部類的塊中
- 局部類有宇哥優勢可以對外界世界完全隱藏起來,除了該方法沒有任何方法直到該類存在
- 與其他內部類相比,局部類的方法只能引用定義爲final 的局部變量
靜態內部類:
- 使用內部類只是爲了 把一個類隱藏在另一個類的內部,並不需要內部類引用外圍類對象,此時可以將內部類聲明爲static,以便取消產生的引用
- 只有內部類可以聲明爲static