用引用操縱對象:java
在Java中一切都被視爲對象,所以能夠採用單一固定的語法;c++
儘管一切都被看做對象,可是操縱的標識符其實是對象的一個「引用」。程序員
舉例:能夠想象成 用遙控器(引用)來操縱電視機(對象)。只要握住這個遙控器,就能保持與電視機的鏈接。當有人想改變頻道或者減少音量時,實際操控的是遙控器(引用),再由遙控器來調控電視機(對象)。若是想在房間裏四處走走,同時仍能調控電視機,那麼只須要攜帶遙控器(引用)而不是電視機(對象)。數據庫
你擁有一個引用,並不必定須要有一個對象與它關聯數組
也就是說,即便沒有電視機,遙控器亦可獨立存在。安全
常見錯誤(注意):對建立的引用,沒有關聯對象的狀況下;向引用發送一個消息,就會返回一個運行時錯誤。函數
必須由你建立全部對象:spa
Java怎麼建立對象;設計
String s = new String("");指針
new關鍵字的意思是「給我一個新對象」;
存儲到什麼地方?
程序運行時,對象是怎麼進行放置安排的呢?特別是內存是怎麼分配的呢?對於這些方面的瞭解會對你有很大的幫助。有五種不一樣的地方能夠存儲數據:
1)寄存器。
這是最快的存儲區,由於它位於不一樣於其餘存儲區的地方--處理器內部。可是寄存器的數量極其有限,因此寄存器根據需求進行分配。你不能直接控制,也不能在程序中感受到寄存器存在的任何痕跡(看完我來個草,告訴我幹嗎!!)。
2)堆棧。
位於通用RAM(隨機訪問存儲器)中,但經過堆棧指針能夠從處理器哪裏得到直接支持。堆棧指針若向下移動,則分配新的內存;若向上移動,則釋放那些內存。這是一種快速有效的分配存儲方法,僅次於寄存器。建立程序時,Java系統必須知道存儲在堆棧內全部項的確切生命週期,以便上下移動堆棧指針。這一約束限制了程序的靈活性,因此雖然某些Java數據存儲與堆棧中--特別是對象引用,可是Java對象並不存儲與其中。
3)堆。
一種通用的內存池(也位於RAM區),用於存放全部的Java對象。堆不一樣於堆棧的好處是:編譯器不須要知道存儲的數據在堆裏存活多長時間。所以,在堆裏分配存儲有很大的靈活性。當須要一個新對象時,只須要new寫一行簡單的代碼,當執行這行代碼時,會自動在堆裏進行存儲分配。固然,爲這種靈活性必需要付出相應的代價:用堆進行存儲分配和清理可能比用堆棧進行存儲分配須要更多的時間。
4)常量存儲。
常量值一般直接存放在程序代碼內部,這樣作是安全的,由於它們永遠不會被改變。有時,在嵌入式系統中,常量自己會和其餘部分隔離開,因此在這種狀況下,能夠選擇將其存放在ROM(只讀存儲器)中。
5)非RAM存儲。
若是數據徹底存活於程序以外,那麼它能夠不受程序的任何控制,在程序沒有運行時也能夠存在。其中兩個基本的例子是流對象和持久化對象。在流對象中,對象轉化成字節流,一般被髮送給另外一臺機器。在「持久化對象「中,對象被存放於磁盤上,所以,即便程序終止,它們仍能夠保持本身的狀態。這種存儲方式的技巧在於:把對象轉化成能夠存放在其餘媒介上的實物,在須要時,可恢復成常規的、基於RAM的對象。
Java提供了對輕量級持久化的支持。而諸如JDBC和Hibernate這樣的機制提供了更加複雜的對在數據庫中存儲和讀取對象信息的支持。
特例:基本類型
1)特殊對待緣由:new將對象存儲在「堆」裏,故用new建立一個對象----特別是小的、簡單的變量,每每不是頗有效。
2)對於這些類型,java採起了與C和C++相同的方法。也就是說,不用new來建立變量,而是建立一個並不是是引用的「自動」變量。這個變量直接存儲「值」,並置於堆棧中,所以更加高效。
3)Java對基本類型的處理:Java要肯定每種基本類型所佔存儲空間的大小。它們的大小並不像其餘大多數語言那樣隨機器硬件結構的變化而變化。這種所佔存儲空間大小的不變性是Java程序比用其它大多數語言編寫的程序更具可移植性的緣由之一。
4)基本類型都具備包裝器類。(存在緣由?)
數組:
幾乎全部程序語言都支持數組。在C和C++裏使用數組是很危險的,由於C和C++中的數組及時內存塊。若是一個程序要訪問氣自身內存塊以外的數組,或在數組初始化前使用內存(程序中常見的錯誤),都會產生難以預料的後果。
java不一樣:
java主要目標之一是安全性,因此許多在C和C++裏困擾程序員的問題在java裏不會再出現。java確保數組會被初始化,並且不能在它的範圍以外被訪問。這種範圍檢查,是以每一個數組上少許的內存開銷及運行時的下標檢查爲代價的。
當建立一個數組對象時,實際上就是建立了一個引用數組,而且每一個引用都會自動被初始化爲一個特定值,該值擁有本身的關鍵字null,一旦java看到null,就知道這個引用尚未指向某個對象。在使用任何引用前,必須爲其指定一個對象;若是試圖使用一個仍是null的引用,在運行時將會報錯。所以,常犯的數組錯誤在java中就能夠避免。
還能夠建立用來存放基本數據類型的數組。一樣,編譯器也能確保這種數組的初始化,由於它會將這種數組所佔的內存所有置零。
永遠不須要銷燬對象
在大多數程序設計語言中,變量生命週期的概念,佔據了程序設計工做中很是重要的部分。變量須要存活多長時間?若是想要銷燬對象,那麼什麼時刻進行?變量生命週期的混亂每每會致使大量的程序bug,本節將介紹java是怎樣替咱們完成全部的清理工做,從而大大地簡化這個問題的。
1)變量做用域:
做用域決定了在其內定義的變量名的可見性和生命週期。在C,C++,Java中,做用域由花括號的位置決定。
在做用域裏定義的變量只可用做用域結束以前。
可是他們也有區別:如下代碼,在C和c++裏是合法的,可是在java中卻不能這樣寫
{
int x=12;
{
int x = 9;
}
}
java中編譯器將會報告變量x已經定義過。在C和C++裏,較大做用域的變量會」隱藏「起來。
2)對象做用域:
java對象不具有和基本類型同樣的生命週期。當用new建立一個java對象時,它能夠存活於做用域以外。因此假如你採用代碼
{
String s = new String("a String");
}
引用s在做用域終點就消失。然而,s指向的String對象仍繼續佔據內存空間。
這樣便帶來了一個有趣的問題。若是java讓對象繼續存在,那麼靠什麼才能防止這些對象填滿內存空間,進而阻塞你的程序?這正是C++裏可能會發生的問題,java的神奇在於,它有一個垃圾回收器,用來監視new建立的全部對象,並辨別那些不會再被引用的對象。隨後釋放這些對象的內存空間。
3)新數據類型:類
若是一切都是對象,那麼是什麼決定了某一類對象的外觀和行爲?
定義一個類
class ATypename {
//這就是一個類
}
這樣就能夠用new來建立這種類型的對象了:
ATypename a = new ATypename();
可是若是定義類型裏沒有定義方法以前,他什麼都作不了。(也就是說,你不能向它發送任何有意義的信息)
----------------------
字段和方法
一旦定義了一個類(在java中你所作的所有工做就是定義類,產生那些類的對象,以及發送消息給這些對象),就能夠在類中設置兩種類型的對象:字段(有時被稱做數據成員)和方法(有時被稱做成員函數)。字段能夠是任何類型的對象能夠經過其引用與其進行通訊;也能夠是基本類型中的一種。若是字段是對某個對象的引用,那麼必須初始化該引用,以便使其與一個實際的對象(使用new來實現)相關聯。
字段
每一個對象都有用來存儲其字段的空間;普通字段不能在對象間共享。
類裏定義了字段,只能用於保存數據,沒有別的用處,由於它尚未任務成員方法,若是想了解成員方法的運行機制,就得先了解參數和返回值的概念,這個稍後提。
類裏的非方法題裏的基本數據類型,若是沒有初始化,java 會提供默認值。方法體裏的基本數據類型則沒有默認值。
方法
java的方法決定了一個對象可以接收什麼樣的消息。方法的基本組成部分包括:名稱、參數、返回值和方法體。下面是它最基本的形式:
ReturnType methodName(/*參數列表*/){
/*方法體*/
}
返回類型描述的是調用方法以後從方法返回的值。
參數列表給出了要傳給方法的信息的類型和名稱。
方法名和參數列表(它們合起來被稱爲「方法簽名」)惟一地標識出某個方法。
java中的方法只能做爲類的一部分來建立。方法只有經過對象才能被調用,且這個對象必須能執行這個方法調用。
(若是試圖在某個對象上調用他並不具有的方法,那麼在編譯時就會獲得一條錯誤消息)
面向對象的程序設計一般簡單地概括爲「向對象發送消息」。
參數列表
方法的參數列表指定要傳遞給方法什麼樣的信息。正如你可能料想的那樣,這些信息向java中的其它信息同樣,採用的都是對象形式。所以,在參數列表中必須指定每一個所傳遞對象的類型和名字。像java中任何傳遞對象的場合同樣,這裏傳遞的實際也是引用。
return關鍵字的用法:
兩方面:首先,它表明「已經作完,離開此方法」。其次,若是此方法產生了一個值,這個值要放在return語句後面。
static關鍵字
一般來講,當建立類時,就是在描述那個類的對象的外觀與行爲。除非用new建立那個類的對象,不然,實際上並未得到任務對象。執行new來建立對象時,數據存儲空間才被分配,其方法才供外界調用。
有兩種情形用上述方法沒法解決的。
一:只想爲某特定域分配單一存儲空間,而不去考慮究竟要建立多少對象,甚至根本就不建立任務對象。
二:但願某個方法不與包含的類的任務對象關聯在一塊兒。也就是說,即便沒有建立對象,也可以調用這個方法。
儘管當static做用於某個字段時,確定會改變數據建立的方式(由於一個static字段對每一個類來講都只有一份存儲空間,而非static字段則是對每一個對象有一個存儲空間),可是若是static做用在某個方法上,差異卻沒有那麼大。static方法的一個重要用法就是在不建立任何對象的前提下就能夠調用它。正如咱們將會看到的那樣,這一點對定義main()方法很重要,這個方法是運行一個應用時的入口點。
和其餘任何方法同樣,static方法能夠建立或使用與其類型相同的被命名對象,所以,static方法經常拿來作「牧羊人」的角色,負責看護與其隸屬同一類型的實例羣。