在面向對象程式設計方法中,封裝(英語:Encapsulation)是指一種將抽象性函式接口的實現細節部份包裝、隱藏起來的方法。java
封裝能夠被認爲是一個保護屏障,防止該類的代碼和數據被外部類定義的代碼隨機訪問。shell
要訪問該類的代碼和數據,必須經過嚴格的接口控制。編程
封裝最主要的功能在於咱們能修改本身的實現代碼,而不用修改那些調用咱們代碼的程序片斷。windows
適當的封裝可讓程式碼更容易理解與維護,也增強了程式碼的安全性。安全
1. 良好的封裝可以減小耦合。編程語言
2. 類內部的結構能夠自由修改。ide
3. 能夠對成員變量進行更精確的控制。函數
4. 隱藏信息,實現細節。測試
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封裝類的例子:this
EncapTest.java 文件代碼: /* 文件名: EncapTest.java */ public class EncapTest{ private String name; private String idNum; private int age; public int getAge(){ return age; } public String getName(){ return name; } public String getIdNum(){ return idNum; } public void setAge( int newAge){ age = newAge; } public void setName(String newName){ name = newName; } public void setIdNum( String newId){ idNum = newId; } } 以上實例中public方法是外部類訪問該類成員變量的入口。 一般狀況下,這些方法被稱爲getter和setter方法。 所以,任何要訪問類中私有成員變量的類都要經過這些getter和setter方法。 經過以下的例子說明EncapTest類的變量怎樣被訪問: RunEncap.java 文件代碼: /* F文件名 : RunEncap.java */ public class RunEncap{ public static void main(String args[]){ EncapTest encap = new EncapTest(); encap.setName("James"); encap.setAge(20); encap.setIdNum("12343ms"); System.out.print("Name : " + encap.getName()+ " Age : "+ encap.getAge()); } } 以上代碼編譯運行結果以下: Name : James Age : 20
接口(英文:Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合,接口一般以interface來聲明。一個類經過繼承接口的方式,從而來繼承接口的抽象方法。
接口並非類,編寫接口的方式和類很類似,可是它們屬於不一樣的概念。類描述對象的屬性和方法。接口則包含類要實現的方法。
除非實現接口的類是抽象類,不然該類要定義接口中的全部方法。
接口沒法被實例化,可是能夠被實現。一個實現接口的類,必須實現接口內所描述的全部方法,不然就必須聲明爲抽象類。另外,在 Java 中,接口類型可用來聲明一個變量,他們能夠成爲一個空指針,或是被綁定在一個以此接口實現的對象。
接口的聲明語法格式以下:
[可見度] interface 接口名稱 [extends 其餘的接口名名] { // 聲明變量 // 抽象方法 } Interface關鍵字用來聲明一個接口。下面是接口聲明的一個簡單例子。 NameOfInterface.java 文件代碼: /* 文件名 : NameOfInterface.java */ import java.lang.*; //引入包 public interface NameOfInterface { //任何類型 final, static 字段 //抽象方法 }
接口有如下特性:
實例 Animal.java 文件代碼: /* 文件名 : Animal.java */ interface Animal { public void eat(); public void travel(); }
當類實現接口的時候,類要實現接口中全部的方法。不然,類必須聲明爲抽象的類。
類使用implements關鍵字實現接口。在類聲明中,Implements關鍵字放在class聲明後面。
實現一個接口的語法,可使用這個公式:...implements 接口名稱[, 其餘接口名稱, 其餘接口名稱..., ...] ...
實例 MammalInt.java 文件代碼: /* 文件名 : MammalInt.java */ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } } 以上實例編譯運行結果以下: Mammal eats Mammal travels
重寫接口中聲明的方法時,須要注意如下規則:
在實現接口的時候,也要注意一些規則:
一個接口能繼承另外一個接口,和類之間的繼承方式比較類似。接口的繼承使用extends關鍵字,子接口繼承父接口的方法。
下面的Sports接口被Hockey和Football接口繼承:
// 文件名: Sports.java public interface Sports { public void setHomeTeam(String name); public void setVisitingTeam(String name); } // 文件名: Football.java public interface Football extends Sports { public void homeTeamScored(int points); public void visitingTeamScored(int points); public void endOfQuarter(int quarter); } // 文件名: Hockey.java public interface Hockey extends Sports { public void homeGoalScored(); public void visitingGoalScored(); public void endOfPeriod(int period); public void overtimePeriod(int ot); } Hockey接口本身聲明瞭四個方法,從Sports接口繼承了兩個方法,這樣,實現Hockey接口的類須要實現六個方法。 類似的,實現Football接口的類須要實現五個方法,其中兩個來自於Sports接口。
在Java中,類的多繼承是不合法,但接口容許多繼承。
在接口的多繼承中extends關鍵字只須要使用一次,在其後跟着繼承接口。 以下所示:
public interface Hockey extends Sports, Event
以上的程序片斷是合法定義的子接口,與類不一樣的是,接口容許多繼承,而 Sports及 Event 可能定義或是繼承相同的方法
最經常使用的繼承接口是沒有包含任何方法的接口。
標記接口是沒有任何方法和屬性的接口.它僅僅代表它的類屬於一個特定的類型,供其餘代碼來測試容許作一些事情。
標記接口做用:簡單形象的說就是給某個對象打個標(蓋個戳),使對象擁有某個或某些特權。
例如:java.awt.event 包中的 MouseListener 接口繼承的 java.util.EventListener 接口定義以下:
package java.util; public interface EventListener {}
沒有任何方法的接口被稱爲標記接口。標記接口主要用於如下兩種目的:
正如EventListener接口,這是由幾十個其餘接口擴展的Java API,你可使用一個標記接口來創建一組接口的父接口。例如:當一個接口繼承了EventListener接口,Java虛擬機(JVM)就知道該接口將要被用於一個事件的代理方案。
這種狀況是標記接口最初的目的,實現標記接口的類不須要定義任何接口方法(由於標記接口根本就沒有方法),可是該類經過多態性變成一個接口類型。
爲了更好地組織類,Java 提供了包機制,用於區別類名的命名空間。
一、把功能類似或相關的類或接口組織在同一個包中,方便類的查找和使用。
二、如同文件夾同樣,包也採用了樹形目錄的存儲方式。同一個包中的類名字是不一樣的,不一樣的包中的類的名字是能夠相同的,當同時調用兩個不一樣包中相同類名的類時,應該加上包名加以區別。所以,包能夠避免名字衝突。
三、包也限定了訪問權限,擁有包訪問權限的類才能訪問某個包中的類。
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 中的包:
開發者能夠本身把一組類和接口等打包,並定義本身的包。並且在實際開發中這樣作是值得提倡的,當你本身完成類的實現以後,將相關的類分組,可讓其餘的編程者更容易地肯定哪些類、接口、枚舉和註釋等是相關的。
因爲包建立了新的命名空間(namespace),因此不會跟其餘包中的任何名字產生命名衝突。使用包這種機制,更容易實現訪問控制,而且讓定位相關類更加簡單。
建立包的時候,你須要爲這個包取一個合適的名字。以後,若是其餘的一個源文件包含了這個包提供的類、接口、枚舉或者註釋類型的時候,都必須將這個包的聲明放在這個源文件的開頭。
包聲明應該在源文件的第一行,每一個源文件只能有一個包聲明,這個文件中的每一個類型都應用於它。
若是一個源文件中沒有使用包聲明,那麼其中的類,函數,枚舉,註釋等將被放在一個無名的包(unnamed package)中。
例子 讓咱們來看一個例子,這個例子建立了一個叫作animals的包。一般使用小寫的字母來命名避免與類、接口名字的衝突。 在 animals 包中加入一個接口(interface): Animal.java 文件代碼: /* 文件名: Animal.java */ package animals; interface Animal { public void eat(); public void travel(); } 接下來,在同一個包中加入該接口的實現: MammalInt.java 文件代碼: package animals; /* 文件名 : MammalInt.java */ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } } 而後,編譯這兩個文件,並把他們放在一個叫作animals的子目錄中。 用下面的命令來運行: $ mkdir animals $ cp Animal.class MammalInt.class animals $ java animals/MammalInt Mammal eats Mammal travel
爲了可以使用某一個包的成員,咱們須要在 Java 程序中明確導入該包。使用 "import" 語句可完成此功能。
在 java 源文件中 import 語句應位於 package 語句以後,全部類的定義以前,能夠沒有,也能夠有多條,其語法格式爲:
import package1[.package2…].(classname|*);
若是在一個包中,一個類想要使用本包中的另外一個類,那麼該包名能夠省略。
例子 下面的 payroll 包已經包含了 Employee 類,接下來向 payroll 包中添加一個 Boss 類。Boss 類引用 Employee 類的時候能夠不用使用 payroll 前綴,Boss類的實例以下。 Boss.java 文件代碼: package payroll; public class Boss { public void payEmployee(Employee e) { e.mailCheck(); } } 若是 Boss 類不在 payroll 包中又會怎樣?Boss 類必須使用下面幾種方法之一來引用其餘包中的類。 使用類全名描述,例如: payroll.Employee 用 import 關鍵字引入,使用通配符 "*" import payroll.*; 使用 import 關鍵字引入 Employee 類: import payroll.Employee; 注意: 類文件中能夠包含任意數量的 import 聲明。import 聲明必須在包聲明以後,類聲明以前。
類放在包中會有兩種主要的結果:
下面是管理你本身 java 中文件的一種簡單方式: 將類、接口等類型的源碼放在一個文本中,這個文件的名字就是這個類型的名字,並以.java做爲擴展名。例如: // 文件名 : Car.java package vehicle; public class Car { // 類實現 } 接下來,把源文件放在一個目錄中,這個目錄要對應類所在包的名字。 ....\vehicle\Car.java 如今,正確的類名和路徑將會是以下樣子: 類名 -> vehicle.Car 路徑名 -> vehicle\Car.java (在 windows 系統中) 一般,一個公司使用它互聯網域名的顛倒形式來做爲它的包名.例如:互聯網域名是 runoob.com,全部的包名都以 com.runoob 開頭。包名中的每個部分對應一個子目錄。 例如:有一個 com.runoob.test 的包,這個包包含一個叫作 Runoob.java 的源文件,那麼相應的,應該有以下面的一連串子目錄: ....\com\runoob\test\Runoob.java 編譯的時候,編譯器爲包中定義的每一個類、接口等類型各建立一個不一樣的輸出文件,輸出文件的名字就是這個類型的名字,並加上 .class 做爲擴展後綴。 例如: // 文件名: Runoob.java package com.runoob.test; public class Runoob { } class Google { } 如今,咱們用-d選項來編譯這個文件,以下: $javac -d . Runoob.java 這樣會像下面這樣放置編譯了的文件: .\com\runoob\test\Runoob.class .\com\runoob\test\Google.class 你能夠像下面這樣來導入全部 \com\runoob\test\ 中定義的類、接口等: import com.runoob.test.*; 編譯以後的 .class 文件應該和 .java 源文件同樣,它們放置的目錄應該跟包的名字對應起來。可是,並不要求 .class 文件的路徑跟相應的 .java 的路徑同樣。你能夠分開來安排源碼和類的目錄。 <path-one>\sources\com\runoob\test\Runoob.java <path-two>\classes\com\runoob\test\Google.class 這樣,你能夠將你的類目錄分享給其餘的編程人員,而不用透露本身的源碼。用這種方法管理源碼和類文件可讓編譯器和java 虛擬機(JVM)能夠找到你程序中使用的全部類型。 類目錄的絕對路徑叫作 class path。設置在系統變量 CLASSPATH 中。編譯器和 java 虛擬機經過將 package 名字加到 class path 後來構造 .class 文件的路徑。 <path- two>\classes 是 class path,package 名字是 com.runoob.test,而編譯器和 JVM 會在 <path-two>\classes\com\runoob\test 中找 .class 文件。 一個 class path 可能會包含好幾個路徑,多路徑應該用分隔符分開。默認狀況下,編譯器和 JVM 查找當前目錄。JAR 文件按包含 Java 平臺相關的類,因此他們的目錄默認放在了 class path 中。
用下面的命令顯示當前的CLASSPATH變量:
刪除當前CLASSPATH變量內容:
設置CLASSPATH變量: