MODULE 5 OOP 面向對象程序設計
--------------------------------------------------------
Object Oriented Programming 縮寫java
Class類/Object對象
--------------------
萬物皆對象算法
類:具備相同屬性和行爲的一組對象的組合
class 類名{
屬性
構造器
方法
}
對象:類的一個實例
new 類名編程
OOP三大特性
1.封裝Encapsulation
封裝的目的:實現信息的隱藏
1)實現對象的屬性信息的隱藏
2)對行爲的實現細節的隱藏
外部用戶無需關注方法的實現細節
2.Inheritance繼承
類與類之間的關係
1)對象間具備必定的類似性
2)子類和父類之間必定要知足「is a」的語義關係
子類 is a 父類
Cat is a Animal
總結:
一般父類表明了一個大羣體,子類是這個大羣體中的小羣體
3,多態Polymorhism
相同的行爲,不一樣的對象具備不一樣的實現小程序
java中的方法定義
--------------------------
1)一個方法容許存在多個修飾符,多個修飾符之間沒有順序的前後之別
2)返回類型位於修飾符以後,一個方法必定要有返回類型
對於沒有返回值的方法,返回類型爲void
3)方法中存在返回值時,要求方法中的每一個分支都要有return,以確保在任何一種狀況都有返回值
4)方法的參數能夠是0~多個
訪問同一類中的方法時能夠直接調用
方法定義時:必定要指定參數類型
方法調用時:參數接收外部數據
5)構造器不是普通方法,構造器和普通方法的調用機制不一樣數組
參數傳遞*
-----------------------
區分形參和實參
形參:方法定義時的參數,尚未明確的取值
實參:方法調用時傳遞給形參的明確的取值安全
實參----> 形參
1.參數爲基本數據類型
傳值,將實參的值拷貝一份傳遞給形參
2.參數爲引用類型
傳引用 是將引用的對象的地址拷貝了一份傳給了參數數據結構
this關鍵字
-------------------
attribute:name gender age 表明成員變量app
成對的訪問子:用於對屬性進行賦值和取值的操做框架
public void setName(String name){name=name;}
//根據就近原則,找到的是局部變量nameide
this 表明當前類或對象
當成員變量名與局部變量名相同時,用this加以區分
public void setName(String name){this.name=name;}
封裝
--------------------
1)屬性信息的隱藏
在屬性前面添加private修飾符,表明只能在該類內部訪問
對外提供訪問子,能夠經過訪問子約束屬性的合理取值範圍
方法重載 overloading
-----------------------
條件:
1)在同一個類的內部
2)定義了多個同名方法
3)參數類型或個數不一樣
4)返回類型不作要求 (能夠相同也能夠不相同)
優點:外部用戶每每不關注調用的方法,由編譯器本身判斷
建立和初始化對象
---------------------------
建立對象:new Student();
1)爲對象開闢空間;
2)爲對象的成員變量進行默認初始化(0/false/null)
3)顯式初始化
class Student{
String name="zhan";
int age=23;
}
缺點:每次建立一個對象,屬性值都相同
4)構造器
當對象的屬性值不肯定時,經過構造器能夠靈活控制
做用:
對屬性進行初始化,不能涉及複雜的邏輯代碼
容許定義多個構造器,提供多種初始化方案
知識點:
1)類中必定存在構造器
2)用戶沒有顯式定義構造器java會默認分配無參構造器
public Student(){}
3)一旦用戶顯式定義了構造器,不會再分配無參構造器
如何在一個構造器中調用另外一個構造器?
目的:簡化代碼
用this關鍵字
this(name,gender);
注意:
1)調用另外一構造器用this(...) 能夠簡化代碼
2)構造方法中的this()語句必須是第一條語句
總結this的兩個用法:
1)成員變量和方法的局部變量名相同時
public void setName(String name){this.name=name;}
2)構造器重載時,調用另外一構造器
this(param_list);
繼承Inheritance
--------------------------
本質目的:實現代碼的複用
語法:classs Subclass extends Superclass{...}
意義:
1)子類繼承父類的屬性和方法
2)子類能夠添加屬於本身特有的屬性和行爲
知足繼承的條件:
1)"is a"的關係
2)java中的繼承只能是單繼承,子類只能有一個父類
class A extends B,C //錯誤
父類的哪些語法成分被子類繼承?
--------------------------------------
1)父類的屬性和非私有的方法能夠被子類繼承
父類的私有屬性,子類只能經過訪問子進行訪問
2)父類的構造方法不能被子類繼承,可是子類必定會調用父類構造器
父類構造器的調用
1)隱式調用
子類中沒有super(...)顯式調用父類構造器,則子類會默認調用父類的無參構造器
2)顯式調用
若父類中沒有默認的無參構造器時,子類構造器必定要顯式調用父類的構造方法
語法:super(param_list);
參數類型必定要與父類構造器匹配
該語句必定要在第一句執行
super關鍵字
------------
super表明父類
1)子類調用父類的同名方法時
super.setAge(age);
2)子類構造器中調用父類的構造方法
super(param_list);
多態Polymorphism
--------------------------
對於不一樣的對象,相同的行爲致使不一樣的結果,程序會在運行時動態決定調用的是哪一個對象及其方法
靜態類型
Person p; p的類型已經肯定
動態類型
new Student(); 程序運行時
p表明的能夠是Person對象自己,也能夠是其子類對象
p=new Person(); p.display();//Person中的方法
p=new Student(); p.display();//Student中的方法
多態存在的三個條件:
1)必定要有子類繼承父類;
2)必定要有子類重寫父類的同名方法,即Overriding
3)父類的引用指向子類的對象
Casting強制類型轉換
--------------------------
大類型賦給小類型時,須要進行強制類型轉化
語法:(轉換的目標類型)待轉換的變量
如何避免任意的類型轉化?
------------------------------
例如:
Animal a=new Bird();
Cat c=(Cat)a; //ClassCastExcption類型轉換錯誤
不能將Bird類型對象轉換爲Cat類型
操做符instanceof
---------------------------
比較操做符,結果爲true/false
用法: 引用型變量 instanceof 類名
做用:判斷前面的引用型變量實際指向的對象的動態類型是不是後面的類自身或其子類,是返回true,不然返回false
一般對引用類型進行casting是,應該先用instanceof進行類型斷定
方法重寫/覆蓋Overriding
-------------------------------------
1)必定是在子類和父類之間(與overloading不一樣)
2)方法名:參數列表和返回類型都相同;
3)可見範圍不能被縮小
要求子類的同名方法的訪問權限不能小於父類的方法訪問權限
4)拋出的異常不能被子類放大
即子類方法拋出的異常必須和父類的同名方法拋出的異常相同,或者是父類方法拋出的異常類的子類
class Super{
public void method() throws IOException{}
}
class Sub extends Super{
public void method() throws Exception{}
}
MODULE 6 高級語言特徵
---------------------------------------------------
重點:
1.static關鍵字 修飾變量 方法 初始化代碼塊
2.final關鍵字 修飾類 方法 變量
3.訪問權限控制 public protected default(package private) private
4."=="和equals()比較
5.抽象類和接口*
6.內部類*
7.集合框架Collection**
8.反射機制reflection**
static修飾符
-----------------------------
1.修飾變量-----靜態變量
----只能修飾成員變量,不能修飾局部變量
特色:該類的全部對象共享
static int maxAge=120;
1)static某種程度上相似全局變量
2)語法: 類名.靜態變量名
p1.name 普通成員變量的訪問
Person.maxAge 靜態變量的訪問
2.修飾方法---靜態方法
特色:
1)該類的全部對象共享該方法
2)不能訪問非靜態的語法成分(普通方法/成員變量),只能訪問靜態變量和靜態方法
3)在靜態方法中訪問類的普通方法和成員變量,必定要先建立該類的實例化對象
一般將只操做靜態變量而不操做成員變量的方法定義爲靜態變量方法
4)父類中的靜態方法不能被子類重寫爲非靜態的
(即必須被子類覆蓋成靜態方法)
5)一般java中的工具類,提供的都是靜態方法
3.static 修飾初始化代碼塊
----靜態代碼塊
能夠把代碼寫在方法外,必定要用static{...}括起來
class A{
static{
//code,沒有方法名稱能夠調用
}
}
1)只能被執行一次,在類加載時(裝入內存時)一次性的執行
2)能夠存在多個靜態代碼塊,JVM會合並執行
3)優先於類的構造器
一般對於只要求一次性初始化的靜態變量,不寫在構造器中,而用靜態代碼塊
final關鍵字
-----------------------
特色:不可更改性
1.修飾變量----常量
一旦被賦值,就不能再修改
2.修飾方法
該方法只能在子類中被繼承,但不能被重寫Overriden
3.修飾類
不能有子類繼承final類
final class A{}
class B extends A{} //非法
類是final,該類不會再有子類,裏面的方法意味着就不能被重寫,等同於方法final
static final -----------靜態常量
Access Control訪問權限控制
------------------------------------
public 共有,最大訪問權限
protected 同一個包中或其餘包中的子類能夠訪問
(package private)同一個包中的類能夠訪問
private 私有,只在本類內部能夠訪問
public > protected > package private > private
Object
----------------------
java中默認的祖先類,Object 至關於全部類的樹根,單繼承的父類最終會掛在Object類
class A(extends Object){}
1.toString()
返回的是字符串,用於描述對象的屬性信息
class Person{
String toString(){
return name;
}
}
用法:Person p=new Person();
System.out.println(p);//默認調用p.toString()
System.out.println(p.display());//當p爲null是,報錯
"=="和equals()比較
------------------------
1.「==」
一般用於比較基本數據類型----比較值
若是比較的是引用類型--------比較的是引用地址
Person p1=new Person();
Person p2=new Person();
p1==p2 ? false 兩個引用指向的不是同一個對象
p1=p2;
pq==p2 ? true p1和p2指向同一個對象
2.equals(Object obj)
p1.equals(p2); 比較的是兩個對象的類型和內容是否相同
1)java 提供的類,例如,String
默認以實現了equals()方法,能夠直接調用進行對象的比較
2)對於自定義的類,必定要重寫equals()方法
public boolean equals(Object obj){
//1.比較類型是否相同,用instanceof
//2.再比較每一個屬性取值是否相同
//3.只有類型和內容都相同時,才return true;
}
代碼以下:---------------------------------------------------------------------------------------------
public boolean equals(Object obj){
if(obj instanceof Person){
Person p;
p=(Person)obj; //強制類型轉換
if((this.getName()==p.getName())&&(this.getSex()==p.getSex())&&(this.getAge()==p.getAge())){
return true;
}
else return false;
}
else return false;
}
或者:----------------------------------------------------------------------------------------------------------
public boolean equals(Object obj){
if(obj instanceof Person){
Person p;
p=(Person)obj; //強制類型轉換
if((this.getName().equals(p.getName()))&&(this.getSex().equals(p.getSex()))&&(this.getAge()==p.getAge())){
return true;
}
else return false;
}
else return false;
}
包裝器類Wrapper Class
--------------------------------
提供了四類八種基本數據類型相對應的包裝器類
1)方便設計對象的操做
2)提供數值型和字符串類型間的轉換方法
3)集合中存放的數據類型都爲引用類型,不支持基本數據類型存儲
用法:
1.jdk1.5以前 顯式裝箱/拆箱
裝箱:基本數據類型 --> 引用類型
int i=20;
Integer inte=new Integer(i);
拆箱:引用類型 --> 基本數據類型
int j=inte.intValue(); ==> j=20
2.jdk1.5以後 自動裝箱/拆箱
裝箱:
Integer inte=30;
拆箱:
int i=new Integer(5); ==> i=5
int j=inte;
賦值號兩邊,一邊是基本數據類型,一邊能夠是包裝器類
抽象類和抽象方法
--------------------------------------
抽象類
abstract class A{}
現實世界對象---------(抽象)----------> 類
類---------> (抽象)------> 抽象類
Cat類 Dog類 ===> Animal抽象類
特色:
1)不能實例化對象(不能用new操做符)
Animal a=new Animal();//非法
Animal a; //合法
a=new Cat();
a=new Dog(); //合法
設計目的:
用抽象類的引用型變量去操做它的子類對象;
2)和子類知足"is a"語義關係;
3)單繼承
抽象方法
abstract class A{
abstract void method();
}
特色:
沒有方法的具體實現,只有方法的聲明
設計目的:
一般定義了一種規範,表示全部的子類必須具備的行爲,要求子類必須提供該行爲的具體實現
知識點:
1)有抽象方法的類必定要聲明爲抽象類
2)抽象類當中能夠有0~多個抽象方法,也能夠有普通方法
3)子類中必須對抽象類中的抽象方法提供實現
4)抽象類能夠繼承抽象類,抽象類不能繼承普通類
具體的類 繼承 抽象
5)abstract 不能和 final 共同修飾一個類(不能實例化對象,不能被繼承的類——無用)
6)抽象類中 有 構造器
給子類調用
思考: Fish Animal Food
接口Interface
-----------------------
間接地實現多繼承
定義: public interface 接口名{}
特色:
1)不能實例化對象,是抽象類的另外一種形式
2)接口中的語法成分:
a)接口中的變量都是靜態常量(static final 寫不寫都是默認的)
b)接口中的方法都是抽象的(abstract 寫不寫都是默認的)
public interface A{
int ABC=100;
public void method();
}
定義了一種行爲的規範,接口的實現類必定要對這些行爲提供具體的實現,這些實現類之間能夠毫無關聯
Cat Dog Bird Animal Plane
public interface Flable{
publi void fly();
}
class Bird extends Animal implements Flable{
public void eat(){...}
public void fly(){...}
}
c)不存在 構造器
3)接口與接口以及接口與類之間的合法關係
a)類實現接口,能夠實現多個接口
class A implements B,C{}
類能夠既繼承類有實現多個接口
b)接口能夠繼承多個接口
public interface C extends A,B{}
抽象類和接口的區別
---------------------------
類似處:
1)都不能實例化
2)抽象方法都只能聲明不能實現,都表明一種行爲規範
3)子類或實現類必須對抽象方法提供實現
設計角度:
都是爲了讓父類或接口的引用變量指向子類或實現類的對象
不一樣處:
1.語法角度
關鍵字 abstract class interface
--------------------------------------------------------------------------
變量 成員變量/靜態變量/final 只能靜態常量
方法 普通方法/抽象方法 只能抽象方法
構造器 存在,能夠自定義 不存在
2.編程思想(設計理念)
語義關係 知足"is a" 沒有
對類的抽象 對行爲的抽象
(將子類的公有部分泛化出來) 實現類之間無關聯
練習:
自定義類,以數組的形式實現對多個對象的增刪改查以及遍歷操做
該數據結構以線性方式管理數據(以索引號存取)
內部類Inner Class
--------------------------
class A{
int i;
void method(){}
class B{
int j;
void print(){}
}
}
將一個類定義在另外一個類的內部
設計目的:
1)減小命名衝突,能夠再不一樣的類中定義同名的類
內部類身上都攜帶有外部類信息
2)縮小類的使用範圍,使其使用範圍比包小,能夠在一個類的內部或者方法的內部甚至表達式的內部使用
精確的肯定類的使用範圍
3)內部類能夠訪問外部類的私有語法成分
主要做用:
精確的控制類的使用範圍
如何避免屢次實例化一個內部類對象?
匿名內部類,控制內部類只能一次性的使用
一般將內部類的定義和使用放在一塊兒
new 發動機(){ //借用父類或接口的名稱建立內部類
void produce(){}
}; //不要忘了大括號後面的分號
內部類的分類:
----------------------------
1.靜態內部類
參考靜態方法或靜態成員變量
class Outer{
private static int i;
static void method(){}
static class Inner{
public void method(){
i++; //能夠訪問靜態語法成分
Out.method(); //訪問外部類的方法
}
}
}
特色:
1)定義在類的內部,在該類內部均可以訪問
2)不依賴於外部類對象,能夠獨立構建
3)只能訪問外部類的靜態語法成分
用法:
1)在外部類的內部如何建立?
Inner inn=new Inner(); //和普通類建立對象同樣
2)在外部類的外部如何建立?
條件:內部類非私有
Outer.Inner oitest=new Outer.Inner(); //建立內部類的對象
Outer o=new Outer(); //這個語句只建立了外部類對象,內部類對象須要獨立建立
2.成員內部類
參考普通成員變量和方法
1)定義在類的內部,方法外部
2)成員內部類緊密依賴於它所在的外在的外部類對象(不一樣於靜態內部類)
3)能夠訪問外部類中的全部語法成分,包括私有的
用法:
1)在外部類內部建立內部類對象
Inner inn=new Inner();
2)在外部類外部建立內部類對象
普通成員變量和方法都緊密依賴於類的對象,必定要先建立對象,再訪問其餘的屬性和方法,成員內部類也同樣
Out.Inner oinn=(new Outer()).new Out.Inner();
3.局部內部類
進一步縮小了使用範圍,只在方法內部使用
1)定義在方法內部,參考局部變量
2)能夠訪問外部類的全部語法成分
3)只能訪問它所在的 【局部常量】
4)不能加public/protected/private/static 修飾符,無心義
相似局部變量,只在方法內部使用
4.匿名內部類
沒有類名
class Outer{
public void method(){
class Inner implements IInterface{
void method(){}
}
Inner inn=new Inner();
}
}
1)也是定義在方法內部
2)沒有類名,沒有構造器,沒有class/extends/implements關鍵字
借用其父類或接口的名稱
3)將使用和定義放在一塊兒,一次性地運用
改造:
class Outer{
public void method(){
IInterface inn=new IInterface(){
void method(){}
};
}
}
改造流程:
1)將class/extends/implements以及類名都刪掉
2)建立對象時改用父類或接口的名稱,寫法區別於建立類的對象:
A a=new A(); //建立類A的對象
A a=new A(){...};
a)A是類:建立類A的一個匿名的子類對象
b)A是接口:建立的是接口A的一個匿名的實現類的對象
Collection 集合框架**
------------------------------------
java中的集合框架屬於半成品,能夠拿來作二次開發
---提供了常見的數據結構的實現,用來存儲和管理多個對象
1)會看API
2)瞭解常見數據結構的特色
3)可以對各個集合類進行增刪改查操做
特色:
集合中的類都用於存儲多個對象(只能是Object類型)
包:java.util;
接口:
1.Collection接口 存儲管理沒有依賴關係的一組對象
|-------List接口 數據是順序存儲的,以索引號方式存取,容許對象重複,也容許null
|-------Set接口 存儲的數據無序,不容許重複
|------SortedSet接口 具備排序功能的Set
2.Map接口 以鍵值對的形式管理一組成對的對象(key~value)
|------SortedMap接口 提供了具備排序功能的Map
問題:
1)Set中如何判斷存儲的對象是重複的?是否只要重寫equals()就足夠?
2)SortedSet提供了排序的功能,那麼根據什麼來排序?
好比:學生(學號,姓名,分數,年齡),每一個屬性均可以排序,
須要開發人員指定排序的規則
實現了:
Collection 無實現類
List實現類
ArrayList 採用數組的方式存儲一組對象,根據索引號方式存取數據,增刪效率低,查找高效
LinkedList 採用雙向鏈表的方式,只能提供從前日後或從後往前一個個順序查找元素,增刪高效,查找低效
Vector 線程安全的ArrayList
Set 實現類
HashSet 數據無順序,不重複
SortedSet實現類
TreeSet 提供了排序功能的Set
List練習:
建立一個銀行帳戶類Account
屬性:int code;
String name;
double balance;
方法:重寫toString()方法,返回帳戶信息
建立ListTest.java 用ArrayList 對一組帳戶進行增刪改查操做,並打印輸出該List中的全部帳戶信息
Set練習:
建立SetTest.java 用HashSet對一組帳戶進行操做,放入一些重複的帳戶,驗證重複數據是否成功放入
Set中的元素存放機制:
按照hashtable的散列算法存放,數值型是對錶長取餘數,那麼對象呢?
如何得到對象身上的惟一的int型數據?
Object中的hashCode()方法:
返回該對象的hash代碼
在Set中判斷兩個對象是否相同,須要重寫equals()和hashCode()兩個方法
Iterator迭代器
-------------------------------
對不一樣的數據結構提供了統一的遍歷算法,解決的就是數據結構的遍歷問題
public interface Iterator{
public boolean hasNext();
public Object next();
public void remove();
}
Iterator{
}
class ArrayList{ //這段小程序很重要
...
public Iterator iterator(){ //匿名內部類
return new Iterator(){
public boolean hasNext(){...}
public Object next(){...}
public void remove(){...}
};
}
...
}
以ArrayList爲例實現遍歷:
List list=new ArrayList();
Iterator iter=list.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
迭代器只適用於Collection分支,不適合Map分支
Comparator 比較器
-------------------------
指定對象之間的比較規則
public Interface Comparator{
public int compare(Obiject o1,Object O2);
public boolean equals(Object o);
}
public class CodeComparator implements Comparator{
public int compare(Object o1,Object o2){
//比較o1和o2的code屬性
}
}
compare方法:
若是返回的結果>0,則o1>o2
若是返回的結果<0,則o1<o2
若是返回的結果=0,則o1=o2
Set set=new TreeSet();
練習:採用TreeSet數據結構管理一組Account,要求:
1)對Account提供按照code正排的方式
2)對Account提供按照balance倒排的方式
Map
----------------------
以鍵值對的方式存儲和管理一組對象,一個key對應一個value
key ~ value
例:Student: code ~ Student
key值:惟一不重複 key值也是一個Object類型的對象
value:能夠重複 也是Object類型
Map.Entry:存放key和value的關聯關係,也是Object類型
Map的實現類
Hashtable 線程安全
HashMap 線程不安全的Hashtable
SortedMap的實現類
TreeMap 增長了排序功能
練習:建立MapTest測試類,存儲一組Account(code,name,balance)
Set keySet() 獲取Map中全部的Key對象的集合
Collection values() 獲取Map中全部的Value對象的集合
Set entrySet() 獲取Map中全部的key~value 的映射關係對象的集合
Reflection 反射 ***
--------------------------------
類 ----> 鏡像
人 ----> 照鏡子
class中的語法成分:
package信息
import信息
public class 類名 extends/implements 父類/接口{
成員變量:修飾符,數據類型,標識符
普通方法:修飾符,返回類型,標識符,參數列表,異常
構造器:修飾符,參數列表
}
包:java.lang.reflect;
須要import
類的鏡像
java.lang.Class
成員變量的鏡像
java.lang.reflect.Field
方法的鏡像
java.lang.reflect.Method
構造器的鏡像
java.lang.reflect.Constructor
A a=new A();//建立類A的對象a
String classname="A";
反射機制的核心:
在運行時動態獲取已知名字的class類的相關信息,動態建立該類(調用構造器),並調用其方法或修改器屬性(甚至是private的屬性和方法)
introspection:內省/內觀,看透class的能力
反射機制的運用:
1)經過鏡像能夠獲得類的原始構造信息
2)在程序運行時,經過類名動態建立該類的對象(不是編譯時)
在框架中普遍引用
3)破壞封裝:經過反射能夠得到類的成員變量/方法/構造器等私有特性
如何得到類的鏡像
--------------------------
1)若是知道類名,根據類名.class 獲得該類的鏡像
Class c=String.class;//c表明String類的鏡像
Class c1=int.class;//c1表明int基本數據類型的鏡像
2)只知道引用型變量,調用變量的getClass()方法
String str="abc";
Class c=str.getClass();//c表明String類的鏡像
3)只知道字符串形式給出的類名
Class.forName("類名");
String classname="java.lang.String";
Class.forName(classname);
沒有Declared的方法
例:getFields() getMethods()..
返回的是class對象所表示的類或接口中的公有的屬性或方法,包括繼承
帶有Declared的方法
例:getDeclaredFiedlds() getDeclaredMethods()...
返回的是全部的屬性或方法(public/protected/default/private),但不包括繼承的屬性和方法
練習:
經過命令行傳遞一個數據結構(Collection)所表示的類名,經過反射機制動態建立該類的對象(new ArrayList()),往該數據結構中放入幾個對象,而後再遍歷輸出該數據結構中的對象信息
例:"java.util.ArrayList" ---> args --> args[0]
分析:
1)拿到args[0]表示的類的鏡像
Class c=Class.forName(args[0]);
2)建立該類的實例化對象
Object o=c.newInstance();
3)o ---> Collection ----> o.add(...);
newInstance()方法 調用的是該類的公有且無參的構造器
練習: 定義一個Data.java類,使其中的語法成分都爲private Data d=new Data();//沒法在外部建立該類的對象(由於構造器私有) 經過反射機制: 1)建立該類的實例化對象 獲取類的鏡像 Data.class; 獲取該類的構造器鏡像 c.getDeclaredConstructors(); 打開構造器爲共有的 con.setAccessible(true); 2)調用其中的私有方法 3)修改器屬性值