【讀】Java核心技術卷1
看到這本書時,我的內心是崩潰的,卷1就700多頁,但是這本書是很多前輩所推薦的,想必其中必有精華所在,硬著頭皮上吧。
如何閱讀本書
- 拿到書的第一眼肯定去看目錄,大概瞭解一下,各個章節所講內容。
- 為表對作者的尊重,快讀掃讀了,譯者序、前言和致謝。
- 通過目錄瞭解到,第1,2章所講概述和環境搭建,對於我來說沒有價值,選擇忽略。
- 第10,11,12,13章所講Java圖形介面相關,當今這方面幾乎很少使用,選擇忽略。
- 由於並不是Java新手,所以我將選擇對我有益的知識點進行記錄。
第三章 Java的基本程式設計結構
長整型
long a = 3.14L 這裡注意要用大寫的L作為字尾,因為小寫 l 有時很像數字 1
浮點型
- 單精度型別表示:float a = 3.14F 或 3.14f
- 雙精度型別的表示:double b = 3.14D 或 3.14d
注意:當浮點型數字沒有後綴時(如:3.14),預設為double型別。另外浮點數值不適用於無法接受舍入誤差的金融計算中,如 2.0 - 1.1 結果是 0.89999999999999,為更精確的計算,可以使用BigDecimal類。
有三個特殊的浮點型數值:
- 正無窮大
- 負無窮大
- NaN (不是一個數字)
正整數除以0的結果正無窮大(如:3/0.0 結果為Infinity),Infinity表示無窮大的概念,0.0並不是真正意義上的0,它只是非常接近0而已。
,0/0或者負數的平方根結果為NaN.(如:0.0/0.0 ,Math.sqrt(-3)結果為 NaN ),對於所有沒有良好的數字定義的浮點計算,例如0.0/0.0,或者對負數求平方根其值都是它.
結合賦值和運算子
x = x + 4
簡寫: x += 4
注意: 如果運算子得到一個值,其型別與左側運算元型別不同,,就會發生強制型別轉換,如 int x = 2 ; x += 3.14 ; 這相當於 x = (int)(x + 3.14)
自增自減運算子
java中借鑑了C和C++的做法,提供了自增自減運算子:n + + 將當前值加1
這種運算子有兩種形式:運算子作為字首和運算子作為字尾。例:
int m = 7 ; int n = 7 ; int a = 2 * ++m;//a=16,m=8 int b = 2 * n++;//b=14,n=8
字首形式先完成加1,字尾形式會使用原來的值,再加1。
不建議在表示式中使用++,因為這樣的程式碼很容易讓人困惑,而且會帶來煩人的bug。
&&和& 與 ||和|
&&表示邏輯“與”,||表示邏輯“或”。
這兩個運算子是按照“短路”方式來求值的:如果第一個運算元已經能夠確定表示式的值,第二個運算元就不會計算了。如:
exp1 && exp2 ,當exp1為flase時,那麼exp2就不會執行了。 exp1 || exp2 ,當exp1為true時,那麼exp2就不會執行了。
&和| 運算子不採用“短路”方式求值,所以不論第一個運算元是否確定整個表示式的值,兩個運算元都會被計算。
字串
- 檢測是否相等
一定要用equals()函式,它是判斷兩個字串內容是否相等,而 == 是判斷兩個字串是否在同一個位置上。如果 == 相等,那麼equals一定相等,反之不然。
- 空串和Null
""是一個Java物件,有自己的串長度(0)和內容(空),當為Null時,表示目前沒有任何物件與該變數關聯。
檢查一個字串既不是null也不是空串:
if(str != null && str.length() != 0)
要先檢查不為null,因為為null時無法呼叫length()函式。
多重選擇:switch
switch(x){ case x1 : *** break; case x2 : *** break; }
其中x可以為char,byte,short,int型別,到Java SE 7開始,可以是String型別的。
一般不建議使用switch語句,因為break語句的忘記容易導致問題。
命令列引數
學習Java你一定知道下面程式碼:
public class Massage{ public static void main(String[] args){ System.out.println(args[0]); System.out.println(args[1]); } }
當你在命令列變異執行這個類時:java Massage -hello world
列印結果:
hello world
第四章 物件與類
類之間的關係
- 依賴(uses-a) A類方法操縱B類物件,叫做一個類依賴另一個類。
- 聚合(has-a) A類的物件包含B類的物件。
- 繼承(is-a) A類繼承B類。
我們應該儘量減少相互依賴的類存在,如果A類不知道B類,就不會關係B類的變化,這樣B類無論怎麼變化都不會導致A的bug,軟體工程上叫做:讓類之間的耦合度最小。
Java 8中新增LocalDate類
Date是一個用來表示時間點的Date類,LocalDate用來表示大家熟悉的日曆表示法。
1.Date和SimpleDateFormatter都不是執行緒安全的。
2.Date對日期的計算方式繁瑣,月份從0開始。
建立一個物件可以通過以下幾個方式:
LocalDate local1 = LocalDate.now(); LocalDate local2 = LocalDate.of(2017,10,30);
LocalDate並不包含時間,你可以通過下面獲取年月日:
int year = local2.getYear(); int month = local2.getMonthValue(); int day = local2.getDayOfMonth();
當然LocalDate也提供了日期的增減:
local2.pulsDays(100); local2.minusDays(100);
更多方法檢視API,這裡不做詳細表述。
final例項域
將例項域定義為final,構建物件時必須初始化這個例項域,後面的操作中不能夠再對它進行修改。如:
public class Employee{ private final String name; …… }
這個name屬性沒有setName方法。final修飾符大都應用於基本資料型別或不可變的類或物件。如果類中每個方法都不會改變其物件,那麼這個類就是不可變類,如String類。
對於可變的類使用final修飾,會對別人造成混亂。如:
private final StringBuilder sb;
在Employee構造方法中進行初始化
public Employee(){ sb = new StringBuilder(); }
final關鍵詞只是表示儲存在sb變數中的物件應用不會再指向其他StringBuilder物件,不過這個物件可以更改:
public void giveGoldStar(){ sb.append( LocalDate.now() + ": Gold star!"); }
靜態域 static
public class Employee{ private static int sid = 1001; private int id ; …… }
static 修飾的常量,是面向類的,即無論存在多少Employee物件,sid只存在一個,所有物件將共享一個sid,但id卻和物件同存在,多少個物件就有多少個id。(static 修飾後,它屬於類,而不屬於任何物件)
靜態工廠方法
類似LocalDate.now和LocalDate.of都是使用靜態工廠方法來構造物件。
NumberFormat currenyFormatter = NumberFormat.getCurrencyInstance(); NumberFormat percentFormatter = NumberFormat.getPercentInstance(); double x = 0.1; System.out.println(currenyFormatter.format(x)); //輸出 $0.10 System.out.println(percentFormatter.format(x)); //輸出 10%
為什麼不利用構造方法來完成這些操作呢?原因:
- 無法命名構造器,這裡希望得到的貨幣例項和百分比例項採用不同的名字。
- 當使用構造器時,無法改變所構造的物件型別,而Factory方法將返回一個DecimalFormat類物件,這是NumberFormat的子類。
方法引數
方法引數共有兩種型別:
- 基本資料型別
- 物件型別
- 一個方法不可能修改一個基本資料型別的引數,如:
double x = 10; harry.raiseSalary(x);
中不論加薪方法具體怎麼實現,但x值始終不變。
- 物件作為引數其實是物件引用的拷貝,他們指向同一個物件。
public void swap(Employee x,Employee y){ Employee temp = x; x = y; y = temp; } Employee a = new Employee("zhang"); Employee b = new Employee("wang"); swap(a,b); //現在x指向wang,y指向zhang System.out.println(a.toString()+"--"+b.toString());
最後你會發現a依然是zhang,b依然是wang,因為形參x,y在執行完後被丟棄了,原來的a,b依然指向之前的的物件。
總結:
- java對物件採用的不是引用呼叫,實際上,物件引用是按值傳遞的。
- 一個方法不能修改一個基本資料型別(數值型和布林型)
- 一個方法可以改變一個物件的狀態(屬性……)
- 一個方法不能讓一個物件引數引用新的物件
無參建構函式
當一個類沒有提供建構函式時,系統會為這個類提供一個預設的無參建構函式,但當你提供了有參的建構函式時,系統是不會提供無參建構函式的,所以當你要呼叫無參建構函式時,主動提供無參建構函式或不提供任何建構函式。
類設計技巧
- 一定保證資料的私有性
- 一定對資料初始化
- 不要在類中使用過多的基本型別
- 將職責過多的類進行分解
- 類名和方法名要能體現他們的職責
- 優先使用不可變類
類不可變,就可以安全地在多個執行緒間共享其物件。
第五章 繼承
父類和子類
- 將通用方法放在父類中,而將具有特殊用途的方法放在子類中。
- 關鍵字this的兩種用法:一是引用本類成員變數,二是呼叫本類其他建構函式。
- 關鍵字super兩種用法:一是應用父類成員變數,二是呼叫父類建構函式。不過兩者呼叫建構函式時,呼叫語句必須放在建構函式第一行。