1. 程式人生 > >JAVA多型/封裝/介面/包/包的命名規則——java面向物件

JAVA多型/封裝/介面/包/包的命名規則——java面向物件

Java 多型

多型是同一個行為具有多個不同表現形式或形態的能力。

多型的優點

  1. 消除型別之間的耦合關係
  2. 可替換性
  3. 可擴充性
  4. 介面性
  5. 靈活性
  6. 簡化性

多型存在的三個必要條件

繼承
重寫
父類引用指向子類物件
比如:
Parent p = new Child();
當使用多型方式呼叫方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去呼叫子類的同名方法。
多型的好處:可以使程式有良好的擴充套件,並可以對所有類的物件進行通用處理。

虛方法

我們將介紹在Java中,當設計類時,被重寫的方法的行為怎樣影響多型性。
我們已經討論了方法的重寫,也就是子類能夠重寫父類的方法。
當子類物件呼叫重寫的方法時,呼叫的是子類的方法,而不是父類中被重寫的方法。
要想呼叫父類中被重寫的方法,則必須使用關鍵字super。

多型的實現方式

方式一:重寫:
方式二:介面
方式三:抽象類和抽象方法

Java 抽象類

在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,並不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類。
抽象類除了不能例項化物件之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣。
由於抽象類不能例項化物件,所以抽象類必須被繼承,才能被使用。也是因為這個原因,通常在設計階段決定要不要設計抽象類。
父類包含了子類集合的常見的方法,但是由於父類本身是抽象的,所以不能使用這些方法。
在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

抽象類

在Java語言中使用abstract class來定義抽象類

抽象方法

如果你想設計這樣一個類,該類包含一個特別的成員方法,該方法的具體實現由它的子類確定,那麼你可以在父類中宣告該方法為抽象方法。
Abstract關鍵字同樣可以用來宣告抽象方法,抽象方法只包含一個方法名,而沒有方法體。
抽象方法沒有定義,方法名後面直接跟一個分號,而不是花括號。
宣告抽象方法會造成以下兩個結果:
如果一個類包含抽象方法,那麼該類必須是抽象類。
任何子類必須重寫父類的抽象方法,或者宣告自身為抽象類。
繼承抽象方法的子類必須重寫該方法。否則,該子類也必須宣告為抽象類。最終,必須有子類實現該抽象方法,否則,從最初的父類到最終的子類都不能用來例項化物件。

抽象類總結規定

  1. 抽象類不能被例項化(初學者很容易犯的錯),如果被例項化,就會報錯,編譯無法通過。只有抽象類的非抽象子類可以建立物件。
  2. 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
  3. 抽象類中的抽象方法只是宣告,不包含方法體,就是不給出方法的具體實現也就是方法的具體功能。
  4. 構造方法,類方法(用static修飾的方法)不能宣告為抽象方法。
  5. 抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類

Java 封裝

在面向物件程式設計方法中,封裝(英語:Encapsulation)是指,一種將抽象性函式介面的實作細節部份包裝、隱藏起來的方法。
封裝可以被認為是一個保護屏障,防止該類的程式碼和資料被外部類定義的程式碼隨機訪問。
要訪問該類的程式碼和資料,必須通過嚴格的介面控制。
封裝最主要的功能在於我們能修改自己的實現程式碼,而不用修改那些呼叫我們程式碼的程式片段。
適當的封裝可以讓程式碼更容易理解與維護,也加強了程式碼的安全性。

封裝的優點

  1. 良好的封裝能夠減少耦合。
  2. 類內部的結構可以自由修改。
  3. 可以對成員變數進行更精確的控制。
  4. 隱藏資訊,實現細節。

重點內容實現Java封裝的步驟

  1. 修改屬性的可見性來限制對屬性的訪問(一般限制為private),例如:
    public class Person {
    private String name;
    private int age;
    }
    這段程式碼中,將 name 和 age 屬性設定為私有的,只能本類才能訪問,其他類都訪問不了,如此就對資訊進行了隱藏。
  2. 對每個值屬性提供對外的公共方法訪問,也就是建立一對賦取值方法,用於對私有屬性的訪問,例如:
    public class Person{
    private String name;
    private int age;

    public int getAge(){
    return age;
    }

    public String getName(){
    return name;
    }

    public void setAge(int age){
    this.age = age;
    }

    public void setName(String name){
    this.name = name;
    }
    }
    採用 this 關鍵字是為了解決例項變數(private String name)和區域性變數(setName(String name)中的name變數)之間發生的同名的衝突。

Java 介面

介面(英文:Interface),在JAVA程式語言中是一個抽象型別,是抽象方法的集合,介面通常以interface來宣告。一個類通過繼承介面的方式,從而來繼承介面的抽象方法。
介面並不是類,編寫介面的方式和類很相似,但是它們屬於不同的概念。類描述物件的屬性和方法。介面則包含類要實現的方法。
除非實現介面的類是抽象類,否則該類要定義介面中的所有方法。
介面無法被例項化,但是可以被實現。一個實現介面的類,必須實現介面內所描述的所有方法,否則就必須宣告為抽象類。另外,在 Java 中,介面型別可用來宣告一個變數,他們可以成為一個空指標,或是被繫結在一個以此介面實現的物件。

Java介面的作用與優點:

介面的最主要的作用是達到統一訪問,就是在建立物件的時候用介面建立,【介面名】 【物件名】=new 【實現介面的類】,這樣你像用哪個類的物件就可以new哪個物件了,不需要改原來的程式碼,就和你的USB介面一樣,插什麼讀什麼,就是這個原理。就像你問的,都有個method1的方法,如果我用介面,我上面就可以one.method1();是吧?那樣我new a();就是用a的方法,new b()就是用b的方法
這樣不方便嗎?
這個就叫統一訪問,因為你實現這個介面的類的方法名相同,但是實現內容不同
我用介面來定義物件不就可以做到統一訪問了嗎?介面主要針對多個類實現它來說的,要是隻有一個類當然可以不用介面了.你這樣想,我做一個USB介面,有個read()抽象方法,然後mp3類實現,U盤類實現,行動硬碟類實現,這樣我用的時候用USB a=new 【類名】;這樣a.read();要是我類名裡寫U盤,就讀U盤,寫mp3就讀mp3,而這個名字可以從屬性檔案裡讀,你寫哪個就用哪個了,呵呵。

介面與類相似點:

一個介面可以有多個方法。
介面檔案儲存在 .java 結尾的檔案中,檔名使用介面名。
介面的位元組碼檔案儲存在 .class 結尾的檔案中。
介面相應的位元組碼檔案必須在與包名稱相匹配的目錄結構中。

介面與類的區別:

介面不能用於例項化物件。
介面沒有構造方法。
介面中所有的方法必須是抽象方法。
介面不能包含成員變數,除了 static 和 final 變數。
介面不是被類繼承了,而是要被類實現。
介面支援多重繼承。

介面特性

介面中每一個方法也是隱式抽象的,介面中的方法會被隱式的指定為 public abstract(只能是 public abstract,其他修飾符都會報錯)。
介面中可以含有變數,但是介面中的變數會被隱式的指定為 public static final 變數(並且只能是 public,用 private 修飾會報編譯錯誤。
介面中的方法是不能在介面中實現的,只能由實現介面的類來實現介面中的方法。

抽象類和介面的區別

  1. 抽象類中的方法可以有方法體,就是能實現方法的具體功能,但是介面中的方法不行。
  2. 抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是 public static final 型別的。
  3. 介面中不能還有靜態程式碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態程式碼塊和靜態方法。
  4. 一個類只能繼承一個抽象類,而一個類卻可以實現多個介面。

介面的宣告

介面的宣告語法格式如下:
[可見度] interface 介面名稱 [extends 其他的類名] {
// 宣告變數
// 抽象方法
}

介面的實現

當類實現介面的時候,類要實現介面中所有的方法。否則,類必須宣告為抽象的類。
類使用implements關鍵字實現介面。在類宣告中,Implements關鍵字放在class聲明後面。
實現一個介面的語法,可以使用這個公式:
Animal.java 檔案程式碼:
…implements 介面名稱[, 其他介面, 其他介面…, …] …
重寫介面中宣告的方法時,需要注意以下規則:
類在實現介面的方法時,不能丟擲強制性異常,只能在介面中,或者繼承介面的抽象類中丟擲該強制性異常。
類在重寫方法時要保持一致的方法名,並且應該保持相同或者相相容的返回值型別。
如果實現介面的類是抽象類,那麼就沒必要實現該介面的方法。
在實現介面的時候,也要注意一些規則:
一個類可以同時實現多個介面。
一個類只能繼承一個類,但是能實現多個介面。
一個介面能繼承另一個介面,這和類之間的繼承比較相似。

介面的繼承

一個介面能繼承另一個介面,和類之間的繼承方式比較相似。介面的繼承使用extends關鍵字,子介面繼承父介面的方法。

介面的多重繼承

在Java中,類的多重繼承是不合法,但介面允許多重繼承,。
在介面的多重繼承中extends關鍵字只需要使用一次,在其後跟著繼承介面。 如下所示:
public interface Hockey extends Sports, Event
以上的程式片段是合法定義的子介面,與類不同的是,介面允許多重繼承,而 Sports及 Event 可能定義或是繼承相同的方法

標記介面

最常用的繼承介面是沒有包含任何方法的介面。
標識介面是沒有任何方法和屬性的介面.它僅僅表明它的類屬於一個特定的型別,供其他程式碼來測試允許做一些事情。
標識介面作用:簡單形象的說就是給某個物件打個標(蓋個戳),使物件擁有某個或某些特權。
例如:java.awt.event 包中的 MouseListener 介面繼承的 java.util.EventListener 介面定義如下:
package java.util;
public interface EventListener
{}
沒有任何方法的介面被稱為標記介面。標記介面主要用於以下兩種目的:
1.建立一個公共的父介面:
正如EventListener介面,這是由幾十個其他介面擴充套件的Java API,你可以使用一個標記介面來建立一組介面的父介面。例如:當一個介面繼承了EventListener介面,Java虛擬機器(JVM)就知道該介面將要被用於一個事件的代理方案。
2.向一個類新增資料型別:
這種情況是標記介面最初的目的,實現標記介面的類不需要定義任何介面方法(因為標記介面根本就沒有方法),但是該類通過多型性變成一個介面型別。

Java 包(package)

為了更好地組織類,Java 提供了包機制,用於區別類名的名稱空間。

包的作用

1、把功能相似或相關的類或介面組織在同一個包中,方便類的查詢和使用。
2、如同資料夾一樣,包也採用了樹形目錄的儲存方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時呼叫兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字衝突。
3、包也限定了訪問許可權,擁有包訪問許可權的類才能訪問某個包中的類。
Java 使用包(package)這種機制是為了防止命名衝突,訪問控制,提供搜尋和定位類(class)、介面、列舉(enumerations)和註釋(annotation)等。

包語句的語法格式為:

package pkg1[.pkg2[.pkg3…]];
例如,一個Something.java 檔案它的內容
package net.java.util
public class Something{

}
那麼它的路徑應該是 net/java/util/Something.java 這樣儲存的。 package(包) 的作用是把不同的 java 程式分類儲存,更方便的被其他java 程式呼叫。
一個包(package)可以定義為一組相互聯絡的型別(類、介面、列舉和註釋),為這些型別提供訪問保護和名稱空間管理的功能。
以下是一些 Java 中的包:
1.java.lang-打包基礎的類
2.java.io-包含輸入輸出功能的函式
開發者可以自己把一組類和介面等打包,並定義自己的包。而且在實際開發中這樣做是值得提倡的,當你自己完成類的實現之後,將相關的類分組,可以讓其他的程式設計者更容易地確定哪些類、介面、列舉和註釋等是相關的。
由於包建立了新的名稱空間(namespace),所以不會跟其他包中的任何名字產生命名衝突。使用包這種機制,更容易實現訪問控制,並且讓定位相關類更加簡單。

建立包

建立包的時候,你需要為這個包取一個合適的名字。之後,如果其他的一個原始檔包含了這個包提供的類、介面、列舉或者註釋型別的時候,都必須將這個包的宣告放在這個原始檔的開頭。
包宣告應該在原始檔的第一行,每個原始檔只能有一個包宣告,這個檔案中的每個型別都應用於它。
如果一個原始檔中沒有使用包宣告,那麼其中的類,函式,列舉,註釋等將被放在一個無名的包(unnamed package)中。

import 關鍵字

為了能夠使用某一個包的成員,我們需要在 Java 程式中明確匯入該包。使用 “import” 語句可完成此功能。
在 java 原始檔中 import 語句應位於 package 語句之後,所有類的定義之前,可以沒有,也可以有多條,其語法格式為:
import package1[.package2…].(classname|*);
如果在一個包中,一個類想要使用本包中的另一個類,那麼該包名可以省略。

package 的目錄結構

類放在包中會有兩種主要的結果:
包名成為類名的一部分,正如我們前面討論的一樣。
包名必須與相應的位元組碼所在的目錄結構相吻合。
下面是管理你自己 java 中檔案的一種簡單方式:
將類、介面等型別的原始碼放在一個文字中,這個檔案的名字就是這個型別的名字,並以.java作為副檔名。例如:
// 檔名 : Car.java

package vehicle;

public class Car {
// 類實現
}
接下來,把原始檔放在一個目錄中,這個目錄要對應類所在包的名字。
….\vehicle\Car.java
現在,正確的類名和路徑將會是如下樣子:
類名 -> vehicle.Car
路徑名 -> vehicle\Car.java (在 windows 系統中)
通常,一個公司使用它網際網路域名的顛倒形式來作為它的包名.例如:網際網路域名是 xxxxx.com,所有的包名都以 com.xxxxx開頭。包名中的每一個部分對應一個子目錄。
例如:有一個 com.xxxxxx.test 的包,這個包包含一個叫做 Sites.java 的原始檔,那麼相應的,應該有如下面的一連串子目錄:
….\com\xxxxxx\test\Sites.java
編譯的時候,編譯器為包中定義的每個類、介面等型別各建立一個不同的輸出檔案,輸出檔案的名字就是這個型別的名字,並加上 .class 作為擴充套件字尾。 例如:
// 檔名: Site.java

package com.xxxxx.test;
public class xxxxxx{

}
class Google {

}
現在,我們用-d選項來編譯這個檔案,如下:
$javac -d . xxxxxx.java
這樣會像下面這樣放置編譯了的檔案:
.\com\xxxxx\test\xxxxx.class
.\com\xxxxxx\test\Google.class
你可以像下面這樣來匯入所有 \com\xxxxxx\test\ 中定義的類、介面等:
import com.xxxxxx.test.*;
編譯之後的 .class 檔案應該和 .java 原始檔一樣,它們放置的目錄應該跟包的名字對應起來。但是,並不要求 .class 檔案的路徑跟相應的 .java 的路徑一樣。你可以分開來安排原始碼和類的目錄。
\sources\com\xxxxx\test\xxxxx.java
\classes\com\xxxxx\test\Google.class
這樣,你可以將你的類目錄分享給其他的程式設計人員,而不用透露自己的原始碼。用這種方法管理原始碼和類檔案可以讓編譯器和java 虛擬機器(JVM)可以找到你程式中使用的所有型別。
類目錄的絕對路徑叫做 class path。設定在系統變數 CLASSPATH 中。編譯器和 java 虛擬機器通過將 package 名字加到 class path 後來構造 .class 檔案的路徑。
\classes 是 class path,package 名字是 com.runoob.test,而編譯器和 JVM 會在 \classes\com\runoob\test 中找 .class 檔案。
一個 class path 可能會包含好幾個路徑,多路徑應該用分隔符分開。預設情況下,編譯器和 JVM 查詢當前目錄。JAR 檔案按包含 Java 平臺相關的類,所以他們的目錄預設放在了 class path 中。

設定 CLASSPATH 系統變數

用下面的命令顯示當前的CLASSPATH變數:
Windows 平臺(DOS 命令列下):C:> set CLASSPATH
UNIX 平臺(Bourne shell 下):# echo $CLASSPATH
刪除當前CLASSPATH變數內容:
Windows 平臺(DOS 命令列下):C:> set CLASSPATH=
UNIX 平臺(Bourne shell 下):# unset CLASSPATH; export CLASSPATH
設定CLASSPATH變數:
Windows 平臺(DOS 命令列下): C:> set CLASSPATH=C:\users\jack\java\classes
UNIX 平臺(Bourne shell 下):# CLASSPATH=/home/jack/java/classes; export CLASSPATH

#Java包(package)的命名規範,java中package命名規則
Java的包名都有小寫單片語成,類名首字母大寫;包的路徑符合所開發的 系統模組的 定義,比如生產對生產,物資對物資,基礎類對基礎類。以便看了包名就明白是哪個模組,從而直接到對應包裡找相應的實現。

由於Java面向物件的特性,每名Java開發人員都可以編寫屬於自己的Java Package,為了保障每個Java Package命名的唯一性,在最新的Java程式設計規範中,要求開發人員在自己定義的包名前加上唯一的字首。由於網際網路上的域名稱是不會重複的,所以多數開發人員採用自己公司在網際網路上的域名稱作為自己程式包的唯一字首。例如: com.sun.swt.……。

從而,我們知道,一般公司命名為“com.公司名.專案名.模組名....”。
那,我們個人的專案又怎麼命名呢?
經過我對“個人的”單詞搜尋,有“individual、personal、private、one-man”,進一步對以上4個單詞詞意的分析,並在保證了唯一性,使用每個單詞的前4個字母作為字首,正好和“com”也做了區分。如下:
indi :
     個體專案,指個人發起,但非自己獨自完成的專案,可公開或私有專案,copyright主要屬於發起者。
     包名為“indi.發起者名.專案名.模組名.……”。
pers :
     個人專案,指個人發起,獨自完成,可分享的專案,copyright主要屬於個人。
     包名為“pers.個人名.專案名.模組名.……”。
priv :
     私有專案,指個人發起,獨自完成,非公開的私人使用的專案,copyright屬於個人。
     包名為“priv.個人名.專案名.模組名.……”。
onem :
     與“indi”相同,推薦使用“indi”。

另外,我為了區分團隊專案和前面所說專案的區分,還有了一下擴充套件:
team :
     團隊專案,指由團隊發起,並由該團隊開發的專案,copyright屬於該團隊所有。
     包名為“team.團隊名.專案名.模組名.……”。
com :

公司專案,copyright由專案發起的公司所有。
包名為“com.公司名.專案名.模組名.……”。