面向對象的三條學習主線
- java類及類的成員
屬性、方法、構造器;代碼塊、內部類 - 面向對象的三大特征
封裝性、繼承性、多態性(抽象性) - 其他關鍵字
this、super、static、final、abstract、interface、package、import等
面向過程(POP)與面向對象(OOP)
二者都是一種思想,面向對象是相對於面向過程而言。面向過程,強調的是功能行為,以函數為最小單位,考慮怎么做。面向對象,將功能封裝進對象,強調具備功能的對象,以類/對象為最小單位,考慮誰來做。
面向對象更加強調運用人類在日常的思維邏輯中采用的思想方法與原則,如抽象、分類、繼承、聚合多態等。
面向對象程序設計的三大基本特征
封裝性(Encapsulation)
封裝是一種信息隱蔽技術,它體現於類的說明,是對象的重要特征。封裝把數據和加工該數據的方法(函數)打包為一個整體,以實現獨立性很強的模塊,使得用戶只能見到對象的外特性(對象能接受哪些信息,具有哪些處理能力),而對象的內特性(保存內部狀態的私有數據和實現加工能力的算法)對用戶是隱蔽的。封裝的目的在於把對象的設計者和對象的使用者分開,使用者不必知曉其行為實現的細節,只需要用設計者提供消息來訪問該對象
繼承性(Inheritance)
繼承性是子類共享其父類數據和方法的機制他由類的派生功能體現。一個類直接繼承其他類的全部描述,同時可以修改和擴充。繼承具有傳遞性。類的對象是各自封閉的,如果沒有繼承性機制,則類中的屬性(數據成員)、方法(對數據的操作)就會出現大量重復。繼承不僅支持系統的可重用性,而且還促進系統的可擴展性。
多態性(Polymorphism)
對象通常根據接受到的消息做出動作。當同一消息被不同的對象接受並產生不同的行動,這種現象稱為多態性。例如:同樣是run方法,鳥調用時是飛,野獸調用時是奔跑。
利用多態性,用戶可以發送一個通用信息,而將所有的實現細節都留給接受消息的對象自行決定。
類和對象的基本概念
類和對象是面向對象的核心概念
類是對一類事物的描述,是抽象的、概念上的定義
對象是實際存在的該類事物的每個個體,也稱為實例
類
類是一個抽象的概念,要利用類的方式解決問題,必須用類創建一個實例化的對象,然后通過對象去訪問類的成員變量,去調用類的成員方法來實現程序的功能。比如“汽車”是一個抽象的概念,只有使用一輛具體的汽車才能感受汽車的功能。
一個類可以創建多個類的對象,它們具有相同的屬性模式,但可以具有不同的屬性值。java程序為每個對象都開辟了內存空間,已保存各自的屬性值。
對象
對象(object)是類的實例化后的產物。對象的特征分為靜態特征和動態特征。
靜態特征是指對象的外觀、特質、屬性等。動態特征是指對象具有的功能、行為等。
人們將對象的靜態特征抽象為屬性,用數據來描述,在JAVA語言中稱之為成員變量。而將動態特征抽象為行為,用一組代碼來表示,完成對數據的操作,在JAVA語言中稱之為方法(Method)。
一個對象是由一組屬性和一類屬性進行的操作(即方法)構成的。
類的聲明與定義
限修飾符
在java中提供了四種訪問權限,使用不同的訪問權限修飾符修飾時,被修飾的內容會有不同的訪問權限
- public:公共的
- protected:受保護的
- default:默認的
- private:私有的
public | protected | default(空的) | private | |
---|---|---|---|---|
同一類中 | √ | √ | √ | √ |
同一包中(子類與無關類) | √ | √ | √ | |
不同包的子類 | √ | √ | ||
不同包中的無關類 | √ |
public具有最大權限。private則最小權限
編寫代碼時,如果沒有特殊考慮,建議這樣使用權限:
- 成員變量使用private,隱藏細節
- 構造方法使用public,方便創建對象
- 成員方法使用public,方便調用方法
類的聲明
[標識符] class 類名稱
{
//類的成員變量
//類的方法
}
聲明類使用的class關鍵字。聲明一個類時,在class關鍵字后面加上類的名稱,
標識符可以是public、private、protected或者完全省略,類名稱只要是一個合法的表示符即可,但從程序的可讀性方面來看,類名稱建議是由一個或多個有意義的單詞連綴而成,形成自我注釋(SelfDocumenting),每個單詞首字母大寫,單詞間不要使用其他分隔符。
類的組成
class Person {
String name;
int age;
void talk(){
System.out.println("我是"+naem+",今年"+age+"歲");
}
}
首先用class聲明了一個名為Person的類,在這里Perosn是類的名稱
第02和03行聲明了兩個屬性(即描述數據的變量)name和age,name為String(字符串類型)
型,age為int(整型)型。
第04~06行聲明了一個talk()方法----操作數據(如name和age)的方法,此方法用於向屏幕打印信息。
類的定義
對於一個類而言。構造方法、屬性和方法,是常見的3種成員。可以定義零個或者多個。如果3中成員都只定義零個,實際上這是一個空類。
各個成員之間定義的先后順序沒有任何影響。各個成員可以互相調用,但是static修飾的成員不能被非static修飾的成員訪問。
類的定義使用
public class ColorDefine {
String color = "黑色";
void getMes(){
System.out.println("定義類");
}
public static void main(String[] args) {
ColorDefine b = new ColorDefine();
System.out.println(b.color); //黑色
b.getMes(); //定義類
}
}
類的屬性
屬性的定義
[修飾符] 屬性類型 屬性名 [=默認值]
- 修飾符:修飾符可以省略,使用默認的訪問權想default,也可以是顯示的訪問控制符public、protected、private及static、final,其中3個訪問控制符public、protected和private只能使用其中之一,static和final則可組合起來修飾屬性。
- 屬性類型:屬性類型可以是JAVA允許的任何數據類型,包括基本類型(int、float等)和引用類型(接口、數組、類等)
- 屬性名:從語法的角度來說,屬性名則只要是一個合法的標識符即可。但如果從程序可讀性的角度來看,屬性名應該由一個或多個有意義的單詞連綴而成,推薦第一個單詞小寫開頭第二個大寫開頭,其余全部小寫單詞間不使用分隔符。如 String studentNumber
- 默認值:定義屬性還可以定義一個可選的默認值
屬性是一種比較符合漢語習慣的說法,在JAVA官方文獻中,屬性被稱為Field,因此有些書籍也把“屬性”翻譯為“字段”或“域”,它們在本質上是一樣的
屬性的使用
public class usingAttribute {
//定義兩個String類型的屬性str1和str2,它們是靜態的,所以它們是屬於類的,也就是屬於這個類定義的所有對象共有,對象看到的靜態屬性值都是相同的
static String str1 = "string-1";
static String str2;
//定義了兩個String類型的屬性str3和str4,因為它們是非靜態的,所以它們是屬於這個類所定義的對象私有的,每個對象都有這個屬性,且各自的屬性值可不同
String str3 = "string-3";
String str4;
//定義了靜態方法塊,它沒有名稱。使用static關鍵字加以修飾並用大括號“{}”括起來稱之為靜態代碼塊用來初始化靜態成員變量。如靜態變量str2被初始化為“string-2"
static{
printStatic("before static");
str2 = "String-2";
printStatic("after static");
}
//定義一個方法用來打印靜態成員變量
public static void printStatic(String title){
System.out.println("--------"+title+"---------");
System.out.println("str1=\""+str1+"\"");
System.out.println("str2=\""+str2+"\"");
}
//定義一個構造方法usingAttribute(),在這個方法中,使用了類中各個屬性。構造方法與類同名,且無返回值(包括void),它主要的目的是創建對象。
//打印一次屬性,然后改變str4屬性,最后再打印一次
public usingAttribute(){
print("before constructor");
str4 = "string-4";
print("after constructor");
}
//定義公有方法用來打印所有屬性,包括靜態成員
public void print(String title){
System.out.println("--------"+title+"--------");
System.out.println("str1=\""+str1+"\"");
System.out.println("str2=\""+str2+"\"");
System.out.println("str4=\""+str4+"\"");
System.out.println("str3=\""+str3+"\"");
}
public static void main(String[] args) {
System.out.println();
System.out.println("--------創建usingAttribute對象---------");
System.out.println();
//匿名對象
new usingAttribute();
}
}
運行結果
--------before static---------
str1="string-1"
str2="null"
--------after static---------
str1="string-1"
str2="String-2"
--------創建usingAttribute對象---------
--------before constructor--------
str1="string-1"
str2="String-2"
str3="string-3"
str4="null"
--------after constructor--------
str1="string-1"
str2="String-2"
str3="string-3"
str4="string-4"
對象的聲明與使用
對象的聲明
類名 對象名 = new 類名();
創建屬於某類的對象,需要通過下面兩個步驟來實現
1、聲明指向“由類所創建的對象”的變量
2、利用new創建新的對象,並指派給先前所創建的變量
舉例說明:如果要創建Person類的對象,可用下列語句實現
//1、聲明一個Person對象,再用new關鍵字實例化Personp1
Person p1;
p1 = new Person;
//2、聲明Person對象p1並直接實例化此對象
Person p1 = new Person();
對象只有在實例化之后才能被使用,而實例化對象的關鍵字就是new
對象的使用
如果向訪問對象里的某個成員變量或方法,可以通過下面的語法來實現
對象名稱.屬性名 //訪問屬性
對象名稱.方法名() //訪問方法
使用Person類的對象調用類中的屬性與方法的過程
public class ObjectDemo {
public static void main(String[] args) {
//實例對象,調用構造方法
Person p1 = new Person();
//對p1的name和age進行賦值
p1.name = "leesin";
p1.age = 30;
//調用talk方法
p1.talk();
}
//Person類的定義
static class Person{
String name;
int age;
void talk(){
System.out.println("我是:"+name+",今年:"+age+"歲");
}
}
}
匿名對象
匿名對象是指沒有名字的對象。實際上,根據前面的分析,對於對象實例化的操作來講,對象真正有用的部分在堆內存里面,而棧內存只是保存一個對象引用名稱(嚴格來說是對象在堆內存的地址),所以所謂的匿名對象就是指,只開辟了堆內存空間,而沒有棧內存指向的對象。
創建匿名對象
public class NoNameObject {
public void say(){
System.out.println("面向大海,春暖花開!");
}
public static void main(String [] args){
//匿名對象,沒有被其他對象所引用
new NoNameObject().say(); //面向大海,春暖花開!
}
}
匿名對象有兩個特點:
1、匿名對象沒有被其他對象所引用,即沒有棧內存指向
2、因為沒有棧內存指向,所以只能使用一次,之后就無法找尋的垃圾對象,會被垃圾回收器收回
對象的比較
有兩種方式可用於對象間的比較:
1、利用“==”運算符
“==”運算符用於比較兩個對象的內存地址值是否相等
2、利用equals()方法
equals()方法用於比較兩個對象的內容是否相等
對象比較的范例
public class CompareObject {
public static void main(String[] args) {
String s1 = new String("java");
String s2 = new String("java");
String s3 = s2;
if(s1 == s2){
System.out.println("s1 == s2");
}else {
System.out.println("s1 != s2"); //s1 != s2
}
if (s2 == s3){
System.out.println("s2 == s3"); //s2 == s3
}else {
System.out.println("s2 != s3");
}
System.out.println(s3.equals(s2)); //true
System.out.println(s3.equals(s1)); //true
}
}
對象數組的使用
把類理解為用戶自定義的數據類型,它和基本數據類型(int、float等)具有等同的地位。。
通過兩個步驟可以用數組來存放對象
1、聲明以類為數據類型的數組變量,並用new分配內存空間給數組
2、用new產生新的對象,並分配內存空間給它
要創建3個Person類型的數組元素,語法如下
Person p[]; //聲明Person類類型的數組變量
p = new Person[3]; //用new分配內存空間
創建好數組元素之后,便可把數組元素指向Person類所定義的對象
p[0] = new Person();
p[1] = new Person();
p[2] = new Person();
例:創建一個Person類
public class Person {
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String talk(){
return "我是" + this.name + ",今年:" + this.age + "歲";
}
}
例:聲明對象數組
public class ObjectArray {
public static void main(String[] args) {****
Person p[] = {
new Person("leesin",30),
new Person("zed",35),
new Person("king",25)
};
for (int i = 0; i < p.length; i++) {
System.out.println(p[i].talk());
}
/*
我是leesin,今年:30歲
我是zed,今年:35歲
我是king,今年:25歲
*/
}
}
關鍵字
this關鍵字
1、this調用本類中的屬性,也就是類中的成員變量;
2、this調用本類中的其他方法;
3、this調用本類中的其他構造方法,調用時要放在構造方法的首行
解析上面Person類中this關鍵字的使用
static關鍵字
程序中如果用static定義屬性的話,則此屬性成為靜態屬性
沒有使用靜態屬性的不便
class Person{
String name;
int age;
String nation;
public Person(String name,int age,String nation){
this.name = name;
this.age = age;
this.nation = nation;
}
public String talk(){
return "我是:"+this.name+",今年:"+this.age+",來自:"+this.nation;
}
}
public class noStaticDemo {
public static void main(String[] args) {
Person p1 = new Person("李青",30,"艾歐尼亞");
Person p2 = new Person("艾瑞利亞",35,"艾歐尼亞");
System.out.println(p1.talk());
System.out.println(p2.talk());
}
/*output
我是:李青,今年:30,來自:艾歐尼亞
我是:艾瑞利亞,今年:35,來自:艾歐尼亞
*/
}
在程序中可以看到,兩個Person對象都有一個nation屬性,而且都相同。
如果要生產500個對象,每個對象的nation屬性都相同,浪費空間不說,如果想修改所有人的nation屬性,就要實施500次nation屬性修改,這顯然太麻煩。所以java提供了static關鍵字,用它來修飾類的屬性后,此屬性就是公共屬性了。
用static修飾nation
class Person{
String name;
int age;
static String nation;
public Person(String name,int age,String nation){
this.name = name;
this.age = age;
this.nation = nation;
}
public String talk(){
return "我是:"+this.name+",今年:"+this.age+",來自:"+this.nation;
}
}
public class noStaticDemo {
public static void main(String[] args) {
Person p1 = new Person("李青",30,"艾歐尼亞");
Person p2 = new Person("艾瑞利亞",35,"艾歐尼亞");
System.out.println("修改之前的信息:"+p1.talk());
System.out.println("修改之前的信息:"+p2.talk());
System.out.println("---------修改之后的信息----------");
p1.nation = "均衡教派";
System.out.println("修改之后的信息:"+p1.talk());
System.out.println("修改之后的信息:"+p2.talk());
}
/*output
修改之前的信息:我是:李青,今年:30,來自:艾歐尼亞
修改之前的信息:我是:艾瑞利亞,今年:35,來自:艾歐尼亞
---------修改之后的信息----------
修改之后的信息:我是:李青,今年:30,來自:均衡教派
修改之后的信息:我是:艾瑞利亞,今年:35,來自:均衡教派
*/
}
final關鍵字
final關鍵字用於修飾不可改變的內容
final:不可改變。可以用於修飾類、方法和變量
- 類:被修飾的類不能被繼承
- 方法:被修飾的方法不能被重寫
- 變量:被修飾的變量不能被重新賦值
修飾類
final class 類名{
}
修飾方法
修飾符 final 返回值類型 方法名(參數列表){
//方法體
}
修飾變量
1、局部變量--基本類型
基本類型的局部變量,被final修飾后,只能賦值一次,不能再更改
public class Demo01 {
public static void main(String[] args) {
//聲明變量,使用final修飾
final int a;
//第一次賦值
a = 10;
//第二次賦值
//a = 20; //報錯,不可重新賦值
//聲明變量,直接賦值,使用final修飾
final int b = 10;
//第二次賦值
b = 20;//報錯,不可重復賦值
}
}
**2、局部變量--引用類型
引用類型的局部變量,被final修飾后,只能指向一個對象,地址不能再更改,但是不影響對象內部的成員變量值的修改
**
public class Demo02 {
public static void main(String[] args) {
//創建user對象
final User u = new User();
//創建另一個User對象
//u = new User(); // 報錯,指向了新對象,地址值改變
//調用setName方法
u.setName("leesin");
}
}
3、成員變量
成員變量設計到初始化問題,初始化方式有兩種,只能二選一
- 顯示初始化
public class User{
final String USERNAME = "leesin"
private int age;
}
- 構造方法初始化
public class User{
final String USERNAME;
private int age;
public User(String username, int age){
this.USERNAME = username;
this.age = age
}
}
被final修飾的常量名稱,一般都有書寫規范,所有的字母都大寫