面向物件
面向物件:以類的方式組織代碼,以物件組織資料
特性:
- 封裝
- 繼承
- 多型
類:抽象概念
物件:具體事物
- 面向物件是java學習的重中之重,畢竟java就是一個面向物件的語言~
- 類 = 屬性+方法
- 面向物件的概念適合復雜系統、多人協作
- 從宏觀上來說,java是面向物件的,但在微觀上是面向程序的
創建
物件的創建
使用new實體化一個物件,如
Student student = new Student();//實體化物件
new時:
- 記憶體空間的分配
- 屬性的初始化
- 構造器的呼叫
- 回傳一個物件的參考(指標)
構造器
構造器在實體化時首先被自動呼叫,用于初始化引數,
new的本質是呼叫了構造器,回傳一個物件
-
名字和類名相同
-
沒有回傳型別(不能寫!)
-
可以傳參
-
this是一個指標,指向這個物件本身
public class Person { String name; public Person(){ //構造器 this.name = "小明"; } }
封裝--訪問控制
“高耦合,低內聚”,內部資料操作細節自己完成,不由外部干涉, 暴露少部分方法給外部使用,
封裝:禁止訪問物件的實際表示,而應該通過介面來訪問,
修飾詞:
- public:可以由外部呼叫,公開使用
- private:不可由外部呼叫
- protected:由本包內或不同包的子類呼叫

繼承
使用extend關鍵字,表示子類是父類的擴展
public class Student extends Person{
Student(String name){
this.name = name;
}
}
- 子類擁有父類的全部public/protected方法和屬性
- 且子類可以對所有方法和屬性重寫
- private屬性無法被繼承
- java中所有類都是object類的子類
構造器
使用super可以訪問到父類,構造器中super.generator()可以呼叫父類的構造器,
public class Person {
String name;
public Person(String name){
//構造器
this.name = name;
}
}
public class Student extends Person{
Student(String name){
super(name);
}
}
public class Demo2 {
public static void main(String[] args){
Student s = new Student("小明");
System.out.println(s.name);
}
}
輸出“小明”,
如果在子類中不指定呼叫super,會自動呼叫
public class Person {
String name;
public Person() {
//構造器
System.out.println("父類Person無引數構造器執行");
}
}
public class Student extends Person{
Student(){
System.out.println("子類Student無引數構造器執行");
}
}
在new Student時輸出:

若將子類構造器改為有參,仍然會首先呼叫父類的無參構造器

大致邏輯如下:

注:
- 呼叫構造器時,需要將父類構造器呼叫陳述句放在子類構造器的第一句
- 父類沒寫無參,默認有一個空的構造器函式
- 如果寫了一個有參構造器,那么父類就沒有無參構造器了,子類不能自動呼叫構造器,即子類中必須顯式呼叫有參構造器了,
方法重寫
- Person類:
public static void test(){
System.out.println("Person Test");
}
Student類:
public static void test(){
System.out.println("Student Test");
}
呼叫:
public static void main(String[] args){
Student s = new Student("小明");
s.test();
}
結果:

- 但是,如果修改main
public static void main(String[] args){
Person s = new Student("小明");
s.test();
}
會導致輸出:

這可以說明
- 呼叫的方法根據宣告的型別確定
-
以上結論來自于靜態方法
如果全部改為非靜態,即將test改為無static修飾
如
@Override public void test(){ System.out.println("Student Test"); }
注意點:
- override 的前提是繼承
- 方法名相同
- 引數串列相同(不是多載)
- 修飾符的范圍只能擴大不能縮小 public>protected>default>private
- 例外的范圍可以被縮小但不能擴大,如:ClassNotFoundException->Exception
多型
定義
同一方法根據物件的不同采用不同的行為
參考型別
一個物件的實際型別是確定的,但參考型別并不一致
如
Student s = new Student();
Person s1 = new Student();
Object s2 = new Student();
實際型別都是Student,而參考型別可以是其任意父類
對于這樣的物件s1/s2,如果沒有static修飾,呼叫一個方法時
-
若子類父類都有該方法,且子類未重寫:呼叫父類的方法
-
若都有,但子類重寫了:呼叫子類的方法
-
若只有子類有,則無法呼叫(需要強制型別轉換修改參考型別)
如在Student寫一個新的eat方法:

即能呼叫的方法取決于其參考型別而不是實際型別
方法修飾
-
static 屬于類,不屬于物件,不可重寫
-
final 無法修改,不可重寫
-
private 只屬于父類,無法重寫
instanceof運算子
語法:
obj instanceof class
System.out.println(s instanceof Student);//true
System.out.println(s1 instanceof Student);//true
System.out.println(s1 instanceof Object);//true
System.out.println(s2 instanceof Student);//true
System.out.println(s2 instanceof Teacher);//false
如果物件的類是class或class的子類,則為True
在編譯狀態中,class可以是object物件的父類,自身類,子類,在這三種情況下Java編譯時不會報錯,(需要在同一條繼承鏈上)
在運行轉態中,class可以是object物件的父類,自身類,不能是子類,在前兩種情況下result的結果為true,最后一種為false,但是class為子類時編譯不會報錯,運行結果為false,
編譯的時候查看其參考型別判斷是否報錯,
運行的時候查看其實際型別判斷是否為true,
強制型別轉換
優先級:父類>子類,
子類轉父類自動轉換,
父類轉子類需要強制轉換,
轉父類后部分方法可能無法再呼叫,
static
-
static修飾(靜態)的從屬于類,普通的從屬于物件
-
靜態方法不能呼叫非靜態成員

變數
靜態變數(類變數)
- 有static修飾的變數為靜態變數,在該類的記憶體中只能存在一個,可以使用類名.變數名進行訪問
- 內部任何方法都可以直接訪問靜態變數(可以不使用類名.靜態成員進行訪問)
- 類外部可以使用類名訪問類中靜態變數
實體變數
-
無static修飾的變數
-
每創建一個實體就會生成一個新的記憶體空間
-
類內部只有非靜態方法可以訪問實體變數
-
靜態方法或其他類中只能通過實體物件訪問

靜態變數的作用
- 靜態變數被所有實體共享,可以作為實體物件間的共享資料
- 如果所有實體都有一個相同的常量屬性,可以定義為static以節省空間
方法
靜態方法(類方法)
- 靜態方法不需要通過任何實體就可以被呼叫,
- 不能使用this/super關鍵字
- 也不能直接訪問類內部的實體變數和實力方法
- 可以直接呼叫類內部的靜態變數和靜態方法
實體方法
- 通過實體物件訪問
代碼塊
靜態代碼塊
- static{}代碼塊
- 用于初始化類(一次性的),為類的靜態變數賦初值
- 類似于一個方法,但不在方法體中
- 可以在類的任意位置,可以有任意多個
- java虛擬機在加載類的時候執行靜態代碼塊
- 多個代碼塊按順序運行
- 靜態代碼塊和靜態方法類似,不能訪問非靜態成員
非靜態代碼塊
- {}
- 創建物件時自動執行,不創建物件不執行
- 代碼域中的變數都是區域的,只在內部使用
抽象
abstract修飾
抽象類
- abstract修飾的方法
- 抽象類中可以有抽象方法和具體方法
- 抽象類無法實體化
抽象方法
- 抽象方法只宣告沒有方法體
- 抽象方法必須在抽象類中
- 子類重寫父類時,必須重寫父類的所有抽象方法
- 不能用private修飾,因為private阻止重寫
實體
public abstract class Shape {
public int width; // 幾何圖形的長
public int height; // 幾何圖形的寬
public Shape(int width, int height) {
this.width = width;
this.height = height;
}
public abstract double area(); // 定義抽象方法,計算面積
}
public class Square extends Shape {
public Square(int width, int height) {
super(width, height);
}
// 重寫父類中的抽象方法,實作計算正方形面積的功能
@Override
public double area() {
return width * height;
}
}
public class Triangle extends Shape {
public Triangle(int width, int height) {
super(width, height);
}
// 重寫父類中的抽象方法,實作計算三角形面積的功能
@Override
public double area() {
return 0.5 * width * height;
}
}
介面
- 普通類:只有具體實作
- 抽象類:有具體實作和規范(抽象方法)
- 介面:只有規范,沒有具體實作 專業的約束,實作約束和實作的分離,比抽象類更加抽象
介面定義
[public] interface interface_name [extends interface1_name[, interface2_name,…]] {
// 介面體,其中可以包含定義常量和宣告方法
[public] [static] [final] type constant_name = value; // 定義常量
[public] [abstract] returnType method_name(parameter_list); // 宣告方法
}
- 介面只能繼承介面
- public定義的介面可以被任何類使用,而沒有public只能被包內使用
- 介面中的變數隱式宣告為public static final(可以不寫),即為常量,所以全部必須初始化
- 介面中的方法隱式宣告為 public abstract
介面實作
-
一個類可以實作一個或者多個介面
-
實作使用implements關鍵字
<public> class <class_name> [extends superclass_name] [implements interface1_name[, interface2_name…]] { // 主體 } -
與繼承類似,可以獲得所有的常量和方法
-
implements在extend后
-
類實作介面后必須重寫所有抽象方法
例
public interface IMath {
public int sum(); // 完成兩個數的相加
public int maxNum(int a,int b); // 獲取較大的數
}
public class MathClass implements IMath {
private int num1; // 第 1 個運算元
private int num2; // 第 2 個運算元
public MathClass(int num1,int num2) {
// 構造方法
this.num1 = num1;
this.num2 = num2;
}
// 實作介面中的求和方法
public int sum() {
return num1 + num2;
}
// 實作介面中的獲取較大數的方法
public int maxNum(int a,int b) {
if(a >= b) {
return a;
} else {
return b;
}
}
}
內部類
類內部定義的類
分類:
- 成員內部類
- 靜態內部類
- 區域內部類
- 匿名內部類

- 內部類還是一個獨立的類,會編譯為獨立的.class檔案,但前面會冠以類名和$符號
- 是內部類的一個成員,可以操作到外部類的私有屬性
- 外部類只有兩種級別:public和默認
- 內部類有四種級別:public、protected、private、默認
Outer o = new Outer();
//外部類可直接new
Inner in = new Inner();
//外部類外需要通過外部類來實體化內部類
Outer.Inner inner = o.new Inner();
實體內部類
沒有static修飾,也成為非靜態內部類,例:
public class Outer {
class Inner {
// 實體內部類
}
}
- 和實體方法、實體變數相同,在外部類/外部類以外,必須通過外部類的實體創建內部類的實體
- 實體內部類中可以訪問外部類的所有成員(多層嵌套也可)
- 外部類中不能直接訪問內部類的成員,而必須通過內部類的實體訪問(不是很懂)
- 實體內部類中的成員不能使用static修飾,除非同時有final修飾
靜態內部類
static修飾的內部類,例:
public class Outer {
static class Inner {
// 靜態內部類
}
}
- 可以通過外部類創建內部類的實體
- 類中可定義靜態成員/實體成員
- 可直接訪問外部類的靜態成員,如果要訪問外部類的實體成員,則需要通過外部類的實體去訪問,
區域內部類
一個方法中定義的類,如:
public class Test {
public void method() {
class Inner {
// 區域內部類
}
}
}
- 類似區域變數,不用訪問控制修飾符和static修飾符修飾
- 只在方法內可用
- 不能定義static成員
- 內部類的內部類也不能用訪問控制修飾符和static修飾符
- 可訪問外部類的所有成員
- 方法中的成員與外部類成員同名,可以使用
.this. 的形式訪問外部類中的成員,
匿名內部類
沒有類名的內部類,直接使用new來宣告,例:
new <類或介面>() {
// 類的主體
};
一般用法:
- 繼承一個類,重寫其方法,
- 實作一個介面(可以是多個),實作其方法,
public class Out {
void show() {
System.out.println("呼叫 Out 類的 show() 方法");
}
}
public class TestAnonymousInterClass {
// 在這個方法中構造一個匿名內部類
private void show() {
Out anonyInter = new Out() {
// 獲取匿名內部類的實體
void show() {
System.out.println("呼叫匿名類中的 show() 方法");
}
};
anonyInter.show();
}
public static void main(String[] args) {
TestAnonymousInterClass test = new TestAnonymousInterClass();
test.show();
}
}
- 和區域內部類相同,可訪問外部類所有成員,若位于方法中,只能訪問方法中final修飾的量
- 可以使用非靜態代碼塊進行初始化,在父類的建構式后執行
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543074.html
標籤:其他
上一篇:RabbitMQ的使用介紹
