寫代碼:
1,明確需求,。我要做什么?
2,分析思路。我要怎么做?1,2,3,。
3,確定步驟。每一個思路部分用到哪些語句,方法,和對象,。
4,代碼實現(xiàn),。用具體的 java 語言代碼把思路體現(xiàn)出來,。
學習新技術(shù)的四點:
1,該技術(shù)是什么?
2,該技術(shù)有什么特點(使用注意):
3,該技術(shù)怎么使用,。demo
4,該技術(shù)什么時候用?test。
如果此文章能幫助到你或者你學到了一點點東西,希望你能給個關(guān)注,、點贊和評論,。期待您的三連。你的關(guān)注,、點贊和評論對我來說就是我寫下去的動力,。
第一章:Java繼承
java 繼承
繼承是所有 OOP 語言和 Java 語言不可缺少的組成部分,。
繼承是 Java 面對對象編程技術(shù)的一塊基石,是面對對象的三大特征之一,也是實現(xiàn)軟件復用的重要手段,繼承可以理解為一個對象從另一個對象獲取屬性的過程。
如果類 A 是類 B 的父類,而類? B 是類 C 的父類,我們也稱類 C 是 A 的子類,類 C 是從類 A 繼承而來的,。在 Java 中,類的繼承是單一繼承,也就是說,一個子類只能擁有一個父類,。
繼承中最常使用的兩個關(guān)鍵字是?extends?和?implements?。
這兩個關(guān)鍵字的使用決定了一個對象和另一個對象是否是 IS-A (是一個)關(guān)系,。
通過使用這兩個關(guān)鍵字,我們能實現(xiàn)一個對象獲取另一個對象的屬性,。
所有 Java 的類均是由 java.lang.Object 類繼承而來的,所以 Object 是所有類的祖先類,而除了 Object 外,所有類必須有一個父類。
通過?extends?關(guān)鍵字可以申明一個類是繼承另外一個類而來的,一般形式如下:
// A.java
public class A {
private int i;
protected int j;
public void func() {
}
}
// B.java
public class B extends A {
????public int z;
????public void fund(){
????}
????
}
以上的代碼片段說明,類 B 由類 A 繼承而來的,類 B 是類 A 的子類,。而類 A 是 Object 的子類,這里可以不顯示地聲明,。
作為子類,類 B 的實例擁有類 A 所有的成員變量,但對于 private 類型的成員變量類 B 卻沒有訪問權(quán)限,這保障了類 A 的封裝性。
IS-A 關(guān)系
IS-A 就是說:一個對象是另一個對象的一個分類,。
下面是使用關(guān)鍵字?extends?實現(xiàn)繼承,。
public class Animal{
}
public class Mammal extends Animal{
}
public class Reptile extends Animal{
}
public class Dog extends Mammal{
}
基于上面的例子,以下說法是正確的:
- Animal 類是 Mammal 類的父類。
- Animal 類是 Reptile 類的父類,。
- Mammal 類和 Reptile 類是 Animal 類的子類,。
- Dog 類既是 Mammal 類的子類又是 Animal 類的子類。
分析以上示例中的 IS-A 關(guān)系,如下:
- Mammal IS-A Animal
- Reptile IS-A Animal
- Dog IS-A Mammal
因此 : Dog IS-A Animal
通過使用關(guān)鍵字?extends?,子類可以繼承父類的除 private 屬性外所有的屬性,。
我們通過使用 instanceof 操作符,能夠確定 Mammal IS-A Animal
實例
public class Dog extends Mammal{
public static void main(String args[]){
Animal a = new Animal();
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
以上實例編譯運行結(jié)果如下:
true
true
true
介紹完?extends?關(guān)鍵字之后,我們再來看下?implements?關(guān)鍵字是怎樣使用來表示 IS-A 關(guān)系,。
Implements?關(guān)鍵字在類繼承接口的情況下使用, 這種情況不能使用關(guān)鍵字?extends?。
實例
public interface Animal {}
public class Mammal implements Animal{
}
public class Dog extends Mammal{
}
instanceof 關(guān)鍵字
可以使用?instanceof?運算符來檢驗 Mammal 和 dog 對象是否是 Animal 類的一個實例,。
interface Animal{}
class Mammal implements Animal{}
public class Dog extends Mammal{
public static void main(String args[]){
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
以上實例編譯運行結(jié)果如下:
true
true
true
HAS-A 關(guān)系
HAS-A 代表類和它的成員之間的從屬關(guān)系,。這有助于代碼的重用和減少代碼的錯誤。
例子
public class Vehicle{}
public class Speed{}
public class Van extends Vehicle{
private Speed sp;
}
Van 類和 Speed 類是 HAS-A 關(guān)系( Van 有一個 Speed ),這樣就不用將 Speed 類的全部代碼粘貼到 Van 類中了,并且 Speed 類也可以重復利用于多個應(yīng)用程序,。
在面向?qū)ο筇匦灾?#xff0c;用戶不必擔心類的內(nèi)部怎樣實現(xiàn),。
Van 類將實現(xiàn)的細節(jié)對用戶隱藏起來,因此,用戶只需要知道怎樣調(diào)用 Van 類來完成某一功能,而不必知道 Van 類是自己來做還是調(diào)用其他類來做這些工作。
Java 只支持單繼承,也就是說,一個類不能繼承多個類,。
下面的做法是不合法的:
public class extends Animal, Mammal{}
Java 只支持單繼承(繼承基本類和抽象類),但是我們可以用接口來實現(xiàn)(多繼承接口來實現(xiàn)),代碼結(jié)構(gòu)如下:
public class Apple extends Fruit implements Fruit1, Fruit2{}
一般我們繼承基本類和抽象類用?extends?關(guān)鍵字,實現(xiàn)接口類的繼承用?implements?關(guān)鍵字,。
第二章:Java 重寫(Override)與重載(Overload)
重寫 (Override)
重寫是子類對父類的允許訪問的方法的實現(xiàn)過程進行重新編寫!返回值和形參都不能改變。即外殼不變,核心重寫!
重寫的好處在于子類可以根據(jù)需要,定義特定于自己的行為,。
也就是說子類能夠根據(jù)需要實現(xiàn)父類的方法,。
在面向?qū)ο笤瓌t里,重寫意味著可以重寫任何現(xiàn)有方法。實例如下:
class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 對象
Animal b = new Dog(); // Dog 對象
a.move();// 執(zhí)行 Animal 類的方法
b.move();//執(zhí)行 Dog 類的方法
}
}
以上實例編譯運行結(jié)果如下:
動物可以移動
狗可以跑和走
在上面的例子中可以看到,盡管 b 屬于 Animal 類型,但是它運行的是 Dog 類的 move 方法,。
這是由于在編譯階段,只是檢查參數(shù)的引用類型。
然而在運行時,Java 虛擬機 (JVM) 指定對象的類型并且運行該對象的方法,。
因此在上面的例子中,之所以能編譯成功,是因為 Animal 類中存在 move 方法,然而運行時,運行的是特定對象的方法,。
思考以下例子:
class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 對象
Animal b = new Dog(); // Dog 對象
a.move();// 執(zhí)行 Animal 類的方法
b.move();//執(zhí)行 Dog 類的方法
a.bark();//執(zhí)行 Animal 類的方法
}
}
以上實例編譯運行結(jié)果如下:
TestDog.java:30: cannot find symbol
symbol : method bark()
location: class Animal
a.bark();
^
該程序?qū)伋鲆粋€編譯錯誤,因為 a 的引用類型 Animal 沒有 bark 方法。
方法重寫的規(guī)則
- 參數(shù)列表與被重寫方法的參數(shù)列表必須完全相同。
- 返回類型與被重寫方法的返回類型可以不相同,但是必須是父類返回值的派生類(java5 及更早版本返回類型要一樣,java7 及更高版本可以不同),。
- 子類方法的訪問權(quán)限必須大于或等于父類方法的訪問權(quán)限,。例如:如果父類的一個方法被聲明為 public,那么在子類中重寫該方法就不能聲明為 protected。
- 父類的成員方法只能被它的子類重寫,。
- 聲明為 final 的方法不能被重寫,。
- 聲明為 static 的方法不能被重寫,但是能夠被再次聲明。
- 子類和父類在同一個包中,那么子類可以重寫父類所有方法,除了聲明為 private 和 final 的方法,。
- 子類和父類不在同一個包中,那么子類只能夠重寫父類的聲明為 public 和 protected 的非 final 方法,。
- 重寫的方法能夠拋出任何非強制異常,無論被重寫的方法是否拋出異常。但是,重寫的方法不能拋出新的強制性異常,或者比被重寫方法聲明的更廣泛的強制性異常,反之則可以,。
- 構(gòu)造方法不能被重寫,。
- 如果不能繼承一個方法,則不能重寫這個方法,。
- 訪問權(quán)限不能比父類中被重寫的方法的訪問權(quán)限更低,。例如:如果父類的一個方法被聲明為 public,那么在子類中重寫該方法就不能聲明為 protected。
Super 關(guān)鍵字的使用
當需要在子類中調(diào)用父類的被重寫方法時,要使用 super 關(guān)鍵字,。
class Animal{
public void move(){
System.out.println("動物可以移動");
}
}
class Dog extends Animal{
public void move(){
super.move(); // 應(yīng)用super類的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); //
b.move(); //執(zhí)行 Dog類的方法
}
}
以上實例編譯運行結(jié)果如下:
動物可以移動
狗可以跑和走
重載 (Overload)
重載 (overloading) 是在一個類里面,方法名字相同,而參數(shù)不同,。返回類型呢?可以相同也可以不同。
每個重載的方法(或者構(gòu)造函數(shù))都必須有一個獨一無二的參數(shù)類型列表,。
最常用的地方就是構(gòu)造器的重載。
重載規(guī)則
- 被重載的方法必須改變參數(shù)列表;
- 被重載的方法可以改變返回類型;
- 被重載的方法可以改變訪問修飾符;
- 被重載的方法可以聲明新的或更廣的檢查異常;
- 方法能夠在同一個類中或者在一個子類中被重載,。
- 無法以返回值類型作為重載函數(shù)的區(qū)分標準,。
實例
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下兩個參數(shù)類型順序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
以上實例編譯運行結(jié)果如下:
test1
1
test2
test3
returntest3
test4
returntest4
重寫與重載之間的區(qū)別
區(qū)別點 | 重載方法 | 重寫方法 |
---|
參數(shù)列表 | 必須修改 | 一定不能修改 |
返回類型 | 可以修改 | 一定不能修改 |
異常 | 可以修改 | 可以減少或刪除,一定不能拋出新的或者更廣的異常 |
訪問 | 可以修改 | 一定不能做更嚴格的限制(可以降低限制) |
總結(jié)
方法的重寫 (Overriding) 和重載 (Overloading) 是 java 多態(tài)性的不同表現(xiàn),重寫是父類與子類之間多態(tài)性的一種表現(xiàn),重載可以理解成多態(tài)的具體表現(xiàn)形式。
- (1)方法重載是一個類中定義了多個方法名相同,而他們的參數(shù)的數(shù)量不同或數(shù)量相同而類型和次序不同,則稱為方法的重載 (Overloading),。
- (2)方法重寫是在子類存在方法與父類的方法的名字相同,而且參數(shù)的個數(shù)與類型一樣,返回值也一樣的方法,就稱為重寫 (Overriding),。
- (3)方法重載是一個類的多態(tài)性表現(xiàn),而方法重寫是子類與父類的一種多態(tài)性表現(xiàn)。
第三章? Java多態(tài)
Java 多態(tài)
多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力,。
多態(tài)性是對象多種表現(xiàn)形式的體現(xiàn)。
比如我們說"寵物"這個對象,它就有很多不同的表達或?qū)崿F(xiàn),比如有小貓,、小狗,、蜥蜴等等。那么我到寵物店說"請給我一只寵物",服務(wù)員給我小貓,、小狗或者蜥蜴都可以,我們就說"寵物"這個對象就具備多態(tài)性,。
接下來讓我們通過實例來了解Java的多態(tài),。
簡單的例子
public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
因為Deer類具有多重繼承,所以它具有多態(tài)性,。以上實例解析如下:
- 一個 Deer IS-A(是一個) Animal
- 一個 Deer IS-A(是一個) Vegetarian
- 一個 Deer IS-A(是一個) Deer
- 一個 Deer IS-A(是一個)Object
在Java中,所有的對象都具有多態(tài)性,因為任何對象都能通過IS-A測試的類型和Object類,。
訪問一個對象的唯一方法就是通過引用型變量。
引用型變量只能有一種類型,一旦被聲明,引用型變量的類型就不能被改變了,。
引用型變量不僅能夠被重置為其他對象,前提是這些對象沒有被聲明為final,。還可以引用和它類型相同的或者相兼容的對象。它可以聲明為類類型或者接口類型,。
當我們將引用型變量應(yīng)用于Deer對象的引用時,下面的聲明是合法的:
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;
所有的引用型變量d,a,v,o都指向堆中相同的Deer對象,。
虛方法
我們將介紹在Java中,當設(shè)計類時,被重寫的方法的行為怎樣影響多態(tài)性。
我們已經(jīng)討論了方法的重寫,也就是子類能夠重寫父類的方法,。
當子類對象調(diào)用重寫的方法時,調(diào)用的是子類的方法,而不是父類中被重寫的方法,。
要想調(diào)用父類中被重寫的方法,則必須使用關(guān)鍵字super。
/* 文件名 : Employee.java */
public class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
public String toString()
{
return name + " " + address + " " + number;
}
public String getName()
{
return name;
}
public String getAddress()
{
return address;
}
public void setAddress(String newAddress)
{
address = newAddress;
}
public int getNumber()
{
return number;
}
}
假設(shè)下面的類繼承Employee類:
/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; //Annual salary
public Salary(String name, String address, int number, double
salary)
{
super(name, address, number);
setSalary(salary);
}
public void mailCheck()
{
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to " + getName()
+ " with salary " + salary);
}
public double getSalary()
{
return salary;
}
public void setSalary(double newSalary)
{
if(newSalary >= 0.0)
{
salary = newSalary;
}
}
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
}
現(xiàn)在我們仔細閱讀下面的代碼,嘗試給出它的輸出結(jié)果:
/* 文件名 : VirtualDemo.java */
public class VirtualDemo
{
public static void main(String [] args)
{
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
以上實例編譯運行結(jié)果如下:
Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0
Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.0
例子中,我們實例化了兩個Salary對象,。一個使用Salary引用s,另一個使用Employee引用,。
編譯時,編譯器檢查到mailCheck()方法在Salary類中的聲明。
在調(diào)用s.mailCheck()時,Java虛擬機(JVM)調(diào)用Salary類的mailCheck()方法,。
因為e是Employee的引用,所以調(diào)用e的mailCheck()方法則有完全不同的結(jié)果,。
當編譯器檢查e.mailCheck()方法時,編譯器檢查到Employee類中的mailCheck()方法。
在編譯的時候,編譯器使用Employee類中的mailCheck()方法驗證該語句, 但是在運行的時候,Java虛擬機(JVM)調(diào)用的是Salary類中的mailCheck()方法,。
該行為被稱為虛擬方法調(diào)用,該方法被稱為虛擬方法,。
Java中所有的方法都能以這種方式表現(xiàn),借此,重寫的方法能在運行時調(diào)用,不管編譯的時候源代碼中引用變量是什么數(shù)據(jù)類型。
多態(tài)的實現(xiàn)方式
方式一:重寫:
這個內(nèi)容已經(jīng)在上一章節(jié)詳細講過,就不再闡述,詳細可訪問:Java 重寫(Override)與重載(Overload),。
方式二:接口
- 1. 生活中的接口最具代表性的就是插座,例如一個三接頭的插頭都能接在三孔插座中,因為這個是每個國家都有各自規(guī)定的接口規(guī)則,有可能到國外就不行,那是因為國外自己定義的接口類型,。
- 2. java中的接口類似于生活中的接口,就是一些方法特征的集合,但沒有方法的實現(xiàn)。具體可以看?java接口?這一章節(jié)的內(nèi)容,。
方式三:抽象類和抽象方法
詳情請看?Java 抽象類?章節(jié)
第四章? Java抽象類
Java 抽象類
在 Java 面向?qū)ο蟮母拍钪?#xff0c;所有的對象都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類,。
抽象類除了不能實例化對象之外,類的其它功能依然存在,成員變量、成員方法和構(gòu)造方法的訪問方式和普通類一樣,。
由于抽象類不能實例化對象,所以抽象類必須被繼承,才能被使用,。也是因為這個原因,通常在設(shè)計階段決定要不要設(shè)計抽象類。
父類包含了子類集合的常見的方法,但是由于父類本身是抽象的,所以不能使用這些方法,。
抽象類
在Java語言中使用abstract class來定義抽象類,。如下實例:
/* 文件名 : Employee.java */
public abstract class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay()
{
System.out.println("Inside Employee computePay");
return 0.0;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
public String toString()
{
return name + " " + address + " " + number;
}
public String getName()
{
return name;
}
public String getAddress()
{
return address;
}
public void setAddress(String newAddress)
{
address = newAddress;
}
public int getNumber()
{
return number;
}
}
注意到該Employee類沒有什么不同,盡管該類是抽象類,但是它仍然有3個成員變量,7個成員方法和1個構(gòu)造方法。 現(xiàn)在如果你嘗試如下的例子:
/* 文件名 : AbstractDemo.java */
public class AbstractDemo
{
public static void main(String [] args)
{
/* 以下是不允許的,會引發(fā)錯誤 */
Employee e = new Employee("George W.", "Houston, TX", 43);
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
當你嘗試編譯AbstractDemo類時,會產(chǎn)生如下錯誤:
Employee.java:46: Employee is abstract; cannot be instantiated
Employee e = new Employee("George W.", "Houston, TX", 43);
^
1 error
繼承抽象類
我們能通過一般的方法繼承Employee類:
/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; //Annual salary
public Salary(String name, String address, int number, double
salary)
{
super(name, address, number);
setSalary(salary);
}
public void mailCheck()
{
System.out.println("Within mailCheck of Salary class ");
System.out.println("Mailing check to " + getName()
+ " with salary " + salary);
}
public double getSalary()
{
return salary;
}
public void setSalary(double newSalary)
{
if(newSalary >= 0.0)
{
salary = newSalary;
}
}
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
}
盡管我們不能實例化一個Employee類的對象,但是如果我們實例化一個Salary類對象,該對象將從Employee類繼承3個成員變量和7個成員方法,。
/* 文件名 : AbstractDemo.java */
public class AbstractDemo
{
public static void main(String [] args)
{
Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
System.out.println("Call mailCheck using Salary reference --");
s.mailCheck();
System.out.println("\n Call mailCheck using Employee reference--");
e.mailCheck();
}
}
以上程序編譯運行結(jié)果如下:
Constructing an Employee
Constructing an Employee
Call mailCheck using Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0
Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.
抽象方法
如果你想設(shè)計這樣一個類,該類包含一個特別的成員方法,該方法的具體實現(xiàn)由它的子類確定,那么你可以在父類中聲明該方法為抽象方法,。
Abstract關(guān)鍵字同樣可以用來聲明抽象方法,抽象方法只包含一個方法名,而沒有方法體。
抽象方法沒有定義,方法名后面直接跟一個分號,而不是花括號,。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代碼
}
聲明抽象方法會造成以下兩個結(jié)果:
- 如果一個類包含抽象方法,那么該類必須是抽象類,。
- 任何子類必須重寫父類的抽象方法,或者聲明自身為抽象類。
繼承抽象方法的子類必須重寫該方法。否則,該子類也必須聲明為抽象類,。最終,必須有子類實現(xiàn)該抽象方法,否則,從最初的父類到最終的子類都不能用來實例化對象,。
如果Salary類繼承了Employee類,那么它必須實現(xiàn)computePay()方法:
/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; // Annual salary
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}
//其余代碼
}
第五章 Java封裝
Java 封裝
在面向?qū)ο蟪淌皆O(shè)計方法中,封裝(英語:Encapsulation)是指,一種將抽象性函式接口的實作細節(jié)部份包裝、隱藏起來的方法,。
封裝可以被認為是一個保護屏障,防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機訪問,。
要訪問該類的代碼和數(shù)據(jù),必須通過嚴格的接口控制。
封裝最主要的功能在于我們能修改自己的實現(xiàn)代碼,而不用修改那些調(diào)用我們代碼的程序片段,。
適當?shù)姆庋b可以讓程式碼更容易理解與維護,也加強了程式碼的安全性,。
實例
讓我們來看一個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類的變量怎樣被訪問:
/* 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());
}
}
以上代碼編譯運行結(jié)果如下:
Name : James
第六章 Java接口
Java 接口
接口(英文:Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合,接口通常以interface來聲明。一個類通過繼承接口的方式,從而來繼承接口的抽象方法,。
接口并不是類,編寫接口的方式和類很相似,但是它們屬于不同的概念,。類描述對象的屬性和方法。接口則包含類要實現(xiàn)的方法,。
除非實現(xiàn)接口的類是抽象類,否則該類要定義接口中的所有方法,。
接口無法被實例化,但是可以被實現(xiàn)。一個實現(xiàn)接口的類,必須實現(xiàn)接口內(nèi)所描述的所有方法,否則就必須聲明為抽象類,。另外,在Java中,接口類型可用來聲明一個變量,他們可以成為一個空指針,或是被綁定在一個以此接口實現(xiàn)的對象,。
接口與類相似點:
- 一個接口可以有多個方法。
- 接口文件保存在.java結(jié)尾的文件中,文件名使用接口名,。
- 接口的字節(jié)碼文件保存在.class結(jié)尾的文件中,。
- 接口相應(yīng)的字節(jié)碼文件必須在與包名稱相匹配的目錄結(jié)構(gòu)中。
接口與類的區(qū)別:
- 接口不能用于實例化對象,。
- 接口沒有構(gòu)造方法,。
- 接口中所有的方法必須是抽象方法。
- 接口不能包含成員變量,除了static和final變量,。
- 接口不是被類繼承了,而是要被類實現(xiàn),。
- 接口支持多重繼承。
接口的聲明
接口的聲明語法格式如下:
[可見度] interface 接口名稱 [extends 其他的類名] {
// 聲明變量
// 抽象方法
}
Interface關(guān)鍵字用來聲明一個接口,。下面是接口聲明的一個簡單例子,。
/* 文件名 : NameOfInterface.java */
import java.lang.*;
//引入包
public interface NameOfInterface
{
//任何類型 final, static 字段
//抽象方法
}
接口有以下特性:
- 接口是隱式抽象的,當聲明一個接口的時候,不必使用abstract關(guān)鍵字。
- 接口中每一個方法也是隱式抽象的,聲明時同樣不需要abstract關(guān)鍵子,。
- 接口中的方法都是公有的,。
實例
/* 文件名 : Animal.java */
interface Animal {
public void eat();
public void travel();
}
接口的實現(xiàn)
當類實現(xiàn)接口的時候,類要實現(xiàn)接口中所有的方法。否則,類必須聲明為抽象的類,。
類使用implements關(guān)鍵字實現(xiàn)接口,。在類聲明中,Implements關(guān)鍵字放在class聲明后面,。
實現(xiàn)一個接口的語法,可以使用這個公式:
... implements 接口名稱[, 其他接口, 其他接口..., ...] ...
實例
/* 文件名 : 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();
}
}
以上實例編譯運行結(jié)果如下:
Mammal eats
Mammal travels
重寫接口中聲明的方法時,需要注意以下規(guī)則:
- 類在實現(xiàn)接口的方法時,不能拋出強制性異常,只能在接口中,或者繼承接口的抽象類中拋出該強制性異常。
- 類在重寫方法時要保持一致的方法名,并且應(yīng)該保持相同或者相兼容的返回值類型,。
- 如果實現(xiàn)接口的類是抽象類,那么就沒必要實現(xiàn)該接口的方法,。
在實現(xiàn)接口的時候,也要注意一些規(guī)則:
- 一個類可以同時實現(xiàn)多個接口。
- 一個類只能繼承一個類,但是能實現(xiàn)多個接口,。
- 一個接口能繼承另一個接口,這和類之間的繼承比較相似。
接口的繼承
一個接口能繼承另一個接口,和類之間的繼承方式比較相似,。接口的繼承使用extends關(guān)鍵字,子接口繼承父接口的方法,。
下面的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接口繼承了兩個方法,這樣,實現(xiàn)Hockey接口的類需要實現(xiàn)六個方法。
相似的,實現(xiàn)Football接口的類需要實現(xiàn)五個方法,其中兩個來自于Sports接口,。
接口的多重繼承
在Java中,類的多重繼承是不合法,但接口允許多重繼承,,。
在接口的多重繼承中extends關(guān)鍵字只需要使用一次,在其后跟著繼承接口。 如下所示:
public interface Hockey extends Sports, Event
以上的程序片段是合法定義的子接口,與類不同的是,接口允許多重繼承,而 Sports及 Event 可能定義或是繼承相同的方法
標記接口
最常用的繼承接口是沒有包含任何方法的接口,。
標識接口是沒有任何方法和屬性的接口.它僅僅表明它的類屬于一個特定的類型,供其他代碼來測試允許做一些事情,。
標識接口作用:簡單形象的說就是給某個對象打個標(蓋個戳),使對象擁有某個或某些特權(quán)。
例如:java.awt.event包中的MouseListener接口繼承的java.util.EventListener接口定義如下:
package java.util;
public interface EventListener
{}
沒有任何方法的接口被稱為標記接口,。標記接口主要用于以下兩種目的:
- 建立一個公共的父接口:
正如EventListener接口,這是由幾十個其他接口擴展的Java API,你可以使用一個標記接口來建立一組接口的父接口,。例如:當一個接口繼承了EventListener接口,Java虛擬機(JVM)就知道該接口將要被用于一個事件的代理方案。
- 向一個類添加數(shù)據(jù)類型:
這種情況是標記接口最初的目的,實現(xiàn)標記接口的類不需要定義任何接口方法(因為標記接口根本就沒有方法),但是該類通過多態(tài)性變成一個接口類型,。
第七章 Java包
Java 包(package)
為了更好地組織類,Java提供了包機制,用于區(qū)別類名的命名空間,。
包的作用
- 1 把功能相似或相關(guān)的類或接口組織在同一個包中,方便類的查找和使用。
- 2 如同文件夾一樣,包也采用了樹形目錄的存儲方式,。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時調(diào)用兩個不同包中相同類名的類時,應(yīng)該加上包名加以區(qū)別,。因此,包可以避免名字沖突。
- 3 包也限定了訪問權(quán)限,擁有包訪問權(quán)限的類才能訪問某個包中的類,。
Java使用包(package)這種機制是為了防止命名沖突,訪問控制,提供搜索和定位類(class),、接口、枚舉(enumerations)和注釋(annotation)等,。
包語句的語法格式為:
package pkg1[.pkg2[.pkg3…]];
例如,一個Something.java 文件它的內(nèi)容
package net.java.util
public class Something{
...
}
那么它的路徑應(yīng)該是 net/java/util/Something.java 這樣保存的,。 package(包)的作用是把不同的java程序分類保存,更方便的被其他java程序調(diào)用。
一個包(package)可以定義為一組相互聯(lián)系的類型(類,、接口,、枚舉和注釋),為這些類型提供訪問保護和命名空間管理的功能。
以下是一些Java中的包:
- java.lang-打包基礎(chǔ)的類
- java.io-包含輸入輸出功能的函數(shù)
開發(fā)者可以自己把一組類和接口等打包,并定義自己的package,。而且在實際開發(fā)中這樣做是值得提倡的,當你自己完成類的實現(xiàn)之后,將相關(guān)的類分組,可以讓其他的編程者更容易地確定哪些類,、接口、枚舉和注釋等是相關(guān)的,。
由于package創(chuàng)建了新的命名空間(namespace),所以不會跟其他package中的任何名字產(chǎn)生命名沖突,。使用包這種機制,更容易實現(xiàn)訪問控制,并且讓定位相關(guān)類更加簡單,。
創(chuàng)建包
創(chuàng)建package的時候,你需要為這個package取一個合適的名字。之后,如果其他的一個源文件包含了這個包提供的類,、接口,、枚舉或者注釋類型的時候,都必須將這個package的聲明放在這個源文件的開頭。
包聲明應(yīng)該在源文件的第一行,每個源文件只能有一個包聲明,這個文件中的每個類型都應(yīng)用于它,。
如果一個源文件中沒有使用包聲明,那么其中的類,函數(shù),枚舉,注釋等將被放在一個無名的包(unnamed package)中,。
例子
讓我們來看一個例子,這個例子創(chuàng)建了一個叫做animals的包。通常使用小寫的字母來命名避免與類,、接口名字的沖突,。
在animals包中加入一個接口(interface):
/* 文件名: Animal.java */
package animals;
interface Animal {
public void eat();
public void travel();
}
接下來,在同一個包中加入該接口的實現(xiàn):
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
import關(guān)鍵字
為了能夠使用某一個包的成員,我們需要在 Java 程序中明確導入該包,。使用"import"語句可完成此功能,。
在 java 源文件中 import 語句應(yīng)位于 package 語句之后,所有類的定義之前,可以沒有,也可以有多條,其語法格式為:
import package1[.package2…].(classname|*);
如果在一個包中,一個類想要使用本包中的另一個類,那么該包名可以省略。
例子
下面的payroll包已經(jīng)包含了Employee類,接下來向payroll包中添加一個Boss類,。Boss類引用Employee類的時候可以不用使用payroll前綴,Boss類的實例如下,。
package payroll;
public class Boss
{
public void payEmployee(Employee e)
{
e.mailCheck();
}
}
如果Boss類不在payroll包中又會怎樣?Boss類必須使用下面幾種方法之一來引用其他包中的類
使用類全名描述,例如:
payroll.Employee
用import關(guān)鍵字引入,使用通配符"*"
import payroll.*;
使用import關(guān)鍵字引入Employee類
import payroll.Employee;
注意:
類文件中可以包含任意數(shù)量的import聲明。import聲明必須在包聲明之后,類聲明之前,。
package的目錄結(jié)構(gòu)
類放在包中會有兩種主要的結(jié)果:
- 包名成為類名的一部分,正如我們前面討論的一樣,。
- 包名必須與相應(yīng)的字節(jié)碼所在的目錄結(jié)構(gòu)相吻合。
下面是管理你自己java中文件的一種簡單方式:
將類,、接口等類型的源碼放在一個文件中,這個文件的名字就是這個類型的名字,并以.java作為擴展名,。例如:
// 文件名 : Car.java
package vehicle;
public class Car {
// 類實現(xiàn)
}
接下來,把源文件放在一個目錄中,這個目錄要對應(yīng)類所在包的名字。
....\vehicle\Car.java
現(xiàn)在,正確的類名和路徑將會是如下樣子:
通常,一個公司使用它互聯(lián)網(wǎng)域名的顛倒形式來作為它的包名.例如:互聯(lián)網(wǎng)域名是apple.com,所有的包名都以com.apple開頭,。包名中的每一個部分對應(yīng)一個子目錄,。
例如:這個公司有一個com.apple.computers的包,這個包包含一個叫做Dell.java的源文件,那么相應(yīng)的,應(yīng)該有如下面的一連串子目錄:
....\com\apple\computers\Dell.java
編譯的時候,編譯器為包中定義的每個類、接口等類型各創(chuàng)建一個不同的輸出文件,輸出文件的名字就是這個類型的名字,并加上.class作為擴展后綴,。 例如:
// 文件名: Dell.java
package com.apple.computers;
public class Dell{
}
class Ups{
}
現(xiàn)在,我們用-d選項來編譯這個文件,如下:
$javac -d . Dell.java
這樣會像下面這樣放置編譯了的文件:
.\com\apple\computers\Dell.class.\com\apple\computers\Ups.class
你可以像下面這樣來導入所有 \com\apple\computers\中定義的類,、接口等:
import com.apple.computers.*;
編譯之后的.class文件應(yīng)該和.java源文件一樣,它們放置的目錄應(yīng)該跟包的名字對應(yīng)起來。但是,并不要求.class文件的路徑跟相應(yīng)的.java的路徑一樣,。你可以分開來安排源碼和類的目錄,。
<path-one>\sources\com\apple\computers\Dell.java
<path-two>\classes\com\apple\computers\Dell.class
這樣,你可以將你的類目錄分享給其他的編程人員,而不用透露自己的源碼。用這種方法管理源碼和類文件可以讓編譯器和java虛擬機(JVM)可以找到你程序中使用的所有類型,。
類目錄的絕對路徑叫做class path,。設(shè)置在系統(tǒng)變量CLASSPATH中。編譯器和java虛擬機通過將package名字加到class path后來構(gòu)造.class文件的路徑,。
<path- two>\classes是class path,package名字是com.apple.computers,而編譯器和JVM會在 <path-two>\classes\com\apple\compters中找.class文件,。
一個class path可能會包含好幾個路徑。多路徑應(yīng)該用分隔符分開,。默認情況下,編譯器和JVM查找當前目錄,。JAR文件按包含Java平臺相關(guān)的類,所以他們的目錄默認放在了class path中,。
設(shè)置CLASSPATH系統(tǒng)變量
用下面的命令顯示當前的CLASSPATH變量:
- Windows平臺(DOS 命令行下)-> C:\> set CLASSPATH
- UNIX平臺(Bourne shell下)-> % echo $CLASSPATH
刪除當前CLASSPATH變量內(nèi)容:
- Windows平臺(DOS 命令行下)-> C:\> set CLASSPATH=
- UNIX平臺(Bourne shell下)-> % unset CLASSPATH; export CLASSPATH
設(shè)置CLASSPATH變量:
- Windows平臺(DOS 命令行下)-> set CLASSPATH=C:\users\jack\java\classes
- UNIX平臺(Bourne shell下)-> % CLASSPATH=/home/jack/java/classes; export CLASSPATH
本文參考https://www./java,如若侵權(quán)請私信刪除。