Java作爲一門面向對象編程語言,支持以下基本特性:
- 多態
- 繼承
- 封裝
- 抽象
- 類
- 對象
- 實例
- 方法
- 消息傳遞
這一節,我們一起來學習這兩個基本概念:類和對象。回顧一下上一節中我們提到的基本概念:
- 對象 - 對象包含狀態和行爲。例如,一隻小狗是一個對象,它具有的狀態有顏色、名字和品種,以及具有的行爲有搖尾巴、犬吠和吃東西等。對象是類的實例。
- 類 - 類可以被理解爲一個模板或藍圖,用於描述對象支持的類型、描述對象的行爲和狀態。
Java中的對象
讓我們來更深入地學習一下什麼是對象。在我們的現實生活中,有很多的東西都是對象,例如貓,狗和人等等,所有這些對象都有狀態和行爲屬性。
比如說,狗的狀態屬性有:名字,品種,顏色;行爲屬性有:犬吠,搖尾巴,奔跑。
軟件中的對象和現實生活中對象的概念特徵非常相似。軟件中的對象同樣有狀態和行爲屬性,狀態存放於字段中,而行爲通過方法來展示。因此,在軟件開發中,方法操作對象內部的狀態,同時,對象間的通信也通過方法來完成。
Java中的類
我們在上一節中提到過,類可以被理解爲一個模板或藍圖,而對象就是根據類這個模板創建的。
下面這段代碼展示的是一個簡單的類。
public class Dog {
String breed;
int age;
String color;
void barking() {
}
void hungry() {
}
void sleeping() {
}
}
類可以包含下面這幾種的變量類型:
- 局部變量 - 定義在方法、構造器和代碼塊中的變量被稱爲局部變量。局部變量會在隨方法申明和初始化,並在方法執行完成的時候被銷燬
- 實例變量 - 實例變量是在類中、方法外的變量。實例變量會隨着類的初始化而初始化,能被類中的任意方法、構造器和代碼塊訪問。
- 類變量 - 類變量是定義在類中、方法外,且被static關鍵字定義的變量。
一個類中可以有任意個方法,方法也可以定義成不同的訪問類型。上面的代碼中,barking(),hungry()和sleeping()都是方法。
下面,我們來看一下Java類中比較重要的幾個概念。
構造器
當我們討論類的時候,有幾個比較重要的概念需要着重關注,構造器就是其中的一個。構造器也叫構造函數,每個類中都有構造器,如果在一個類中我們不明確地寫一個構造器的話,Java編譯器會爲這個類創建一個默認的構造器。
每當一個新的對象被創建時,至少有一個構造器會被調用,來初始化新建的對象。需要注意的是,一個類可以有多個構造器,但必須有一個構造器和類的命名相同。
下面是一個構造器的例子。
構造器例子
public class Puppy {
public Puppy() {
}
public Puppy(String name) {
//這個構造器有一個參數:name
}
}
和許多編程語言一樣,Java也支持單例模式,也就是說你只能對單例模式的類創建一個實例。
注意:構造器有兩種不同的類型,我們會在後面的章節中詳細討論構造器。
創建一個對象
前面提到了,類爲對象提供了藍圖。因此,基本上可以說,對象是由類創建而來。在Java中,創建新的對象時,使用關鍵字“new”。
從類創建對象時有3個步驟:
- 聲明 - 變量聲明時需要聲明變量名和類型
- 實例化 - 使用關鍵字“new”來創建對象
- 初始化 - 關鍵字“new”後面跟着構造器,這就是新對象的初始化。
下面是創建對象的一個例子:
public class Puppy {
public Puppy(String name) {
//這個構造器有一個參數:name
System.out.println("傳入的name是 :" + name );
}
public static void main(String []args) {
//創建一個對象:myPuppy
Puppy myPuppy = new Puppy( "tommy" );
}
}
在編譯和運行上面程序後,會輸出:
Passed Name is :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("Puppy的年齡是 :" + puppyAge );
return puppyAge;
}
public static void main(String []args) {
/* 創建對象 */
Puppy myPuppy = new Puppy( "tommy" );
/* 調用類的方法來設置年齡 */
myPuppy.setAge( 2 );
/* 調用類的另一個方法來獲取年齡 */
myPuppy.getAge( );
/* 同樣可以這樣訪問實例變量 */
System.out.println("變量值是 :" + myPuppy.puppyAge );
}
}
編譯和運行後,輸出的結果爲:
選擇的名字是 :tommy
Puppy的年齡是 :2
變量值是 :2
源代碼文件聲明規則
在本節的最後,我們來看一下源代碼文件的聲明規則。當我們在源文件充聲明類,使用import語句和package語句時,這些語法規則都是必須遵守的。
- 在一個源文件中,只能定義一個公共類(public class)
- 一個源文件中,可以有多個非公共類(non-public class)
- 源文件的名字應該和公共類的名字相同,只在最後多個“.java”的後綴。例如,類名是public class Employee{},那麼源文件名字就應該是:Employee.java
- 如果類是定義在包裏面的,那麼package語句就應該在源文件的第一行。
- 如果文件中有引用其它開發包,那麼import語句應該放在package語句和定義類的語句中間。如果沒有引用其它開發包,那麼import語句應該位於源文件的第一行。
- import和package語句將會隱含適用到源文件中的所有類中,同一個源文件中的類不可能會聲明不同的import和package語句。
類可以定義成不同的訪問級別,並且類也有幾種不同類型:抽象類和finale類等等。我們將在訪問修飾符章節中解釋這些概念。除了這些類型的類,Java也有一些特殊的類,例如,內部類和匿名類。
Java包
簡單地來說,包是用來對類和接口進行分類的。當開發Java程序時,會有成百上千的類和接口會被編寫在程序中,因此我們必須給這些類進行分類,由此讓開發工作變得更簡單些。
Import語句
在Java中,只要提供完整的名字(包括報名和類名),編譯器就可以輕鬆地定位到源代碼和類。Import語句就是一種爲編譯器提供正確路徑來定位指定類的方法。
舉個例子,編譯器執行到下面這一行import語句時,將會把包java/io下所有可訪問的類加載出來:
import java.io.*;
一個簡單的案例分析
我們創建兩個類來進行案例分析:Employee和EmployeeTest。
首先,創建一個java文件,把下面的代碼複製到文件中。需要注意的是,下面這段代碼是Employee類,並且是一個公共類,因此保存文件後需要把文件名修改爲和類名一致:Employee.java
Employee類裏有4個實例變量:name,age,designation和salary。類裏有一個明確定義的構造器,構造器有一個傳入參數。
import java.io.*;
public class Employee {
String name;
int age;
String designation;
double salary;
//這是類Employee的構造器
public Employee(String name) {
this.name = name;
}
//給Employee的age變量賦值
public void empAge(int empAge) {
age = empAge;
}
/*給designation變量賦值*/
public void empDesignation(String empDesig) {
designation = empDesig;
}
/*給salary變量賦值*/
public void empSalary(double empSalary) {
salary = empSalary;
}
/*打印Employee的詳情*/
public void printEmployee() {
System.out.println("Name:"+ name );
System.out.println("Age:" + age );
System.out.println("Designation:" + designation );
System.out.println("Salary:" + salary);
}
}
我們的系列教程前面提到過,程序運行是從main函數開始的。因此,爲了運行Employee類,我們需要創建一個main方法和一個對象,我們在一個新的類中完成這兩個創建任務。
下面的EmployeeTest類創建了Employee類的兩個實例對象,並且調用了各自的方法來爲變量分別賦值。
將下面的代碼保存在EmployeeTest.java文件中。
import java.io.*;
public class EmployeeTest {
public static void main(String args[]) {
/* 使用構造器創建兩個對象 */
Employee empOne = new Employee("James Smith");
Employee empTwo = new Employee("Mary Anne");
//給創建的兩個對象調用方法
empOne.empAge(26);
empOne.empDesignation("Senior Software Engineer");
empOne.empSalary(1000);
empOne.printEmployee();
empTwo.empAge(21);
empTwo.empDesignation("Software Engineer");
empTwo.empSalary(500);
empTwo.printEmployee();
}
}
接着,編譯這兩個源文件然後運行EmployeeTest來看看運行結果:
C:\> javac Employee.java
C:\> javac EmployeeTest.java
C:\> java EmployeeTest
Name:James Smith
Age:26
Designation:Senior Software Engineer
Salary:1000.0
Name:Mary Anne
Age:21
Designation:Software Engineer
Salary:500.0
本篇小結
更多交流,歡迎加羣(584017112):