1.編程語言中的數據類型
2.靜態與動態數據類型
3.類型檢查
4.易變性和不變性
5.快照圖
6.複雜的數據類型:數組和集合
7.有用的不可變類型
8.空引用
9.總結java
類型和變量程序員
類型是一組值,以及能夠對這些值執行的操做。
變量:存儲一個特定類型值的命名位置編程
Java中的類型數組
Java有幾種基本類型,例如:安全
Java也有對象類型,例如:數據結構
按照Java約定,基本類型是小寫字母,而對象類型以大寫字母開頭。app
對象類型的層次結構編程語言
根是Object(全部非基元都是對象)ide
class Guitar extends Instrument { ... }
若是省略了子句,則默認爲Object
一個類是其全部超類的一個實例函數
包裝的基本類型
用於原始類型的不變容器
– Boolean, Integer, Short, Long, Character, Float, Double
典型用例是集合
除非你必須使用包裝的基本類型!
語言自動包裝和自動解包裝
運算符
運算符:執行簡單計算的符號
操做順序:遵循標準的數學規則
字符串鏈接(+)
操做
操做是獲取輸入和生成輸出的函數(有時會自行更改值)。
重載操做符/操做
一些操做被重載,由於相同的操做名稱用於不一樣的類型
對於Java中的數字基本數據類型,算術運算符+, - ,*,/會嚴重重載。
方法也能夠重載。 大多數編程語言都有必定程度的重載。
(將在3.3節OOP中討論)
靜態輸入與動態輸入
Java是一種靜態類型的語言。
在像Python這樣的動態類型語言中,這種檢查被推遲到運行時(程序運行時)。
3.類型檢查
靜態檢查和動態檢查
一種語言能夠提供的三種自動檢查:
不用說,靜態捕獲一個bug比動態捕獲它要好,動態捕獲它比根本沒有捕獲它要好。
靜態檢查
靜態檢查意味着在編譯時檢查錯誤。
錯誤是編程的禍根。
靜態類型能夠防止大量的錯誤感染程序:準確地說,經過對錯誤類型的參數應用操做而致使的錯誤。
若是你寫了一行代碼,如:「5」*「6」,它試圖乘以兩個字符串,那麼靜態類型在編程時會捕獲這個錯誤,而不是等到執行過程當中到達該行。
動態檢查
非法的參數值。 例如,當y實際上爲零時,整數表達式x / y只是錯誤的; 不然它將運行。 因此在這個表達式中,除零不是一個靜態錯誤,而是一個動態錯誤。
靜態與動態檢查
靜態檢查每每是關於類型的,與變量具備的特定值無關的錯誤。
相比之下,動態檢查每每是由特定值引發的錯誤。
原始數據類型不是真正的數字
Java中的一個陷阱 - 以及其餘許多編程語言 - 就是它的原始數字類型具備不像咱們習慣的整數和實數那樣的特例。
結果,真正應該動態檢查的一些錯誤根本不被檢查。
4可變性和不變性
賦值
使用「=」給變量賦值
賦值能夠和變量聲明結合使用
更改變量或其值
改變變量和改變數值有什麼區別?
變化是必要的罪惡。
好的程序員能夠避免變化的事情,由於它們可能會意外地改變。
不變性
不變性是一個主要的設計原則。
不可變類型是一種類型,它們的值一旦建立就永遠不會改變。
Java也爲咱們提供了不可變的引用:一次賦值且永不從新賦值的變量。
若是Java編譯器不肯定最終變量只會在運行時分配一次,那麼它將產生編譯器錯誤。 因此最終給你靜態檢查不可變引用。
最好使用final來聲明方法的參數和儘量多的局部變量。
像變量的類型同樣,這些聲明是重要的文檔,對代碼讀者頗有用,並由編譯器進行靜態檢查。
注意:
可變性和不變性
對象是不可變的:一旦建立,它們老是表示相同的值。
對象是可變的:它們具備改變對象值的方法。
字符串做爲不可變類型
字符串是不可變類型的一個例子。
一個String對象老是表示相同的字符串。
因爲String是不可變的,一旦建立,String對象始終具備相同的值。
要將某些內容添加到字符串的末尾,您必須建立一個新的String對象:
StringBuilder做爲一個可變類型
StringBuilder是一個可變類型的例子。
它具備刪除字符串部分,插入或替換字符等的方法
該類具備更改對象值的方法,而不只僅是返回新值:
可變類型的優勢
5快照圖做爲Code-level,Run-time,Moment視圖
快照圖
爲了理解微妙的問題,咱們能夠繪製運行時發生的事情的圖片。
快照圖在運行時表示程序的內部狀態 - 其堆棧(正在進行的方法及其局部變量)及其堆(當前存在的對象)。
爲何咱們使用快照圖表?
可變值與從新分配變量
快照圖給咱們提供了一種可視化更改變量和更改值之間區別的方法:
快照圖中的基本類型和對象類型
基本類型的值
對象類型的值
從新分配和不可變的值
例如,若是咱們有一個字符串變量s,咱們能夠將其從「a」值從新分配給「ab」
String s =「a」;
s = s +「b」;
字符串是不可變類型的一個例子,一種類型的值一旦建立就永遠不會改變。
不變對象(它們的設計者打算始終表示相同的值)在快照圖中用雙邊框表示,就像咱們圖中的String對象同樣。
可變的值
相比之下,StringBuilder(一個內置的Java類)是一個可變對象,表示一串字符,而且它具備更改對象值的方法:
StringBuilder sb = new StringBuilder(「a」);
sb.append( 「B」);
這兩個快照圖看起來很是不一樣,這是很好的:可變性和不可變性之間的差別將在使代碼免受bug影響方面發揮重要做用。
不變的引用
Java也爲咱們提供了不可變的引用:一次賦值且永不從新賦值的變量。 爲了使引用不可變,用關鍵字final聲明它:
final int n = 5;
若是Java編譯器不肯定最終變量只會在運行時分配一次,那麼它將產生編譯器錯誤。 因此最終給出了對不可變引用的靜態檢查。
在快照圖中,不可變引用(final)由雙箭頭表示。
6複雜的數據類型:數組和集合
數組
數組是另外一個類型T的固定長度序列。例如,下面是如何聲明一個數組變量並構造一個數組值以分配給它:
int [] a = new int [100];
int []數組類型包含全部可能的數組值,可是一旦建立了特定的數組值,永遠不會改變其長度。
數組類型的操做包括:
列表
咱們使用List類型來代替固定長度的數組。
列表是另外一個類型T的可變長度序列。 List <Integer> list = new ArrayList <Integer>();
其部分操做:
注1:列表是一個接口
注2:列表中的成員必須是一個對象。
集合
Set是零個或多個惟一對象的無序集合。
一個對象不能屢次出如今一個集合中。 要麼它在或它不在。
Set是一個抽象接口
地圖
地圖相似於字典(key)
地圖是一個抽象界面
聲明List,Set和Map變量
使用Java集合,咱們能夠限制集合中包含的對象的類型。
當咱們添加一個項目時,編譯器能夠執行靜態檢查,以確保咱們只添加適當類型的項目。
而後,當咱們取出一個對象時,咱們保證它的類型將是咱們所指望的。
建立List,Set和Map變量
Java有助於區分
List,Set和Map都是接口:
List,Set和Map的實現:
迭代器是一個可變類型的迭代器
迭代器是一個對象,它遍歷一組元素並逐個返回元素。
當你使用for(...:...)循環遍歷一個List或數組時,迭代器在Java中被使用。
迭代器有兩種方法:
7有用的不可變類型
原始類型和原始包裝都是不可變的。
不要使用可變日期,根據您須要的計時粒度,使用java.time或java.time.ZonedDateTime中適當的不可變類型。
Java的集合類型(List,Set,Map)的一般實現都是可變的:ArrayList,HashMap等
Collections實用程序類具備獲取這些可變集合的不可修改視圖的方法:
可變數據類型的不可變包裝
Java集合類提供了一個有趣的折衷:不可變的包裝器。
缺點是你在運行時得到了不變性,但不是在編譯時。
不可修改的包裝
不可修改的包裝器經過攔截全部修改集合並拋出UnsupportedOperationException的操做來取消修改集合的能力。
不可修改的包裝有兩個主要用途,以下所示:
8空引用
空引用
在Java中,對對象和數組的引用也能夠採用特殊值Null,這意味着引用不指向對象。 空值是Java類型系統中的一個不幸的漏洞。
基元不能爲null,編譯器會拒絕這種帶有靜態錯誤的嘗試:
int size = null; //非法
能夠將null分配給任何非原始變量,而且編譯器在編譯時高興地接受這些代碼。 可是你會在運行時遇到錯誤,由於你不能調用任何方法或者使用帶有這些引用之一的任何字段(拋出NullPointerExceptions):
String name = null;
name.length();
int [] points = null;
points.length;
null與空字符串「」或空數組不一樣。
空引用
非基元和像List這樣的集合的數組多是非空的,但包含null做爲值
只要有人試圖使用集合的內容,這些空值就可能致使錯誤。
空值是麻煩和不安全的,因此你最好建議將它們從你的設計詞彙表中刪除。
空值在參數和返回值中被隱式禁止。
來自Guava(Google)
不當心使用null會致使各類各樣的錯誤。
研究谷歌代碼庫,咱們發現像95%的集合不該該有任何空值,而且讓這些快速失敗而不是默默接受空值會對開發人員有所幫助。
另外,null很不明確。
不多有人明白空返回值應該是什麼意思 - 例如,Map.get(key)能夠返回null,由於map中的值爲null,或者該值不在map中。 空可能意味着失敗,可能意味着成功,幾乎意味着任何事情。
使用除null以外的其餘內容能夠明確您的意思。
總結
靜態類型檢查:
可變性對於性能和便利性頗有用,但它也會經過要求使用對象的代碼在全範圍內表現良好而形成bug的風險,這極大地增長了咱們必須作的推理和測試,以確保其正確性。
確保你瞭解不可變對象(如String)和不可變引用(如final變量)之間的區別。
快照圖能夠幫助理解。
關鍵的設計原則是不變性:儘量使用不可變對象和不可變引用。