Java簡明教程系列(3) - 對象和類

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):

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章