# 前言
> java語言的學習是一個體系椭微,所以如果想要對java的編程有一個很精通的一個掌握隐绵,它離不開很多基礎(chǔ)的知識點之众,比如JVM的原理、java多線程并發(fā)編程依许、數(shù)據(jù)結(jié)構(gòu)等等棺禾。所以我這里對我學習的java的課程進行定期的總結(jié),來記錄我學習java的一些想法和心得峭跳。也希望能通過我的這些分享膘婶,給需要的學習某方面知識的人一些幫助。
# java基礎(chǔ)的回顧總結(jié)
java語言最明顯的幾個特點就是:<font color="#dd0000">`封裝蛀醉、繼承和多態(tài)`</font>悬襟,下面來具體聊一聊這三個特性。
## 封裝
封裝拯刁,它是一中信息隱藏技術(shù)脊岳。面向?qū)ο笥嬎闶加谶@個基本概念,即<font color="#dd0000">`現(xiàn)實世界可以被描繪成一系列完全自治筛璧、封裝的對象逸绎,這些對象通過一個受保護的接口訪問其他對象`</font>惹恃。在java中通過關(guān)鍵字private夭谤,protected和public實現(xiàn)封裝。所以說巫糙,<font color="#dd0000">封裝把對象的所有組成部分組合在一起朗儒,封裝定義程序如何引用對象的數(shù)據(jù),封裝實際上使用方法將類的數(shù)據(jù)隱藏起來参淹,控制用戶對類的修改和訪問數(shù)據(jù)的程度</font>醉锄。 適當?shù)姆庋b可以讓程式碼更容易理解和維護,也加強了程式碼的安全性浙值。
## 繼承
繼承是從已有的類中派生出新的類恳不,新的類能吸收已有類的數(shù)據(jù)屬性和行為,并能擴展新的能力开呐。 新類的定義可以增加新的數(shù)據(jù)或新的功能烟勋,也可以用父類的功能,**但不能選擇性地繼承父類筐付,就是說子類會繼承父類的所有成員屬性和方法**卵惦。繼承只能單一繼承,一個類只能繼承一個父類瓦戚,而不能有多個繼承類沮尿,<font color="#dd0000">多繼承的方式只能通過接口來實現(xiàn)</font>。
在我們?nèi)粘>幊讨薪辖猓侠淼氖褂美^承特性畜疾,能夠消除代碼的復(fù)制赴邻,從而達到簡化代碼以及程序邏輯的作用。
這里我們來說一下繼承的特性庸疾。
1. 繼承關(guān)系是傳遞的乍楚。若類C繼承類B,類B繼承類A(多層繼承)届慈,則類C既有從類B那里繼承下來的屬性與方法徒溪,也有從類A那里繼承下來的屬性與方法,還可以有自己新定義的屬性和方法金顿。繼承來的屬性和方法盡管是隱式的臊泌,但仍是類C的屬性和方法。繼承是在一些比較一般的類的基礎(chǔ)上構(gòu)造揍拆、建立和擴充新類的最有效的手段渠概。
2. 繼承簡化了人們對事物的認識和描述,能清晰體現(xiàn)相關(guān)類間的層次結(jié)構(gòu)關(guān)系嫂拴。
3. 繼承提供了軟件復(fù)用功能播揪。若類B繼承類A,那么建立類B時只需要再描述與基類(類A)不同的少量特征(數(shù)據(jù)成員和成員方法)即可筒狠。這種做法能減小代碼和數(shù)據(jù)的冗余度猪狈,大大增加程序的重用性。
4. 繼承通過增強一致性來減少模塊間的接口和界面辩恼,大大增加了程序的易維護性雇庙。
下面我們來通過一段代碼來說明子類和父類的繼承關(guān)系。
```java
package com.young.basic;
public class ExtendsDemo {
? ? //main
? ? public static void main(String aa[]) {
? ? //new 一個對象B()
? ? ? ? new B();
? ? ? ? new C();
? ? }
}
//建一個A類
class A {
? ? //成員變量 其中num是實參
? ? int num = 0;
? ? private String name = "default name";
? ? public A(){
? ? ? ? System.out.println("父類無參數(shù)構(gòu)造方法");
? ? }
? ? //成員方法,其中 i 是形參
? ? public A(int i) {
? ? ? ? //輸入int型文件輸出下面
? ? ? ? System.out.println("aaaaaaaaaaaaaaaaaaa");
? ? ? ? System.out.println("i= " + i);
? ? ? ? //把輸入的i賦值給成員變量num
? ? ? ? num = i;
? ? }
? ? public String getName() {
? ? ? ? return name;
? ? }
? ? public void setName(String name) {
? ? ? ? this.name = name;
? ? }
}
//B繼承A
class B extends A {
? ? int num = 0;
? ? //成員方法B.
? ? public B() {
? ? ? ? //繼承類A的方法.因為B繼承了A必然繼承了A的特性.所以輸入int值10令方法實現(xiàn).
? ? ? ? super(10);
? ? ? ? System.out.println("bbbbbbbbbbbbbbbbbbbb");
? ? ? ? //這里的num是類B的.
? ? ? ? System.out.println("num= " + num);
? ? ? ? //如果想顯示類A的num則需要用下列的super.num.這里注意num在類A中需是成員變量才可以.
? ? ? ? System.out.println("super.num= " + super.num);
? ? ? ? //子類繼承的私有name只能通過繼承的公有方法來訪問和修改灶伊;如果沒有提供公共方法疆前,則不能訪問和修改
? ? ? ? System.out.println("子類的name = " + this.getName());
? ? }
? ? @Override
? ? public void setName(String name) {
? ? ? ? super.setName(name);
? ? ? ? System.out.println("這是子類B的重寫的");
? ? }
}
class C extends A{
? ? public C(){
? ? ? ? System.out.println("子類C無參數(shù)構(gòu)造函數(shù)");
? ? ? ? System.out.println("cccccccccccccccc");
? ? }
}
```
運行結(jié)果:
> aaaaaaaaaaaaaaaaaaa
i= 10
bbbbbbbbbbbbbbbbbbbb
num= 0
super.num= 10
子類的name = default name
父類無參數(shù)構(gòu)造方法
子類C無參數(shù)構(gòu)造函數(shù)
cccccccccccccccc
從上邊例子中我們能看出,
1. 子類是不繼承父類的構(gòu)造器(構(gòu)造方法或者構(gòu)造函數(shù))的聘萨,<font color="#dd0000">它只是調(diào)用(隱式或顯式)</font>竹椒。<font color="#dd0000">如果父類的構(gòu)造器帶有參數(shù)(但沒有無參數(shù)構(gòu)造方法),則必須在子類的構(gòu)造器中顯式地通過super關(guān)鍵字調(diào)用父類的構(gòu)造器并配以適當?shù)膮?shù)列表米辐,**因為子類的構(gòu)造方法是必須調(diào)用父類的構(gòu)造方法的胸完,默認的調(diào)用無參數(shù)構(gòu)造方法,如果沒有無參構(gòu)造方法儡循,就必須調(diào)用有參數(shù)的父類構(gòu)造方法了舶吗。但如果父類有無參構(gòu)造方法,那么子類默認會調(diào)用無參的構(gòu)造方法**</font>择膝。如果父類的構(gòu)造器有沒有參數(shù)的誓琼,則在子類的構(gòu)造器中不需要使用super關(guān)鍵字調(diào)用父類構(gòu)造器,系統(tǒng)會自動調(diào)用父類的無參構(gòu)造器。
2. 如果父類中的成員變量是私有的(private)腹侣,子類是不能訪問的和修改的叔收,除非父類提供了公共方法來進行訪問和修改。
3. 子類可以重寫(override)父類的方法傲隶,從而使子類具有自己獨特的功能饺律。<font color="#dd0000">這其實是我們后邊講的多態(tài)的一種體現(xiàn)</font>。
## 多態(tài)
在面向?qū)ο笳Z言中跺株,接口的多種不同的實現(xiàn)方式即為多態(tài)复濒。那么在Java語言中,多態(tài)乒省,意味著一個對象有著多重特征巧颈,可以在特定的情況下,表現(xiàn)不同的狀態(tài)袖扛,從而對應(yīng)著不同的屬性和方法砸泛。多態(tài)的這種思想使Java語言更加的靈活,很多設(shè)計模式和spring框架中都使用到了多態(tài)技術(shù)蛆封。
具體的表現(xiàn)在這些方面:
1. 父類定義子類來構(gòu)建
2. 接口定義實現(xiàn)類來構(gòu)建
3. 抽象類定義實體類來構(gòu)建
4. 類方法的重載(overload)和重寫(override)
我們還是通過一段代碼來了解:
```java
public class PolymorphismDemo {
? ? public static void main(String[] args) {
? ? ? ? IParent p1 = new Child_A();
? ? ? ? IParent p2 = new Child_B();
? ? ? ? doSimpleCall(p1);
? ? ? ? doSimpleCall(p2);
? ? ? ? Child_A child_a = new Child_A();
? ? ? ? Child_B child_b = new Child_B();
? ? ? ? //child_a 沒有重寫父類的eat方法唇礁,所以執(zhí)行的是父類的eat方法
? ? ? ? child_a.eat();
? ? ? ? //child_b重寫了父類的eat方法,所以執(zhí)行自己的eat方法
? ? ? ? child_b.eat();
? ? ? ? //child_b對eat方法進行了重載惨篱,增加了一個輸入?yún)?shù)
? ? ? ? child_b.eat("popcorn");
? ? }
? ? //這里我們并不知道具體傳給我們的是哪個實現(xiàn)Parent的類盏筐,但是他們都有一個共同的接口方法
? ? public static void doSimpleCall(IParent p){
? ? ? ? p.simpleCall();
? ? }
}
interface IParent//父類接口
{
? ? public void simpleCall();
}
//父類
class Parent{
? ? public void eat(){
? ? ? ? System.out.println("parent is eating");
? ? }
}
class Child_A extends Parent implements IParent
{
? ? public void simpleCall()
? ? {
? ? ? ? System.out.println("I am Child_A");
? ? ? ? //具體的實現(xiàn)細節(jié);
? ? }
}
class Child_B extends Parent implements IParent
{
? ? public void simpleCall()
? ? {
? ? ? ? System.out.println("I am Child_B");
? ? ? ? //具體的實現(xiàn)細節(jié)妒蛇;
? ? }
? ? @Override
? ? public void eat() {
? ? ? ? System.out.println("Child_B is eating");
? ? }
? ? //這里通過增加一個String類型的參數(shù)對eat方法進行方法的重載
? ? public void eat(String food){
? ? ? ? System.out.println("Child_b is eating" + food);
? ? }
}
```
代碼運行結(jié)果:
> I am Child_A
I am Child_B
parent is eating
Child_B is eating
Child_b is eating popcorn
在上邊代碼中机断,將子類的對象賦值給父類的變量的方式就叫做<font color="#dd0000">`向上造型`</font>楷拳,但是反過來父類的對象不能賦值給子類绣夺。向上造型和類型轉(zhuǎn)換不一樣,類型轉(zhuǎn)換一般是針對基本類型來說的欢揖。
# 編程細節(jié)
> 在編寫Java程序時如果能注意一些編程細節(jié)陶耍,會對整個項目的開發(fā)帶來積極的作用,是你編寫的程序更容易的被讀懂和維護她混。在這里推薦在java的開發(fā)工具中安裝一個`阿里巴巴開發(fā)規(guī)約插件p3c`烈钞,有時間的也可以去閱讀`《阿里巴巴Java開發(fā)手冊》`和`《effective java》`。