- Java的一些基本概念
- Java的起源
Java來自於Sun公司的一個叫Green的項目,其原先的目的是爲家用消費電子產品開發一個分佈式代碼系統,這樣我們可以把E-mail發給電冰箱、電視機等家用電器,對它們進行控制,和它們進行信息交流。
開始,準備採用C++,但C++太複雜,安全性差,最後基於C++開發了一種新的語言Oak(Java的前身),Oak是一種用於網絡的精巧而安全的語言,Sun公司曾以此投標一個交互式電視項目,但結果被SGI打敗。可憐的Oak幾乎無家可歸,恰巧這時Mark Ardreesen開發的Mosaic和Netscape啓發了Oak項目組成員,他們用Java編 制 了HotJava瀏 覽器,得到了Sun公司首席執行官Scott McNealy的支持,觸發了Java進 軍Internet。
Java的取名也有一則趣聞,有一天,幾 位Java成員組的會員正在討論給這個新的語言取什麼名字,當時他們正在咖啡館喝着Java(爪哇)咖 啡,有一個人靈機一動說就叫Java怎 樣,得到了其他人的讚賞,於是,Java這個名字就這樣傳開了。 - 爲什麼我們要學習Java語言
- 簡單的
Java最初是爲對家用電器進行集成控制而設計的一種語言,因此它必須簡單明瞭。Java語言的簡單性主要體現在三個方面:- Java的風格類似於C++,因而C++程序員初次接觸Java語言,就會感到很熟悉。從某種意義上講,Java語言是C及C++語言的一個變種,因此,C++程序員可以很快地掌握Java編程技術。
- Java摒棄了C++中容易引發程序錯誤的一些特性,如指針、結構、枚舉以及內存管理等。
- Java提供了豐富的類庫,可以幫助我們很方便的開發Java程序。
- 面向對象的
面向對象可以說是Java最重要的特性,所以它支持繼承、重載、多態等面向對象的特性。Java語言的設計是完全面向對象的,它不支持類似C語言那樣的面向過程的程序設計技術。 - 健壯的
Java致力於檢查程序在編譯和運行時的錯誤。Java也是一種強類型的語言,其類型檢查比C++還要嚴格。類型檢查幫助我們檢查出許多開發早期出現的錯誤。Java自己負責內存管理,提供了垃圾內存回收機制,有效的避免了C++中最頭疼的內存泄漏問題。 - 安全的
Java的安全性可從兩個方面得到保證。- 一方 面,在Java語言裏,刪除了指針和釋放內存等C++功能,避免了非法內存操作。
- 另一方面,通過Java的安全體系架構來確保Java代碼的安全性。當我們從網上下載Java代碼在本地執行時,Java的安全架構能確保惡意的代碼不能隨意訪問我們本地計算機的資源,例如:刪除文件,訪問本地網絡資源等操作都是被禁止的
- 解釋的
Java代碼是解釋執行的,我們使用Java編譯器將Java代碼編譯成字節碼,這是一種中間代碼,然後由Java解釋器解釋執行。而C++程序是編譯執行的,C++程序代碼被編譯爲本地機器指令,然後執行。 - 與平臺無關的
Java作爲一種網絡語言,其源代碼被編譯成一種結構中立的中間文件格式。只要有Java運行系統的機器都能執行這種中間代碼。Java源程序被編譯成一種與機器無關的字節碼格式,在Java虛擬機上運行。 - 多線程的
Java語言的一個重要特性就是在語言級支持多線程的程序設計。
多線程就好像我們做一張桌子,如果你一個人完成這張桌子—就好像單線程,那麼你需要先做桌面,做完桌面後,再做4個桌子腿,如果現在有5個人來做桌子—在程序中開闢5個線程,其中1個人做桌面,另外4個人分別做4個桌子腿,那麼這兩種方式效率的高低,相信大家都能區分出來。 - 動態的
Java的動態特性是其面向對象設計方法的擴展。它允許程序動態地裝入運行過程中所需要的類,這是我們採用C++語言進行面向對象程序設計所無法實現的。
在C++程序設計過程中,每當在類中增加一個實例變量或一個成員函數後, 引用該類的所有子類都必須重新編譯,否則將導致程序崩潰。
Java從以下幾個方面採取措施來解決這個問題。
Java編譯器不是將對實例變量和成員函數的引用編譯爲數值引用,而是將符號引用信息在字節碼中保存下來,傳遞給解釋器,再由解釋器在完成動態連接類後,將符號引用信息轉換爲數值偏移量。一個在存儲器中生成的對象不在編譯過程中決定,而是延遲到運行時由解釋器確定。這樣,對類中的變量和方法進行更新時就不至於影響現存的代碼。
解釋執行字節碼時,這種符號信息的查找和轉換過程僅在一個新的名字出現時才進行一次,隨後代碼便可以全速執行。在運行時確定引用的好處是可以使用已被更新的類,而不必擔心會影響原有的代碼。如果程序連接了網絡中另一系統中的某一類,該類的所有者也可以自由地對該類進行更新,而不會使任何引用該類的程序崩潰。
Java還簡化了使用一個升級的或全新協議的方法。如果你的系統運行Java程序時遇到了不知怎樣處理的程序,Java能自動下載你所需要的功能程序。
- 簡單的
- Java跨平臺原理剖析
Java的跨平臺是通過Java虛擬機(JVM)來實現的。
Java應用程序的開發週期包括編譯、下載、解釋和執行幾個部分。- Java源文件的編譯過程
Java編譯程序將Java源程序翻譯爲JVM可執行代碼—字節碼。
這一編譯過程同C/C++的編譯有些不同。當C編譯器編譯生成一個對象的代碼時,該代碼是爲在某一特定硬件平臺運行而產生的。因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉換爲特定的內存偏移量,以保證程序運行。
Java編譯器卻不將對變量和方法的引用編譯爲數值引用,也不確定程序執行過程中的內存佈局,而是將這些符號引用信息保留在字節碼中,由解釋器在運行過程中創建內存佈局,然後再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性。 - Java解釋器的執行過程
運行JVM字節碼的工作是由解釋器來完成的。
解釋執行過程分三步進行:代碼的裝入、代碼的校驗和代碼的執行。
裝入代碼的工作由“類裝載器”(class loader)完成。類裝載器負責裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調用的類。當類裝載器裝入一個類時,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其它類。在本臺計算機上的所有類都在同一地址空間內,而所有從外部引進的類,都有一個自己獨立的名字空間。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響。當裝入了運行程序需要的所有類後,解釋器便可確定整個可執行程序的內存佈局。解釋器爲符號引用同特定的地址空間建立對應關係及查詢表。通過在這一階段確定代碼的內存佈局,Java很好地解決了由超類改變而使子類崩潰的問題,同時也防止了代碼對地址的非法訪問。
隨後,被裝入的代碼由字節碼校驗器進行檢查。校驗器可發現操作數棧溢出,非法數據類型轉換等多種錯誤。
通過校驗後,代碼便開始執行了。 - Java字節碼的兩種執行方式
- 即時編譯方式:解釋器先將字節碼編譯成機器碼,然後再執行該機器碼。
- 解釋執行方式:解釋器通過每次解釋並執行一小段代碼來完成Java字節碼程序的所有操作。
通常採用的是第二種方法。由於JVM規格描述具有足夠的靈活性,這使得將字節碼翻譯爲機器代碼的工作具有較高的效率。對於那些對運行速度要求較高的應用程序,解釋器可將Java字節碼即時編譯爲機器碼,從而很好地保證了Java代碼的可移植性和高性能。
- JVM規格描述
JVM的設計目標是提供一個基於抽象規格描述的計算機模型,爲解釋程序開發人員提供很好的靈活性,同時也確保Java代碼可在符合該規範的任何系統上運行。JVM對其實現的某些方面給出了具體的定義,特別是對Java可執行代碼,即字節碼(Bytecode)的格式給出了明確的規格。這一規格包括操作碼和操作數的語法和數值、標識符的數值表示方式、以及Java類文件中的Java對象、常量緩衝池在JVM的存儲映象。這些定義爲JVM解釋器開發人員提供了所需的信息和開發環境。Java的設計者希望給開發人員以隨心所欲使用Java的自由。
JVM是爲Java字節碼定義的一種獨立於具體平臺的規格描述,是Java平臺獨立性的基礎。 - Java程序執行與C/C++程序執行的對比分析
如果把Java源程序想象成我們的C++源程序,Java源程序編譯後生成的字節碼就相當於C++源程序編譯後的80x86的機器碼(二進制程序文件),JVM虛擬機相當於80x86計算機系統,Java解釋器相當於80x86CPU。在80x86CPU上運行的是機器碼,在Java解釋器上運行的是Java字節碼。
Java解釋器相當於運行Java字節碼的“CPU”,但該“CPU”不是通過硬件實現的,而是用軟件實現的。Java解釋器實際上就是特定的平臺下的一個應用程序。只要實現了特定平臺下的解釋器程序,Java字節碼就能通過解釋器程序在該平臺下運行,這是Java跨平臺的根本。當前,並不是在所有的平臺下都有相應Java解釋器程序,這也是Java並不能在所有的平臺下都能運行的原因,它只能在已實現了Java解釋器程序的平臺下運行。 - Java開發工具包(JDK)的下載
http://java.sun.com
- Java源文件的編譯過程
- Java的起源
- Java環境變量的配置
在 我的電腦->屬性->高級->環境變量,在彈出的對話框裏 對系統變量 新建系統變量。
點擊確定。
可以在開始,運行,輸入cmd,再輸入javac(編譯.java後綴名的Java源文件),java(用於運行編譯好的.class後綴名的文件),這2個命令測試下。如果列出一大堆的命令參數列表,說明環境變量設置成功。 - 初學者常犯的問題
每個Java代碼源文件指定要有一個類,如果這個類申明爲public則必須類名與文件前綴名相同(當然,作爲一個習慣,一個文件就寫一個類),顯然,一個文件裏只能有一個public類。
jar用於打包:
jar cvf 新件包文件名 類名 類名
例如:
jar cvf sample Hello.class HelloWorld.class
則表示在當前路徑把hello.class和HelloWorld.class打成sample的包。
將eXeForJava目錄下的所有文件打包成sample包(當前路徑必須存在eXeForJava目錄)
jar cvf sample eXeForJava - Java語言的基本數據類型
- 變量(8種變量類型)
byte b;
Java類型檢查是很嚴格的。
short s;
int i;
long l;
float f;
double d;
boolean bool;
char c = 'W';byte b = 3;
b = b * 3; //This will cause an error,for the result will be an interger number.
b = (byte) (b * 3); //This one will be ok.
System.out.println(b);
關於if(1),這樣寫是錯誤的,應該這樣寫:if(true)
{
} - 數組
定義方法:數組類型名[] 數組名 = new 數組類型名[];
數組的初始化:int [] num=new int[]{1,2,3}; //ok
int [] num=new int[3]{1,2,3}; //error;
int [] num;
num=new int[3];
num[0]=1;
num[1]=12;
num[2]=32;
System.out.println(num[0]);
System.out.println(num[1]);
System.out.println(num[2]);
多維數組:/*int [][] num;
num=new int[3][4];
num[0][1]=12;
num[2][3]=34;*/
/*int [][] num;
num=new int[3][];
num[0]=new int[5];
num[1]=new int[3];
num[2]=new int[2];
num[0][4]=45;
num[1][2]=34;
num[2][1]=21;
System.out.println(num[0][4]);
System.out.println(num[1][2]);
System.out.println(num[2][1]);
System.out.println(num[2][2]);*/
//int [][] num=new int[][]{1,2,3,4,5,5}; //error
//int [][] num=new int[][]{{1,2,3},{4,5,5}}; //ok
//int [][] num=new int[2][]{{1,2,3},{4,5,5}}; //error
//int [][] num={{1,2,3},{4,5,6}}; //ok
/*int [][] num={{1,2,3},{4,5},{6}};
System.out.println(num[0][2]);
System.out.println(num[1][1]);
System.out.println(num[2][0]);*/
關於i++與++i:/*int i=3;
//System.out.println(i++);
System.out.println(++i);*/
/*int i=3;
//int count=(i++)+(i++)+(i++); //4 + 4 + 4 = 12
int count=(++i)+(++i)+(++i); //4 + 5 + 6 = 15
System.out.println(i);
System.out.println(count);*/ - Java的語句。
if()
{
}
while(true)
{
}
do
{
}while(true); - 工具使用
最好的代碼編輯器:EditPlus v2.21
JDK 1.5 : http://java.sun.com
- 變量(8種變量類型)
- 計算機中數據的表示方法
計算機是一種電子設備,由複雜的電子元器件組合而成,一個電子元器件有帶電和不帶電兩種狀態,通常我們將帶電狀態表示爲數值1,不帶電狀態表示爲數值0,多個這樣的元器件的組合可以表示更多狀態,也就是可以表示更多的數據,如000表示0,001表示1,010表示2,011表示3,依此類推,111表示7,一個元器件可表示一位(bit)數據,這種表示數據的方式就叫二進制。
在實際的電子設備中,我們將8個這樣的元器件形成一個單元,這樣的單元叫一個字節(byte),一個字節能表示多少個數呢?表示數值的範圍是0-255。
一個字節由8個二進位組成,其中最右邊的一位稱爲“最低有效位”或“最低位”,最左邊的一位稱爲“最高有效位”或“最高位”。每一個二進位的值是0或1。
二進制計數的缺點:書寫太長,容易出錯,一般計算機的數據位數都是4的整數倍,所以,在計算機裏通常採用16進制計數法。用數字可以表示各種信息,計算機裏只有數值,當你在內存中看到一個數值時,這個數值可能代表各種意義,生活中的數值也可以代表其他意義,如1234可以代表密碼,存款額,電報信息,根據上下線索,我們就能夠知道這數值代表的意義。 - 原碼
將最高位作爲符號位(以0代表正,1代表負),其餘各位代表數值本身的絕對值(以二進制表示)。
爲了簡單起見,我們用1個字節來表示一個整數。
+7的原碼爲: 00000111
-7的原碼爲: 10000111
問題:
+0的原碼爲: 00000000
-0的原碼爲: 10000000 - 反碼
一個數如果爲正,則它的反碼與原碼相同;一個數如果爲負,則符號位爲1,其餘各位是對原碼取反。
爲了簡單起見,我們用1個字節來表示一個整數。
+7的反碼爲: 00000111
-7的反碼爲: 11111000
問題:
+0的反碼爲: 00000000
-0的反碼爲: 11111111 - 補碼
利用溢出,我們可以將減法變成加法。
對於十進制數,如果從9得到結果5,可以用減法:
9-4=5
因爲4+6=10,我們將6作爲4的補數,將上式的減法改寫爲加法:
9+6=15
去掉高位1(也就是減去10),得到結果5。
對於16進制數,如果從C得到結果5,可以用減法:
C-7=5
因爲7+9=16,我們將9作爲7的補數,將上式的減法改寫爲加法:
C+9=15
去掉高位1(也就是減去16),得到結果5。
在計算機中,如果我們用1個字節表示一個數,一個字節有8位,超過8位就進1,在內存中情況爲:
1 00000000
進位1被丟棄。
一個數如果爲正,則它的原碼、反碼、補碼相同;一個數如果爲負,則符號位爲1,其餘各位是對原碼取反,然後整個數加1。
爲了簡單起見,我們用1個字節來表示一個整數。
+7的補碼爲: 00000111
-7的補碼爲:第一步:11111000 (符號位爲,其餘各位取反)
第二步:11111001 (整個數加1)
+0的補碼:00000000;
-0的補碼:11111111;(第一步)
100000000;(第二步)
已知一個負數的補碼,將其轉換爲十進制數,步驟:
1、先對各位取反;
2、將其轉換爲十進制數;
3、加上負號,再減去1。
例如:
11111010,最高位爲1,是負數,先對各位取反得00000101,轉換爲十進制數得5,加上負號得-5,再減1得-6。 - 位運算符
爲了方便對二進制位進行操作,Java給我們提供了四個二進制位操作符:
& 按位與
| 按位或
^ 按位異或
~ 按位取反 - 按位與
一個房間裏有兩個開關控制房間的燈的明暗。當兩個開關同時處於打開狀態時,燈才能亮。
開關1 開關2 燈的狀態
關 關 暗
開 關 暗
關 開 暗
開 開 亮
結論:按位與,只有壹(1)壹(1)爲1。 - 按位或
一個房間裏有兩個開關控制房間的燈的明暗。當任何一個開關處於打開狀態時,燈就能亮。
開關1 開關2 燈的狀態
關 關 暗
開 關 亮
關 開 亮
開 開 亮
結論:按位或,只有零(0)零(0)爲0。 - 按位異或
一個房間裏有兩個開關控制房間的燈的明暗。當兩個開關處於不同狀態時,燈就能亮。
開關1 開關2 燈的狀態
關 關 暗
開 關 亮
關 開 亮
開 開 暗
結論:按位異或,只有零(0)壹(1)或壹(1)零(0)爲1。 - 按位取反
結論:對二進制數按位取反,即0變成1,1變成0。 - Java中有三個移位運算符
左移:<< (相當於 乘以2)
帶符號右移:>> (相當於 除以2)
無符號右移:>>>
數 x x<<2 x>>2 x>>>2
17 00010001 00 01000100 00000100 01 00000100 01
-17 11101111 11 10111100 11111011 11 00111011 11
練習:將一個整數110從右端開始的4~7位變爲0。
-
面向對象編程概述
-
簡單的說,面向對象編程(Object Oriented Programming,簡稱OOP)描述的是對象之間的相互作用。
-
面向對象編程與面向過程編程的區別:
過程化程序設計先確定算法,再確定數據結構;
面向對象編程先確定數據結構,再確定運算。
面向過程編程的程序員,習慣於建立數據結構存放數據並定義方法(函數)來操作數據;
面向對象編程的程序員則構造一個對象模型,將數據與方法組織在一起。
-
-
對象 對象的狀態 對象的行爲
-
我們可以把現實世界的事物抽象成對象。
-
對象一般都有兩個特徵:狀態(state)和行爲(behavior)。
-
軟件的對象概念是由現實世界對象抽象而來 。
把現實世界對象的狀態保存在軟件對象的變量中;現實世界對象的行爲通過軟件對象的方法(函數)來實現。
-
-
類和對象
-
把相似的對象劃歸成一個類。
-
在軟件中,類,就是一個模板,它定義了通用於一個特定種類的所有對象的狀態(變量)和行爲(方法)。
-
類是創建對象的模板,對象是類的實例。
-
-
面向對象程序設計
-
從程序設計的角度看,類是面向對象程序中最基本的程序單元。類實質上定義的是一種數據類型,這種數據類型就是對象類型 。所以我們可以使用類名稱來聲明對象變量。
-
聲明對象變量之後,還不能使用對象。必須用運算符new創建對象實體之後,才能使用對象。
-
-
面向對象編程的難點
-
掌握面向對象的困難之處在於思路的轉換。
我們通常習慣於考慮解決問題的方法,而不是考慮將問題抽象成對象再去解決它。
-
-
一個簡單的例子
-
編寫一個駕駛汽車的方法
面向過程的程序設計:
編寫一個方法,void drivecar();
面向對象的程序設計:
將一輛汽車看成一個對象,將所有汽車對象的共性抽取出來,設計一個類Car,類中有一個方法void drive(),用Car這個類實例化一個具體的對象car,調用:car.drive()。
-
-
類的構造方法
-
構造方法的名字和類名相同,並且沒有返回值。
-
構造方法主要用於爲類的對象定義初始化狀態。
-
我們不能直接調用構造方法,必須通過new關鍵字來自動調用,從而創建類的實例。
-
Java的類都要求有構造方法,如果沒有定義構造方法,Java編譯器會爲我們提供一個缺省的構造方法,也就是不帶參數的構造方法。(javap來反編譯可以得到)
-
-
new關鍵字的作用
-
爲對象分配內存空間。
-
引起對象構造方法的調用。
-
爲對象返回一個引用。
-
-
缺省構造方法
-
當我們用缺省的構造方法初始化對象時,系統用默認值初始化對象的成員變量。
-
各種數據類型的默認值爲:
數值型 0
boolean false
char ‘/0’
對象 null
-
-
方法的重載(overload)
-
重載構成的條件:方法的名稱相同,但參數類型或參數個數不同,才能構成方法的重載。
-
-
特殊變量this
-
this變量代表對象本身
-
當類中有兩個同名變量,一個屬於類(類的成員變量),而另一個屬於某個特定的方法(方法中的局部變量),使用this區分成員變量和局部變量。
-
使用this簡化構造函數的調用。
-
關於實例方法和實例數據成員的進一步說明
一個類所有的實例(對象)調用的成員方法在內存中只有一份拷貝,儘管在內存中可能有多個對象,而數據成員在類的每個對象所在內存中都存在着一份拷貝。this變量允許相同的實例方法爲不同的對象工作。每當調用一個實例方法時,this變量將被設置成引用該實例方法的特定的類對象。方法的代碼接着會與this所代表的對象的特定數據建立關聯。
-
-
關鍵字static
-
靜態方法和靜態變量是屬於某一個類,而不屬於類的對象。
-
靜態方法和靜態變量的引用直接通過類名引用。
-
在靜態方法中不能調用非靜態的方法和引用非靜態的成員變量。反之,則可以。
-
可以用類的對象obj去調用靜態的方法method(),如:obj.method()。
-
實例方法是必須實例話纔可以調用的方法,實例名.方法名()
-
-
常量的定義
-
使用關鍵字final定義常量,例如:
final double PI=3.1415926; -
作爲一種約定,在定義常量時,通常採用大寫形式。
-
final常量可以在聲明的同時賦初值,也可以在構造函數中賦初值。
-
爲了節省內存,我們通常將常量聲明爲靜態的(static)。
-
-
類的繼承
-
理解繼承是理解面向對象程序設計的關鍵。
-
在Java中,通過關鍵字extends繼承一個已有的類,被繼承的類稱爲父類(超類,基類),新的類稱爲子類(派生類)。
-
在Java中,不允許多繼承。
-
-
方法的覆蓋(override)
-
在子類中定義一個與父類同名、返回類型、參數類型均相同一個方法,稱爲方法的覆蓋。
-
覆蓋發生在子類與父類之間。
-
-
特殊變量super
-
特殊變量super,提供了對父類的訪問。
-
可以使用super訪問父類被子類隱藏的變量或覆蓋的方法。
-
每個子類構造方法的第一條語句,都是隱含地調用super(),如果父類沒有這種形式的構造函數,那麼在編譯的時候就會報錯。
-
-
多態性
-
通過覆蓋父類的方法來實現,在運行時根據傳遞的對象引用,來調用相應的方法。
-
-
面向對象的程序設計
-
問題:求一個長方形的周長和麪積。
以面向過程的程序設計方式思考:
1、確定長方形周長和麪積的算法。
2、編寫兩個方法(函數)分別計算長方形的周長和麪積。
3、求周長的方法(函數)和求面積的方法(函數)需要兩個參數,分別是長方形的長和寬。 -
面向過程的程序設計代碼:
class Rectangle
{
static int perimeter(int length,int width)
{
return 2*(length+width);
}
static int area(int length,int width)
{
return length*width;
}
public static void main(String[] args)
{
System.out.println("perimeter = “ + Rectangle.perimeter(5,4));
System.out.println("area = “ + Rectangle.area(5,4));
}
} -
問題:求一個長方形的周長和麪積。
以面向對象的程序設計方式思考:
1、一個長方形可以看成一個長方形對象。
2、一個長方形對象有兩個狀態(長和寬)和兩個行爲(求周長和求面積)。
3、將所有長方形的共性抽取出來,設計一個長方形類。
4、通過長方形對象的行爲,就可以求出某個具體的長方形對象的周長和麪積。
-