從零開始學Java——基礎篇
整理自菜鳥教程
Java 簡介
Java是Java面向物件程式設計語言和Java平臺的總稱。
Java分為三個體系:
- JavaSE(J2SE)(Java2 Platform Standard Edition,java平臺標準版)
- JavaEE(J2EE)(Java 2 Platform,Enterprise Edition,java平臺企業版)
- JavaME(J2ME)(Java 2 Platform Micro Edition,java平臺微型版)。
主要特性
- Java語言是簡單的:
Java語言的語法與C語言和C++語言很接近,使得大多數程式設計師很容易學習和使用。另一方面,Java丟棄了C++中很少使用的、很難理解的、令人迷惑的那些特性,如操作符過載、多繼承、自動的強制型別轉換。特別地,Java語言不使用指標,而是引用。並提供了自動的廢料收集,使得程式設計師不必為記憶體管理而擔憂。
- Java語言是面向物件的:
Java語言提供類、介面和繼承等面向物件的特性,為了簡單起見,只支援類之間的單繼承,但支援介面之間的多繼承,並支援類與介面之間的實現機制(關鍵字為implements)。Java語言全面支援動態繫結,而C++語言只對虛擬函式使用動態繫結。總之,Java語言是一個純的面向物件程式設計語言。
- Java語言是分散式的:
Java語言支援Internet應用的開發,在基本的Java應用程式設計介面中有一個網路應用程式設計介面(java net),它提供了用於網路應用程式設計的類庫,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(遠端方法啟用)機制也是開發分散式應用的重要手段。
- Java語言是健壯的:
Java的強型別機制、異常處理、垃圾的自動收集等是Java程式健壯性的重要保證。對指標的丟棄是Java的明智選擇。Java的安全檢查機制使得Java更具健壯性。
- Java語言是安全的:
Java通常被用在網路環境中,為此,Java提供了一個安全機制以防惡意程式碼的攻擊。除了Java語言具有的許多安全特性以外,Java對通過網路下載的類具有一個安全防範機制(類ClassLoader),如分配不同的名字空間以防替代本地的同名類、位元組程式碼檢查,並提供安全管理機制(類SecurityManager)讓Java應用設定安全哨兵。
- Java語言是體系結構中立的:
Java程式(字尾為java的檔案)在Java平臺上被編譯為體系結構中立的位元組碼格式(字尾為class的檔案),然後可以在實現這個Java平臺的任何系統中執行。這種途徑適合於異構的網路環境和軟體的分發。
- Java語言是可移植的:
這種可移植性來源於體系結構中立性,另外,Java還嚴格規定了各個基本資料型別的長度。Java系統本身也具有很強的可移植性,Java編譯器是用Java實現的,Java的執行環境是用ANSI C實現的。
- Java語言是解釋型的:
如前所述,Java程式在Java平臺上被編譯為位元組碼格式,然後可以在實現這個Java平臺的任何系統中執行。在執行時,Java平臺中的Java直譯器對這些位元組碼進行解釋執行,執行過程中需要的類在聯接階段被載入到執行環境中。
- Java是高效能的:
與那些解釋型的高階指令碼語言相比,Java的確是高效能的。事實上,Java的執行速度隨著JIT(Just-In-Time)編譯器技術的發展越來越接近於C++。
- Java語言是多執行緒的:
在Java語言中,執行緒是一種特殊的物件,它必須由Thread類或其子(孫)類來建立。通常有兩種方法來建立執行緒:其一,使用型構為Thread(Runnable)的構造子將一個實現了Runnable介面的物件包裝成一個執行緒,其二,從Thread類派生出子類並重寫run方法,使用該子類建立的物件即為執行緒。值得注意的是Thread類已經實現了Runnable介面,因此,任何一個執行緒均有它的run方法,而run方法中包含了執行緒所要執行的程式碼。執行緒的活動由一組方法來控制。Java語言支援多個執行緒的同時執行,並提供多執行緒之間的同步機制(關鍵字為synchronized)。
- Java語言是動態的:
Java語言的設計目標之一是適應於動態變化的環境。Java程式需要的類能夠動態地被載入到執行環境,也可以通過網路來載入所需要的類。這也有利於軟體的升級。另外,Java中的類有一個執行時刻的表示,能進行執行時刻的型別檢查。
Java開發環境的配置
下載適合你的系統的java 開發工具包JDK
安裝
配置環境變數
開發工具建議使用IDE eclipse
Java 基礎語法
一個Java程式可以認為是一系列物件的集合,而這些物件通過呼叫彼此的方法來協同工作。
下面簡要介紹下類、物件、方法和例項變數的概念。
- 物件:物件是類的一個例項,有狀態和行為。例如,一條狗是一個物件,它的狀態有:顏色、名字、品種;行為有:搖尾巴、叫、吃等。
- 類:類是一個模板,它描述一類物件的行為和狀態。
- 方法:方法就是行為,一個類可以有很多方法。邏輯運算、資料修改以及所有動作都是在方法中完成的。
- 例項變數:每個物件都有獨特的例項變數,物件的狀態由這些例項變數的值決定。
第一個Java程式
下面看一個簡單的Java程式,它將列印字串 Hello World
例項
public class HelloWorld {
/* 第一個Java程式
* 它將列印字串 Hello World
*/
public static void main(String []args) {
System.out.println("Hello World"); // 列印 Hello World
}
}
下面將逐步介紹如何儲存、編譯以及執行這個程式:
- 開啟Notepad,把上面的程式碼新增進去;
- 把檔名儲存為:HelloWorld.java;
- 開啟cmd命令視窗,進入目標檔案所在的位置,假設是C:\
- 在命令列視窗鍵入 javac HelloWorld.java 按下enter鍵編譯程式碼。如果程式碼沒有錯誤,cmd命令提示符會進入下一行。(假設環境變數都設定好了)。
- 再鍵入java HelloWorld 按下Enter鍵就可以執行程式了
你將會在視窗看到 Hello World
C : > javac HelloWorld.java
C : > java HelloWorld
Hello World
基本語法
編寫Java程式時,應注意以下幾點:
- 大小寫敏感:Java是大小寫敏感的,這就意味著識別符號Hello與hello是不同的。
- 類名:對於所有的類來說,類名的首字母應該大寫。如果類名由若干單片語成,那麼每個單詞的首字母應該大寫,例如 MyFirstJavaClass 。
- 方法名:所有的方法名都應該以小寫字母開頭。如果方法名含有若干單詞,則後面的每個單詞首字母大寫。
- 原始檔名:原始檔名必須和類名相同。當儲存檔案的時候,你應該使用類名作為檔名儲存(切記Java是大小寫敏感的),檔名的字尾為.java。(如果檔名和類名不相同則會導致編譯錯誤)。
- 主方法入口:所有的Java 程式由public static void main(String []args)方法開始執行。
Java識別符號
Java所有的組成部分都需要名字。類名、變數名以及方法名都被稱為識別符號。
關於Java識別符號,有以下幾點需要注意:
- 所有的識別符號都應該以字母(A-Z或者a-z),美元符($)、或者下劃線(_)開始
- 首字元之後可以是字母(A-Z或者a-z),美元符($)、下劃線(_)或數字的任何字元組合
- 關鍵字不能用作識別符號
- 識別符號是大小寫敏感的
- 合法識別符號舉例:age、$salary、_value、__1_value
- 非法識別符號舉例:123abc、-salary
Java修飾符
像其他語言一樣,Java可以使用修飾符來修飾類中方法和屬性。主要有兩類修飾符:
- 訪問控制修飾符 : default, public , protected, private
- 非訪問控制修飾符 : final, abstract, static, synchronized
Java變數
Java中主要有如下幾種型別的變數
- 區域性變數
- 類變數(靜態變數)
- 成員變數(非靜態變數)
Java陣列
陣列是儲存在堆上的物件,可以儲存多個同類型變數。
Java列舉
Java 5.0引入了列舉,列舉限制變數只能是預先設定好的值。使用列舉可以減少程式碼中的bug。
例如,我們為果汁店設計一個程式,它將限制果汁為小杯、中杯、大杯。這就意味著它不允許顧客點除了這三種尺寸外的果汁。
class FreshJuice {
enum FreshJuiceSize{ SMALL, MEDIUM , LARGE }
FreshJuiceSize size;
}
public class FreshJuiceTest {
public static void main(String []args){
FreshJuice juice = new FreshJuice();
juice.size = FreshJuice.FreshJuiceSize.MEDIUM ;
}
}
注意:列舉可以單獨宣告或者宣告在類裡面。方法、變數、建構函式也可以在列舉中定義。
Java 關鍵字
下面列出了Java 關鍵字。這些保留字不能用於常量、變數、和任何識別符號的名稱。
類別 | 關鍵字 | 說明 |
---|---|---|
訪問控制 | private | 私有的 |
protected | 受保護的 | |
public | 公共的 | |
類、方法和變數修飾符 | abstract | 宣告抽象 |
class | 類 | |
extends | 擴充,繼承 | |
final | 最終值,不可改變的 | |
implements | 實現(介面) | |
interface | 介面 | |
native | 本地,原生方法(非Java實現) | |
new | 新,建立 | |
static | 靜態 | |
strictfp | 嚴格,精準 | |
synchronized | 執行緒,同步 | |
transient | 短暫 | |
volatile | 易失 | |
程式控制語句 | break | 跳出迴圈 |
case | 定義一個值以供switch選擇 | |
continue | 繼續 | |
default | 預設 | |
do | 執行 | |
else | 否則 | |
for | 迴圈 | |
if | 如果 | |
instanceof | 例項 | |
return | 返回 | |
switch | 根據值選擇執行 | |
while | 迴圈 | |
錯誤處理 | assert | 斷言表示式是否為真 |
catch | 捕捉異常 | |
finally | 有沒有異常都執行 | |
throw | 丟擲一個異常物件 | |
throws | 宣告一個異常可能被丟擲 | |
try | 捕獲異常 | |
包相關 | import | 引入 |
package | 包 | |
基本型別 | boolean | 布林型 |
byte | 位元組型 | |
char | 字元型 | |
double | 雙精度浮點 | |
float | 單精度浮點 | |
int | 整型 | |
long | 長整型 | |
short | 短整型 | |
變數引用 | super | 父類,超類 |
this | 本類 | |
void | 無返回值 | |
保留關鍵字 | goto | 是關鍵字,但不能使用 |
const | 是關鍵字,但不能使用 | |
null | 空 |
Java註釋
類似於C/C++,Java也支援單行以及多行註釋。註釋中的字元將被Java編譯器忽略。
public class HelloWorld {
/* 這是第一個Java程式
*它將列印Hello World
* 這是一個多行註釋的示例
*/
public static void main(String []args){
// 這是單行註釋的示例
/* 這個也是單行註釋的示例 */
System.out.println("Hello World");
}
}
Java 空行
空白行,或者有註釋的行,Java編譯器都會忽略掉。
繼承
在Java中,一個類可以由其他類派生。如果你要建立一個類,而且已經存在一個類具有你所需要的屬性或方法,那麼你可以將新建立的類繼承該類。
利用繼承的方法,可以重用已存在類的方法和屬性,而不用重寫這些程式碼。被繼承的類稱為超類(super class),派生類稱為子類(subclass)。
介面
在Java中,介面可理解為物件間相互通訊的協議。介面在繼承中扮演著很重要的角色。
介面只定義派生要用到的方法,但是方法的具體實現完全取決於派生類。
Java 源程式與編譯型執行區別
如下圖所示:
Java 物件和類
Java作為一種面嚮物件語言。支援以下基本概念:
- 多型
- 繼承
- 封裝
- 抽象
- 類
- 物件
- 例項
- 方法
- 過載
本節我們重點研究物件和類的概念。
- 物件:物件是類的一個例項,有狀態和行為。例如,一條狗是一個物件,它的狀態有:顏色、名字、品種;行為有:搖尾巴、叫、吃等。
- 類:類是一個模板,它描述一類物件的行為和狀態。
Java中的物件
現在讓我們深入瞭解什麼是物件。看看周圍真實的世界,會發現身邊有很多物件,車,狗,人等等。所有這些物件都有自己的狀態和行為。
拿一條狗來舉例,它的狀態有:名字、品種、顏色,行為有:叫、搖尾巴和跑。
對比現實物件和軟體物件,它們之間十分相似。
軟體物件也有狀態和行為。軟體物件的狀態就是屬性,行為通過方法體現。
在軟體開發中,方法操作物件內部狀態的改變,物件的相互呼叫也是通過方法來完成。
Java中的類
類可以看成是建立Java物件的模板。
通過下面一個簡單的類來理解下Java中類的定義:
public class Dog
{
//屬性
String breed;
int age;
String color;
//方法
void barking(){ }
void hungry(){ }
void sleeping(){ }
}
一個類可以包含以下型別變數:
- 區域性變數:在方法、構造方法或者語句塊中定義的變數被稱為區域性變數。變數宣告和初始化都是在方法中,方法結束後,變數就會自動銷燬。
- 成員變數:成員變數是定義在類中,方法體之外的變數。這種變數在建立物件的時候例項化。成員變數可以被類中方法、構造方法和特定類的語句塊訪問。
- 類變數:類變數也宣告在類中,方法體之外,但必須宣告為static型別。
一個類可以擁有多個方法,在上面的例子中:barking()、hungry()和sleeping()都是Dog類的方法。
構造方法
每個類都有構造方法。如果沒有顯式地為類定義構造方法,Java編譯器將會為該類提供一個預設構造方法。
在建立一個物件的時候,至少要呼叫一個構造方法。構造方法的名稱必須與類同名,一個類可以有多個構造方法。
下面是一個構造方法示例:
public class Puppy{
//無引數構造方法和有引數構造方法
public Puppy(){ }
public Puppy(String name){ // 這個構造器僅有一個引數:name }
}
建立物件
物件是根據類建立的。在Java中,使用關鍵字new來建立一個新的物件。建立物件需要以下三步:
- 宣告:宣告一個物件,包括物件名稱和物件型別。
- 例項化:使用關鍵字new來建立一個物件。
- 初始化:使用new建立物件時,會呼叫構造方法初始化物件。
下面是一個建立物件的例子:
public class Puppy{
public Puppy(String name)
{
//這個構造器僅有一個引數:name
System.out.println("小狗的名字是 : " + name );
}
public static void main(String []args)
{
// 下面的語句將建立一個Puppy物件
Puppy myPuppy = new Puppy( "tommy" );
}
}
編譯並執行上面的程式,會打印出下面的結果:
小狗的名字是 : tommy
訪問例項變數和方法
通過已建立的物件來訪問成員變數和成員方法,如下所示:
/* 例項化物件 */
ObjectReference = new Constructor();
/* 訪問類中的變數 */
ObjectReference.variableName;
/* 訪問類中的方法 */
ObjectReference.methodName();
例項
下面的例子展示如何訪問例項變數和呼叫成員方法:
public class Puppy{
int puppyAge;
public Puppy(String name)
{
// 這個構造器僅有一個引數:name
System.out.println("小狗的名字是 : " + name );
}
public void setAge( int age )
{
puppyAge = age;
}
public int getAge( )
{
System.out.println("小狗的年齡為 : " + puppyAge );
return puppyAge;
}
public static void main(String []args)
{
/* 建立物件 */
Puppy myPuppy = new Puppy( "tommy" );
/* 通過方法來設定age */
myPuppy.setAge( 2 );
/* 呼叫另一個方法獲取age */
myPuppy.getAge( );
/*你也可以像下面這樣訪問成員變數 */
System.out.println("變數值 : " + myPuppy.puppyAge );
}
}
編譯並執行上面的程式,產生如下結果:
小狗的名字是 : tommy
小狗的年齡為 : 2
變數值 : 2
原始檔宣告規則
在本節的最後部分,我們將學習原始檔的宣告規則。當在一個原始檔中定義多個類,並且還有import語句和package語句時,要特別注意這些規則。
- 一個原始檔中只能有一個public類
- 一個原始檔可以有多個非public類
- 原始檔的名稱應該和public類的類名保持一致。例如:原始檔中public類的類名是Employee,那麼原始檔應該命名為Employee.java。
- 如果一個類定義在某個包中,那麼package語句應該在原始檔的首行。
- 如果原始檔包含import語句,那麼應該放在package語句和類定義之間。如果沒有package語句,那麼import語句應該在原始檔中最前面。
- import語句和package語句對原始檔中定義的所有類都有效。在同一原始檔中,不能給不同的類不同的包宣告。
類有若干種訪問級別,並且類也分不同的型別:抽象類和final類等。
除了上面提到的幾種型別,Java還有一些特殊的類,如:內部類、匿名類。
Java包
包主要用來對類和介面進行分類。當開發Java程式時,可能編寫成百上千的類,因此很有必要對類和介面進行分類。
Import語句
在Java中,如果給出一個完整的限定名,包括包名、類名,那麼Java編譯器就可以很容易地定位到原始碼或者類。Import語句就是用來提供一個合理的路徑,使得編譯器可以找到某個類。
例如,下面的命令列將會命令編譯器載入java_installation/java/io路徑下的所有類
import java.io.*;
一個簡單的例子
在該例子中,我們建立兩個類:Employee 和 EmployeeTest。
首先開啟文字編輯器,把下面的程式碼貼上進去。注意將檔案儲存為 Employee.java。
Employee類有四個成員變數:name、age、designation和salary。該類顯式聲明瞭一個構造方法,該方法只有一個引數。
Employee.java 檔案程式碼:
import java.io.*;
public class Employee{
String name;
int age;
String designation;
double salary;
// Employee 類的構造器
public Employee(String name){
this.name = name;
}
// 設定age的值
public void empAge(int empAge){
age = empAge;
}
/* 設定designation的值*/
public void empDesignation(String empDesig){
designation = empDesig;
}
/* 設定salary的值*/
public void empSalary(double empSalary){
salary = empSalary;
}
/* 列印資訊 */
public void printEmployee(){
System.out.println("名字:"+ name );
System.out.println("年齡:" + age );
System.out.println("職位:" + designation );
System.out.println("薪水:" + salary);
}
}
程式都是從main方法開始執行。為了能執行這個程式,必須包含main方法並且建立一個例項物件。
下面給出EmployeeTest類,該類例項化2個 Employee 類的例項,並呼叫方法設定變數的值。
將下面的程式碼儲存在 EmployeeTest.java檔案中。
EmployeeTest.java 檔案程式碼:
import java.io.*;
public class EmployeeTest{
public static void main(String []args){
/* 使用構造器建立兩個物件 */
Employee empOne = new Employee("RUNOOB1");
Employee empTwo = new Employee("RUNOOB2");
// 呼叫這兩個物件的成員方法
empOne.empAge(26);
empOne.empDesignation("高階程式設計師");
empOne.empSalary(1000);
empOne.printEmployee();
empTwo.empAge(21);
empTwo.empDesignation("菜鳥程式設計師");
empTwo.empSalary(500);
empTwo.printEmployee();
}
}
編譯這兩個檔案並且執行 EmployeeTest 類,可以看到如下結果:
$ javac EmployeeTest.java
$ java EmployeeTest
名字:RUNOOB1
年齡:26
職位:高階程式設計師
薪水:1000.0
名字:RUNOOB2
年齡:21
職位:菜鳥程式設計師
薪水:500.0
Java 基本資料型別
變數就是申請記憶體來儲存值。也就是說,當建立變數的時候,需要在記憶體中申請空間。
記憶體管理系統根據變數的型別為變數分配儲存空間,分配的空間只能用來儲存該型別資料。
因此,通過定義不同型別的變數,可以在記憶體中儲存整數、小數或者字元。
Java 的兩大資料型別:
- 內建資料型別
- 引用資料型別
內建資料型別
Java語言提供了八種基本型別。六種數字型別(四個整數型,兩個浮點型),一種字元型別,還有一種布林型。
byte:
- byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數;
- 最小值是 -128(-2^7);
- 最大值是 127(2^7-1);
- 預設值是 0;
- byte 型別用在大型陣列中節約空間,主要代替整數,因為 byte 變數佔用的空間只有 int 型別的四分之一;
- 例子:byte a = 100,byte b = -50。
short:
- short 資料型別是 16 位、有符號的以二進位制補碼錶示的整數
- 最小值是 -32768(-2^15);
- 最大值是 32767(2^15 - 1);
- Short 資料型別也可以像 byte 那樣節省空間。一個short變數是int型變數所佔空間的二分之一;
- 預設值是 0;
- 例子:short s = 1000,short r = -20000。
int:
- int 資料型別是32位、有符號的以二進位制補碼錶示的整數;
- 最小值是 -2,147,483,648(-2^31);
- 最大值是 2,147,483,647(2^31 - 1);
- 一般地整型變數預設為 int 型別;
- 預設值是 0 ;
- 例子:int a = 100000, int b = -200000。
long:
- long 資料型別是 64 位、有符號的以二進位制補碼錶示的整數;
- 最小值是 -9,223,372,036,854,775,808(-2^63);
- 最大值是 9,223,372,036,854,775,807(2^63 -1);
- 這種型別主要使用在需要比較大整數的系統上;
- 預設值是 0L;
- 例子: long a = 100000L,Long b = -200000L。
"L"理論上不分大小寫,但是若寫成"l"容易與數字"1"混淆,不容易分辯。所以最好大寫。
float:
- float 資料型別是單精度、32位、符合IEEE 754標準的浮點數;
- float 在儲存大型浮點陣列的時候可節省記憶體空間;
- 預設值是 0.0f;
- 浮點數不能用來表示精確的值,如貨幣;
- 例子:float f1 = 234.5f。
double:
- double 資料型別是雙精度、64 位、符合IEEE 754標準的浮點數;
- 浮點數的預設型別為double型別;
- double型別同樣不能表示精確的值,如貨幣;
- 預設值是 0.0d;
- 例子:double d1 = 123.4。
boolean:
- boolean資料型別表示一位的資訊;
- 只有兩個取值:true 和 false;
- 這種型別只作為一種標誌來記錄 true/false 情況;
- 預設值是 false;
- 例子:boolean one = true。
char:
- char型別是一個單一的 16 位 Unicode 字元;
- 最小值是 \u0000(即為0);
- 最大值是 \uffff(即為65,535);
- char 資料型別可以儲存任何字元;
- 例子:char letter = 'A';。
對於數值型別的基本型別的取值範圍,我們無需強制去記憶,因為它們的值都已經以常量的形式定義在對應的包裝類中了。
包裝類:java.lang.Byte
包裝類:java.lang.Short
包裝類:java.lang.Integer
包裝類:java.lang.Long
包裝類:java.lang.Float
包裝類:java.lang.Double
包裝類:java.lang.Character
Float和Double的最小值和最大值都是以科學記數法的形式輸出的,結尾的"E+數字"表示E之前的數字要乘以10的多少次方。比如3.14E3就是3.14 × 103 =3140,3.14E-3 就是 3.14 x 10-3 =0.00314。
實際上,JAVA中還存在另外一種基本型別void,它也有對應的包裝類 java.lang.Void,不過我們無法直接對它們進行操作。
引用型別
- 在Java中,引用型別的變數非常類似於C/C++的指標。引用型別指向一個物件,指向物件的變數是引用變數。這些變數在宣告時被指定為一個特定的型別,比如 Employee、Puppy 等。變數一旦聲明後,型別就不能被改變了。
- 物件、陣列都是引用資料型別。
- 所有引用型別的預設值都是null。
- 一個引用變數可以用來引用任何與之相容的型別。
- 例子:Site site = new Site("Runoob")。
Java 常量
常量在程式執行時是不能被修改的。
在 Java 中使用 final 關鍵字來修飾常量,宣告方式和變數類似:
final double PI = 3.1415927;
雖然常量名也可以用小寫,但為了便於識別,通常使用大寫字母表示常量。
字面量可以賦給任何內建型別的變數。例如:
byte a = 68; char a = 'A'
byte、int、long、和short都可以用十進位制、16進位制以及8進位制的方式來表示。
當使用常量的時候,字首 0 表示 8 進位制,而字首 0x 代表 16 進位制, 例如:
int decimal = 100; int octal = 0144; int hexa = 0x64;
和其他語言一樣,Java的字串常量也是包含在兩個引號之間的字元序列。下面是字串型字面量的例子:
"Hello World" "two\nlines" "\"This is in quotes\""
字串常量和字元常量都可以包含任何Unicode字元。例如:
char a = '\u0001'; String a = "\u0001";
Java語言支援一些特殊的轉義字元序列。
符號 | 字元含義 |
---|---|
\n | 換行 (0x0a) |
\r | 回車 (0x0d) |
\f | 換頁符(0x0c) |
\b | 退格 (0x08) |
\0 | 空字元 (0x20) |
\s | 字串 |
\t | 製表符 |
\" | 雙引號 |
\' | 單引號 |
\\ | 反斜槓 |
\ddd | 八進位制字元 (ddd) |
\uxxxx | 16進位制Unicode字元 (xxxx) |
自動型別轉換
整型、實型(常量)、字元型資料可以混合運算。運算中,不同型別的資料先轉化為同一型別,然後進行運算。
轉換從低階到高階。
低 ------------------------------------> 高 byte,short,char—> int —> long—> float —> double
資料型別轉換必須滿足如下規則:
-
1. 不能對boolean型別進行型別轉換。
-
2. 不能把物件型別轉換成不相關類的物件。
-
3. 在把容量大的型別轉換為容量小的型別時必須使用強制型別轉換。
-
4. 轉換過程中可能導致溢位或損失精度,例如:
int i =128; byte b = (byte)i;
因為 byte 型別是 8 位,最大值為127,所以當 int 強制轉換為 byte 型別時,值 128 時候就會導致溢位。
-
5. 浮點數到整數的轉換是通過捨棄小數得到,而不是四捨五入,例如:
(int)23.7 == 23; (int)-45.89f == -45
自動型別轉換
必須滿足轉換前的資料型別的位數要低於轉換後的資料型別,例如: short資料型別的位數為16位,就可以自動轉換位數為32的int型別,同樣float資料型別的位數為32,可以自動轉換為64位的double型別。
例項
public class ZiDongLeiZhuan
{
public static void main(String[] args)
{
char c1='a';//定義一個char型別
int i1 = c1;//char自動型別轉換為int
System.out.println("char自動型別轉換為int後的值等於"+i1);
char c2 = 'A';//定義一個char型別
int i2 = c2+1;//char 型別和 int 型別計算
System.out.println("char型別和int計算後的值等於"+i2);
}
}
執行結果為:
char自動型別轉換為int後的值等於97 char型別和int計算後的值等於66
解析:c1 的值為字元 a ,查 ASCII 碼錶可知對應的 int 型別值為 97, A 對應值為 65,所以 i2=65+1=66。
強制型別轉換
1. 條件是轉換的資料型別必須是相容的。
2. 格式:(type)value type是要強制型別轉換後的資料型別
例項
public class QiangZhiZhuanHuan
{
public static void main(String[] args)
{
int i1 = 123; byte b = (byte)i1;//強制型別轉換為byte
System.out.println("int強制型別轉換為byte後的值等於"+b);
}
}
執行結果:
int強制型別轉換為byte後的值等於123
隱含強制型別轉換
-
1. 整數的預設型別是 int。
-
2. 浮點型不存在這種情況,因為在定義 float 型別時必須在數字後面跟上 F 或者 f。
Java 變數型別
在Java語言中,所有的變數在使用前必須宣告。宣告變數的基本格式如下:
type identifier [ = value][, identifier [= value] ...] ;
格式說明:type為Java資料型別。identifier是變數名。可以使用逗號隔開來宣告多個同類型變數。
以下列出了一些變數的宣告例項。注意有些包含了初始化過程。
int a, b, c; // 宣告三個int型整數:a、 b、c
int d = 3, e = 4, f = 5; // 宣告三個整數並賦予初值
byte z = 22; // 宣告並初始化 z
String s = "runoob"; // 宣告並初始化字串 s
double pi = 3.14159; // 聲明瞭雙精度浮點型變數 pi
char x = 'x'; // 宣告變數 x 的值是字元 'x'。
Java語言支援的變數型別有:
- 類變數:獨立於方法之外的變數,用 static 修飾。
- 例項變數:獨立於方法之外的變數,不過沒有 static 修飾。
- 區域性變數:類的方法中的變數。
例項
public class Variable
{
static int allClicks=0; // 類變數
String str="hello world"; // 例項變數
public void method()
{
int i =0; // 區域性變數
}
}
Java 區域性變數
- 區域性變數宣告在方法、構造方法或者語句塊中;
- 區域性變數在方法、構造方法、或者語句塊被執行的時候建立,當它們執行完成後,變數將會被銷燬;
- 訪問修飾符不能用於區域性變數;
- 區域性變數只在宣告它的方法、構造方法或者語句塊中可見;
- 區域性變數是在棧上分配的。
- 區域性變數沒有預設值,所以區域性變數被聲明後,必須經過初始化,才可以使用。
例項 1
在以下例項中age是一個區域性變數。定義在pupAge()方法中,它的作用域就限制在這個方法中。
package com.runoob.test;
public class Test{
public void pupAge()
{
int age = 0;
age = age + 7;
System.out.println("小狗的年齡是: " + age);
}
public static void main(String[] args)
{
Test test = new Test();
test.pupAge();
}
}
以上例項編譯執行結果如下:
小狗的年齡是: 7
例項 2
在下面的例子中 age 變數沒有初始化,所以在編譯時會出錯:
package com.runoob.test;
public class Test
{
public void pupAge()
{
int age;
age = age + 7;
System.out.println("小狗的年齡是 : " + age);
}
public static void main(String[] args)
{
Test test = new Test();
test.pupAge();
}
}
以上例項編譯執行結果如下:
Test.java:4:variable number might not have been initialized age = age + 7; ^ 1 error
例項變數
- 例項變數宣告在一個類中,但在方法、構造方法和語句塊之外;
- 當一個物件被例項化之後,每個例項變數的值就跟著確定;
- 例項變數在物件建立的時候建立,在物件被銷燬的時候銷燬;
- 例項變數的值應該至少被一個方法、構造方法或者語句塊引用,使得外部能夠通過這些方式獲取例項變數資訊;
- 例項變數可以宣告在使用前或者使用後;
- 訪問修飾符可以修飾例項變數;
- 例項變數對於類中的方法、構造方法或者語句塊是可見的。一般情況下應該把例項變數設為私有。通過使用訪問修飾符可以使例項變數對子類可見;
- 例項變數具有預設值。數值型變數的預設值是0,布林型變數的預設值是false,引用型別變數的預設值是null。變數的值可以在宣告時指定,也可以在構造方法中指定;
- 例項變數可以直接通過變數名訪問。但在靜態方法以及其他類中,就應該使用完全限定名:ObejectReference.VariableName。
例項
Employee.java 檔案程式碼:
import java.io.*;
public class Employee
{
// 這個例項變數對子類可見
public String name;
// 私有變數,僅在該類可見
private double salary;
//在構造器中對name賦值
public Employee (String empName)
{
name = empName;
}
//設定salary的值
public void setSalary(double empSal)
{
salary = empSal;
}
// 列印資訊
public void printEmp()
{
System.out.println("名字 : " + name );
System.out.println("薪水 : " + salary);
}
public static void main(String[] args)
{
Employee empOne = new Employee("RUNOOB");
empOne.setSalary(1000);
empOne.printEmp();
}
}
以上例項編譯執行結果如下:
$ javac Employee.java $ java Employee 名字 : RUNOOB 薪水 : 1000.0
類變數(靜態變數)
- 類變數也稱為靜態變數,在類中以static關鍵字宣告,但必須在方法構造方法和語句塊之外。
- 無論一個類建立了多少個物件,類只擁有類變數的一份拷貝。
- 靜態變數除了被宣告為常量外很少使用。常量是指宣告為public/private,final和static型別的變數。常量初始化後不可改變。
- 靜態變數儲存在靜態儲存區。經常被宣告為常量,很少單獨使用static宣告變數。
- 靜態變數在第一次被訪問時建立,在程式結束時銷燬。
- 與例項變數具有相似的可見性。但為了對類的使用者可見,大多數靜態變數宣告為public型別。
- 預設值和例項變數相似。數值型變數預設值是0,布林型預設值是false,引用型別預設值是null。變數的值可以在宣告的時候指定,也可以在構造方法中指定。此外,靜態變數還可以在靜態語句塊中初始化。
- 靜態變數可以通過:ClassName.VariableName的方式訪問。
- 類變數被宣告為public static final型別時,類變數名稱一般建議使用大寫字母。如果靜態變數不是public和final型別,其命名方式與例項變數以及區域性變數的命名方式一致。
Java 修飾符
Java語言提供了很多修飾符,主要分為以下兩類:
- 訪問修飾符
- 非訪問修飾符
修飾符用來定義類、方法或者變數,通常放在語句的最前端。我們通過下面的例子來說明:
public class className { // ... }
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) { // 方法體 }
訪問控制修飾符
Java中,可以使用訪問控制符來保護對類、變數、方法和構造方法的訪問。Java 支援 4 種不同的訪問許可權。
-
default (即預設,什麼也不寫): 在同一包內可見,不使用任何修飾符。使用物件:類、介面、變數、方法。
-
private : 在同一類內可見。使用物件:變數、方法。 注意:不能修飾類(外部類)
-
public : 對所有類可見。使用物件:類、介面、變數、方法
-
protected : 對同一包內的類和所有子類可見。使用物件:變數、方法。 注意:不能修飾類(外部類)。
我們可以通過以下表來說明訪問許可權:
修飾符 | 當前類 | 同一包內 | 子孫類(同一包) | 子孫類(不同包) | 其他包 |
---|---|---|---|---|---|
public |
Y | Y | Y | Y | Y |
protected |
Y | Y | Y | Y/N(說明) | N |
default |
Y | Y | Y | N | N |
private |
Y | N | N | N | N |
預設訪問修飾符-不使用任何關鍵字
使用預設訪問修飾符宣告的變數和方法,對同一個包內的類是可見的。接口裡的變數都隱式宣告為 public static final,而接口裡的方法預設情況下訪問許可權為 public。
如下例所示,變數和方法的宣告可以不使用任何修飾符。
例項
String version = "1.5.1";
boolean processOrder() { return true; }
私有訪問修飾符-private
私有訪問修飾符是最嚴格的訪問級別,所以被宣告為 private 的方法、變數和構造方法只能被所屬類訪問,並且類和介面不能宣告為 private。
宣告為私有訪問型別的變數只能通過類中公共的 getter 方法被外部類訪問。
Private 訪問修飾符的使用主要用來隱藏類的實現細節和保護類的資料。
下面的類使用了私有訪問修飾符:
public class Logger
{
private String format;
public String getFormat()
{
return this.format;
}
public void setFormat(String format)
{
this.format = format;
}
}
例項中,Logger 類中的 format 變數為私有變數,所以其他類不能直接得到和設定該變數的值。為了使其他類能夠操作該變數,定義了兩個 public 方法:getFormat() (返回 format的值)和 setFormat(String)(設定 format 的值)
公有訪問修飾符-public
被宣告為 public 的類、方法、構造方法和介面能夠被任何其他類訪問。
如果幾個相互訪問的 public 類分佈在不同的包中,則需要匯入相應 public 類所在的包。由於類的繼承性,類所有的公有方法和變數都能被其子類繼承。
以下函式使用了公有訪問控制:
public static void main(String[] arguments) { // ... }
Java 程式的 main() 方法必須設定成公有的,否則,Java 直譯器將不能執行該類。
受保護的訪問修飾符-protected
protected 需要從以下兩個點來分析說明:
-
子類與基類在同一包中:被宣告為 protected 的變數、方法和構造器能被同一個包中的任何其他類訪問;
-
子類與基類不在同一包中:那麼在子類中,子類例項可以訪問其從基類繼承而來的 protected 方法,而不能訪問基類例項的protected方法。
protected 可以修飾資料成員,構造方法,方法成員,不能修飾類(內部類除外)。
介面及介面的成員變數和成員方法不能宣告為 protected。
子類能訪問 protected 修飾符宣告的方法和變數,這樣就能保護不相關的類使用這些方法和變數。
訪問控制和繼承
請注意以下方法繼承的規則:
-
父類中宣告為 public 的方法在子類中也必須為 public。
-
父類中宣告為 protected 的方法在子類中要麼宣告為 protected,要麼宣告為 public,不能宣告為 private。
-
父類中宣告為 private 的方法,不能夠被繼承。
非訪問修飾符
為了實現一些其他的功能,Java 也提供了許多非訪問修飾符。
static 修飾符,用來修飾類方法和類變數。
final 修飾符,用來修飾類、方法和變數,final 修飾的類不能夠被繼承,修飾的方法不能被繼承類重新定義,修飾的變數為常量,是不可修改的。
abstract 修飾符,用來建立抽象類和抽象方法。
synchronized 和 volatile 修飾符,主要用於執行緒的程式設計。
static 修飾符
-
靜態變數:
static 關鍵字用來宣告獨立於物件的靜態變數,無論一個類例項化多少物件,它的靜態變數只有一份拷貝。 靜態變數也被稱為類變數。區域性變數不能被宣告為 static 變數。
-
靜態方法:
static 關鍵字用來宣告獨立於物件的靜態方法。靜態方法不能使用類的非靜態變數。靜態方法從引數列表得到資料,然後計算這些資料。
對類變數和方法的訪問可以直接使用 classname.variablename 和 classname.methodname 的方式訪問。
final 修飾符
final 變數:
final 表示"最後的、最終的"含義,變數一旦賦值後,不能被重新賦值。被 final 修飾的例項變數必須顯式指定初始值。
final 修飾符通常和 static 修飾符一起使用來建立類常量。
final 方法
類中的 final 方法可以被子類繼承,但是不能被子類修改。
宣告 final 方法的主要目的是防止該方法的內容被修改。
final 類
final 類不能被繼承,沒有類能夠繼承 final 類的任何特性。
abstract 修飾符
抽象類:
抽象類不能用來例項化物件,宣告抽象類的唯一目的是為了將來對該類進行擴充。
一個類不能同時被 abstract 和 final 修飾。如果一個類包含抽象方法,那麼該類一定要宣告為抽象類,否則將出現編譯錯誤。
抽象類可以包含抽象方法和非抽象方法。
抽象方法
抽象方法是一種沒有任何實現的方法,該方法的的具體實現由子類提供。
抽象方法不能被宣告成 final 和 static。
任何繼承抽象類的子類必須實現父類的所有抽象方法,除非該子類也是抽象類。
如果一個類包含若干個抽象方法,那麼該類必須宣告為抽象類。抽象類可以不包含抽象方法。
抽象方法的宣告以分號結尾,例如:public abstract sample();。
synchronized 修飾符
synchronized 關鍵字宣告的方法同一時間只能被一個執行緒訪問。synchronized 修飾符可以應用於四個訪問修飾符。
transient 修飾符
序列化的物件包含被 transient 修飾的例項變數時,java 虛擬機器(JVM)跳過該特定的變數。
該修飾符包含在定義變數的語句中,用來預處理類和變數的資料型別。
例項
public transient int limit = 55; // 不會持久化
public int b; // 持久化
volatile 修飾符
volatile 修飾的成員變數在每次被執行緒訪問時,都強制從共享記憶體中重新讀取該成員變數的值。而且,當成員變數發生變化時,會強制執行緒將變化值回寫到共享記憶體。這樣在任何時刻,兩個不同的執行緒總是看到某個成員變數的同一個值。
一個 volatile 物件引用可能是 null。
例項
public class MyRunnable implements Runnable
{
private volatile boolean active;
public void run()
{
active = true;
while (active) { //第一行程式碼 }
}
public void stop()
{
active = false; // 第二行
}
}
通常情況下,在一個執行緒呼叫 run() 方法(在 Runnable 開啟的執行緒),在另一個執行緒呼叫 stop() 方法。 如果 第一行 中緩衝區的 active 值被使用,那麼在 第二行 的 active 值為 false 時迴圈不會停止。
但是以上程式碼中我們使用了 volatile 修飾 active,所以該迴圈會停止。
Java 運算子
計算機的最基本用途之一就是執行數學運算,作為一門計算機語言,Java也提供了一套豐富的運算子來操縱變數。我們可以把運算子分成以下幾組:
- 算術運算子
- 關係運算符
- 位運算子
- 邏輯運算子
- 賦值運算子
- 其他運算子
算術運算子
算術運算子用在數學表示式中,它們的作用和在數學中的作用一樣。下表列出了所有的算術運算子。
表格中的例項假設整數變數A的值為10,變數B的值為20:
操作符 | 描述 | 例子 |
---|---|---|
+ | 加法 - 相加運算子兩側的值 | A + B 等於 30 |
- | 減法 - 左運算元減去右運算元 | A – B 等於 -10 |
* | 乘法 - 相乘操作符兩側的值 | A * B等於200 |
/ | 除法 - 左運算元除以右運算元 | B / A等於2 |
% | 取餘 - 左運算元除以右運算元的餘數 | B%A等於0 |
++ | 自增: 運算元的值增加1 | B++ 或 ++B 等於 21(區別詳見下文) |
-- | 自減: 運算元的值減少1 | B-- 或 --B 等於 19(區別詳見下文) |
自增自減運算子
1、自增(++)自減(--)運算子是一種特殊的算術運算子,在算術運算子中需要兩個運算元來進行運算,而自增自減運算子是一個運算元。
例項
int a = 3;//定義一個變數;
int b = ++a;//自增運算 b = 4
int c = 3;
int d = --c;//自減運算 c = 2
解析:
-
int b = ++a; 拆分運算過程為: a=a+1=4; b=a=4, 最後結果為b=4,a=4
-
int d = --c; 拆分運算過程為: c=c-1=2; d=c=2, 最後結果為d=2,c=2
2、字首自增自減法(++a,--a): 先進行自增或者自減運算,再進行表示式運算。
3、字尾自增自減法(a++,a--): 先進行表示式運算,再進行自增或者自減運算
例項
public class selfAddMinus{
public static void main(String[] args){
int a = 5;//定義一個變數;