1. 程式人生 > 實用技巧 >41. 缺失的第一個正數

41. 缺失的第一個正數

面向物件 & 面向過程

  • 面向過程思想

    • 步驟清晰簡單,第一步做什麼,第二步做什麼...

    • 面向過程適合處理一些較為簡單的問題

  • 面向物件思想

    • 物以類聚,分類的思維模式,思考問題首先會解決問題需要哪些分類,然後對這些分類進行單獨思考。最後才對某個分類下的細節進行面向過程的思索。

    • 面向物件適合處理複雜的問題,適合處理多人協作的問題!

  • 對於描述複雜的事物,為了從巨集觀上把握,從整體上合理分析,我們需要使用面向物件的思路來分析整個系統。但是,具體到微觀操作,仍然需要面向過程的思路去處理。

什麼是面向物件

  • 面向物件程式設計(Object-Oriented Programming,OOP)

  • 面向物件程式設計的本質就是:以類的方式組織程式碼,以物件的形式組織(封裝)資料

  • 抽象

  • 三大特性

    • 封裝

    • 繼承

    • 多型

  • 從認識論考慮是先有物件後有類。物件,是具體的事物。類,是抽象的,是對物件的抽象

  • 從程式碼執行角度考慮是先有類後有物件。類是物件的模板。


package Java高階班.oop;

public class Dome01 {
public static void main(String[] args) {

}

public String sayHello(){
return "hello,world";
}
/*
* 修飾符 返回值型別 方法名(...)
* //方法體
* return 返回值;
* */
//return 結束方法,返回一個結果!
//break 跳出switch 結束迴圈
// public void hello(){
// return;
// }

}
package Java高階班.oop;

public class Dome02 {
public static void main(String[] args) {
//例項化這個類 new
//物件型別 物件名 = 物件值;
Student student = new Student();
student.say();
}
//和類一起載入的
public static void a(){
//b(); //報錯
}
//類例項化之後才存在
public void b(){

}
}
package Java高階班.oop;
//學生類
public class Student {

// //非靜態方法
public void say(){
System.out.println("學生說話了");
}
//靜態方法---->直接呼叫無需new物件
//public static void say(){
// System.out.println("學生說話了");
//}

}
package Java高階班.oop;

public class Dome03 {
public static void main(String[] args) {
//實際引數和形式引數的型別要對應!
int add = Dome03.add(1,2);
System.out.println(add);
}

public static int add(int a,int b){//佔位符
return a + b;
}
}
package Java高階班.oop;
//值傳遞
public class Dome04 {
public static void main(String[] args) {
int a = 1;
System.out.println(a);//1

Dome04.change(a);

System.out.println(a);//1
}
//返回值為空
public static void change(int a){
a = 10;
}
}
package Java高階班.oop;

//引用傳遞 物件,本質還是值傳遞

//物件 記憶體
public class Dome05 {

public void change(Person person){
//person是一個物件:指向是--->
person.name = "二狗子";
}
public static void main(String[] args) {
Dome05 dome05 = new Dome05();
Person person = new Person();
System.out.println(person.name);//null
dome05.change(person);
System.out.println(person.name);//二狗子
}
}
//定義了一個Person類,有一個屬性:name
class Person{
String name;//null
}

類和物件的關係

  • 類是一種抽象的資料型別,它是對某一具體事物整體描述/定義,但是並不能代表某一個具體事物。

    • 動物 植物 手機 電腦

    • Person類 Pet類 Car類等,這些類都是用來描述/定義某一類具體的事物應該具備的特點和行為

  • 物件是抽象概念的具體例項

    • 張三就是人的一個具體例項,張三家裡的旺財就是狗的一個具體例項。

    • 能夠體現出特點,展現出功能的是具體的例項,而不是一個抽象的概念。


建立與初始化物件

  • 使用new關鍵字建立物件

  • 使用new關鍵字建立的時候,除了分配記憶體空間之外,還會給建立好的物件進行預設的初始化以及對類中構造器的呼叫。

  • 類中的構造器也稱為構造方法,是在進行建立物件的時候必須要呼叫的。並且構造器有以下兩個特點:

    • 必須和類的名字相同

    • 必須沒有返回型別,也不能寫void

  • 構造器必須要掌握

package Java高階班.oop.opp2;
//學生類
public class Student {
//屬性:欄位
String name;//這是抽象的模板不能寫死
// String name = "xiaoming";//這是抽象的模板不能寫死
int age;

//方法
public void study(){
System.out.println(this.name + "在學習");
}

//學程式好?對世界進行更好的建模!
}
package Java高階班.oop.opp2;
//一個專案應該只存在一個main方法
public class Application {
public static void main(String[] args) {
//類是抽象的,例項化
//類例項化後會返回一個自己的物件!
//student物件就是一個Student類的具體例項!
Student xiaoming = new Student();
Student xh = new Student();
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);

xiaoming.name = "小明";
xiaoming.age = 3;

System.out.println(xiaoming.name);
System.out.println(xiaoming.age);

xh.name = "小紅";
xh.age = 3;

System.out.println(xh.name);
System.out.println(xh.age);
}
}

補充

保留n位小數

方法一:String的format方法(推薦)

double f = 111231.5585;

System.out.println(String.format("%.2f", f));

//     String i = "";
// System.out.println("*************");
// System.out.println(i);//null和String裡的""不同
package opp1022;

public class Person {
//一個類即使什麼都不寫,它也會存在一個方法
//顯示定義的構造體
String name;
int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

//這個是Alt + Insert 選擇Select None生成的
// public Person() {
// }

// //例項化初始值
// //1.使用new關鍵字,本質是在呼叫構造器
// //2.用來初始化值
//這個是Alt + insert 選擇ok生成的
public Person(String name) {
this.name = name;
}
// public Person() {//無參
// //name = "二狗子";
// }
//
// //有參構造:一旦定義了有參構造,無參就必須顯示定義
// public Person(String name){
// this.name = name;
// }
//alt + insert//Code->Generate->Constructor

}
/*public class Application {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
// String i = "";
// System.out.println("*************");
// System.out.println(i);//null和String裡的""不同
}
}


構造器:
1. 和類名相同
2. 沒有返回值
作用:
1. new 本質在呼叫構造方法
2. 初始化物件的值
注意點:
1.定義有參構造之後,如果想使用無參構造,顯示的定義一個無參的構造

Alt + Insert
是代表當前類的 = 一般是引數傳的值
this. = value


*/


小結(this 指當前類的物件,建構函式互相呼叫用this()

,可有參可無參,必須放在建構函式中的第一行)

  1. 類與物件

    類是一個模板:抽象的 物件是一個具體的例項

  2. 方法

    定義,呼叫!

  3. 物件的引用

    引用型別: 基本型別(8)

物件是通過引用來操作的 棧--->堆(地址)

  1. 屬性:欄位 Field 成員變數

    預設初始化:

    數字:0 0.0

    char:u0000

    boolean:false

    引用:null

    修飾符 屬性型別 屬性名 = 屬性值!

  2. 物件的建立和使用

    • 必須使用new關鍵字創造物件,構造器 Person ergouzi = new Person();

    • 物件的屬性 ergouzi.name

    • 物件的方法 ergouzi.sleep()

  3. 類:

    • 靜態的屬性 屬性

    • 動態的行為 方法

    封裝,繼承,多型


封裝

  • 該露的露,該藏的藏

    • 我們程式設計要求"高內聚,低耦合"。高內聚就是類的內部資料操作細節自己完成,不允許外部干涉;低耦合:僅暴露少量的方法給外部使用。

  • 封裝(資料的隱藏)

    • 通常,應禁止直接訪問一個物件中資料的實際表示,而應通過操作介面來訪問,這稱為資訊隱藏。

  • 記住這句話就夠了:屬性私有,get/set

package opp1024;
/*
* 1.提高程式的安全性保護資料
* 2.隱藏程式碼的細節
* 3.統一介面
* 4.系統可維護性增加
* */
public class StudentTest {
public static void main(String[] args) {
Student student = new Student();
//student.name = "";
//一個疑問 a的返回值型別是String,b本身就是String型別,為什麼a單獨一條語句不報錯,而b卻報錯?
// student.getName();//a
// "hvhj";//b

//方法名,引數列表
System.out.println(student.getName());
student.setName("二狗子");
System.out.println(student.getName());

student.setAge(999);//不合法
System.out.println(student.getAge());

student.setAge(70);//合法
System.out.println(student.getAge());
}
}
package opp1024;
//類
public class Student {
//名字
private String name;
//學號
private int id;
//性別
private char sex;
//年齡
private int age;

//提供一些可以操作這個屬性的方法!
//提供一些public的get,set方法
//正常情況下getSet不會用過載

//get 獲得這個資料

public String getName() {
return name;
}

public int getAge() {
return age;
}

//set 給這個資料設定值

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
if (!(age > 120 || age < 0)) {
this.age = age;
}else {
age = 3;
}
this.age = age;
}
//學習()

//睡覺()
}

繼承

  • 繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模。

  • extends的意思是"擴充套件"。子類是父類的擴充套件。

  • Java中類只有單繼承,沒有多繼承!

  • 繼承是類與類之間的一種關係。除此以外,類與類還有依賴,組合,聚合等。

  • 繼承關係的兩個類,一個為子類(派生類),一個為父類(基類)。子類繼承父類,使用關鍵字extend來表示。

  • 子類和父類之間,從意義上將應該具有"is a"的關係。

  • object類

  • super

  • 方法重寫

package opp1024;
//小學生 Pupil is a Person 人
//老師 Teacher is a Person 人

//繼承是最核心的東西,相當於巨集觀的把握;封裝是關於底層的;多型有繼承的前提

//Person 人:父類

//在Java中所有的類,都預設直接或者間接繼承Object
public class Person /*(extends Object)---> 正常情況下可以省略掉*/{
//
// //public : 他爸爸給兒子的
// //protected
// //default ---> 直接不用寫
// //private: 他爸爸自己的臨死也沒給兒子的 ---> 一般屬性才是私有的
//
// private int money = 1_000_000_000;
// //private int money = 1_000_000_000;
//
// //前提都是public的方法
// public void say(){
// System.out.println("說了一句話。");
// }
//
// public int getMoney() {
// return money;
// }
//
// public void setMoney(int money) {
// this.money = money;
// }
}
package opp1024;
//老師 Teacher is a Person 人
public class Teacher extends Person{
}
package opp1024;
//小學生 Pupil is a Person 人 派生類,子類
public class Pupil extends Person{
}

//Ctrl + H :開啟樹
////這個叫組合
//public class Pupil {
// Person person;
//}
package opp1024;

public class Application {
public static void main(String[] args) {
Pupil pupil = new Pupil();
//pupil.say();
//System.out.println(pupil.money);//private不能繼承

Person person = new Person();
//person.
}
}

Super詳解

super注意點

  1. super呼叫父類的構造方法,必須在構造方法的第一個

  2. super必須只能出現在子類的方法或者構造方法中!

  3. super和this不能同時呼叫構造方法!

vs this

  • 代表的物件不同:

    • this: 本身呼叫這個物件

    • super:代表父類物件的引用

  • 前提

    • this:沒有繼承也可以使用

    • super:只能在繼承條件下才可以使用

  • 構造方法

    • this();本類的構造

    • super();父類的構造

package opp1024;
public class Pupil extends Person{
// Person("qwer");
// private String name = "張大仙";
//

public Pupil() {
//隱藏程式碼:預設呼叫了父類的無參構造
//呼叫父類構造器,必須要在子類構造器的第一行
//包括this也一樣呼叫自己的構造器也是第一行
//一個類只要寫了有參構造就把無參構造加上
//只要寫了有參構造,無參構造就沒了,除非自己再寫一個
//如果不寫無參構造子類也沒法寫父類的無參構造
//如果父類沒寫無參僅寫了有參,子類呼叫父類的無參呼叫
// 不了,但呼叫有參卻可以呼叫。
super("vg");
//super();//--->會報錯
//this("大仙");
System.out.println("Pupil無參構造被執行了");
}

// public Pupil(String name) {
// this.name = name;
// }

public void print(){
System.out.println("Pupil");
}

public void test1(){
print();
this.print();
super.print();
}

public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
package opp1024;
public class Person{
protected String name = "二狗子";

// public Person() {
// System.out.println("Person無參執行了");
// }

public Person(String name) {
this.name = name;
}

//私有的東西無法被繼承
//private void print(){
public void print(){
System.out.println("Person");
}
}
package opp1024;
public class Teacher extends Person{
}
package opp1024;

import java.util.Scanner;

public class Application {
public static void main(String[] args) {
Pupil pupil = new Pupil();
//pupil.test("張冰心");
//pupil.test1();
}
}

物件方法和類方法的區別

  • 物件方法是你必須例項化該物件,才可以使用相對應許可權的方法。

  • 類方法是你不需要例項化該物件,也可以使用該方法,類方法也叫靜態方法


重寫

  • 需要有繼承關係,子類重寫父類的方法!

  • 重寫是繼承裡的一個概念,過載是一個類裡的概念

  • 特點

    • 方法名必須相同

    • 引數列表必須相同

    • 修飾符:範圍可以擴大但不能縮小: public --> protected --> default --> private

    • 子類到父類,子類修飾符限定範圍比父類大,比如子類是protected的話,父類只能是default或protected,但是子類異常範圍更小

    • 丟擲的異常:範圍可以被縮小但不能被擴大 ClassNotFoundException --> Exception

    • 重寫異常丟擲範圍不能大於父類

  • 重寫:子類的方法和父類必須要一致:方法體不同

  • 為什麼需要重寫:

    • 父類的功能,子類不一定需要,或者不一定滿足

      • Alt + Insert :override;

  • static是類方法,方法呼叫只和左邊有關且不屬於重寫範疇,重寫是非static方法的重寫

package opp1024.dome;

public class Application {

//靜態方法和非靜態方法的區別很大
//沒有static時,b呼叫的是物件的方法,
//而b是A new出來的物件,因此呼叫了A的
//方法,因為靜態方法是類的方法,

//非靜態:重寫
public static void main(String[] args) {

//類方法的呼叫只和左邊定義的資料型別有關
A a = new A();
a.test();

//父類的引用指向子類
B b = new A();//子類重寫了父類的方法
b.test();
}
}
package opp1024.dome;
//繼承關係
public class A extends B{
//Override 重寫
//@Override//註解,有功能的註釋
protected void test() {
System.out.println("A=>test()");
}
}
package opp1024.dome;


//重寫都是方法的重寫和屬性無關
//重寫都是非靜態方法,與靜態方法無關
//idea中出現那個o紅色向上的箭頭說明確實重寫了
//重寫關鍵詞是public不能是private
public class B {
void test(){
// private void test(){//編譯出錯
System.out.println("B=>test()");
}
}

多型

  • 動態編譯:執行過程中才可以確定型別,程式可拓展性增強

  • 即同一方法可以根據傳送物件的不同而採用多種不同的行為方式。

  • 一個物件的實際型別是確定的,但可以指向物件的引用的型別有很多(父類或者有關係的類)

  • 多型存在的條件

    • 有繼承關係

    • 子類重寫父類方法

    • 父類引用指向子類物件

  • 注意:多型是方法的多型,屬性沒有多型性

  • instanceof 型別轉換--->引用型別 判斷一個物件是什麼型別

  • 基本資料型別是看容量關係,引用資料型別看子類和父類的關係

package opp1025;

public class Person {
public void run(){
System.out.println("run");
}
}
package opp1025;

public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}

public void eat(){
System.out.println("eat");
}
}

/*
* 多型注意事項
* 1.多型是方法的多型,屬性沒有多型
* 2.父類和子類,有聯絡,即使強制轉換型別,也得互相之間有聯絡父類為大,子類為小
* 父類變子類叫向下型別轉換,子類變父類叫向上型別轉換
* 型別轉換異常 ClassCastException!
* 3.多型存在條件a.繼承關係b.方法需要重寫c.父類引用指向子類物件
*
* 1.static方法屬於類,不屬於例項
* 2.final 常量
* 3.private方法
* */
package opp1025;

public class Application {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//new Student();
//new Person();
//可以指向的引用型別就不確定了


//Student子型別 能呼叫的方法都是自己的或繼承父類的
Student s1 = new Student();

//父類的引用指向子類的型別
//父型別Person雖然可以指向子類,但不能呼叫子類獨有的方法,除非強制型別轉換,
//強制轉換依然遵循大到小轉換 父類比子類大嘛
Person s2 = new Student();
Person s4 = new Person();
Object s3 = new Student();

//子類重寫了父類的方法,執行子類的方法
s2.run();
s1.run();
((Student)s4).run();

//物件能執行哪些方法,主要看物件左邊的型別,和右邊關係不大!
s1.eat();
((Student) s2).eat();
}
}

instanceof 和型別轉換

package opp1025;

public class Test {
public static void main(String[] args) {
//型別之間的轉換:基本型別轉換 高-->低 64 32 16 8
// 引用型別轉換 高-->低 父 子
// 高 低
Animal animal = new Dog();

//animal將這個物件轉換為Dog型別,我們就可以使用Student型別的方法了。
//animal.go();//報錯
//第一種強轉
// ((Dog) animal).go();

//第二種強轉
// Dog dog = (Dog)animal;
// dog.go();

Dog dog = new Dog();
dog.go();
//子類轉換為父類可能會丟失一些方法
//低(子)轉高(父)時,由於子已經繼承了父的所有,所以刪去自己的後自然而然就可以轉換為父類的,
//而父想轉子,則需要重新開闢只屬於子的空間,則需要強制轉換。
Animal animal1 = dog;
//((Dog) animal).go();
}
}

/*
* 前提:
* 父類的引用指向類的物件
* 把子類轉換成父類,向上轉型 子類轉換為父類可能會丟失一些方法,可能會用不了子類的方法
* 把父類轉換成子類,向下轉型 強制轉換 父類強轉子類才可以呼叫子類的方法,並不是丟失但會損失精度,不轉換無法調
* 用子類特有方法,和丟失沒有關係,父類本身不含子類特有方法,記憶體不夠接收不了,
* 精度是各種資料型別的位寬
* */

// Object object = new Dog();
// System.out.println(object instanceof Dog);
// System.out.println(object instanceof Cat);
// System.out.println(object instanceof Object);
// System.out.println(object instanceof Animal);
// System.out.println(object instanceof String);
//
// //能不能編譯通過 看左邊的型別(必須是引用型別)
// //在編譯通過的情況下 實際判斷物件變為=右邊的型別
// //System.out.println(X instanceof Y);
//
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++");
//
// Animal animal = new Dog();
// System.out.println(animal instanceof Dog);
// System.out.println(animal instanceof Cat);
// System.out.println(animal instanceof Object);
// System.out.println(animal instanceof Animal);
//
// //關鍵看new的是什麼,new Dog就看Dog這條線,
// // dog向上只有一個爹,一個爺,一個曾爺...向下可能有一個娃或者多個娃
// //System.out.println(animal instanceof String);//Person和String沒有繼承關係;編譯報錯
//
// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++");
// Dog dog = new Dog();
// System.out.println(dog instanceof Dog);
// //System.out.println(dog instanceof Cat);
// System.out.println(dog instanceof Object);
// System.out.println(dog instanceof Animal);
package opp1025;

public class Cat extends Animal {
}
package opp1025;

public class Dog extends Animal {
public void go(){
System.out.println("go");
}
}
package opp1025;

public class Animal {
public void run(){
System.out.println("father");
}
}

補充點

  • this表示這個類的當前例項,super表示父類的當前例項,static是屬於類的,this是類的一個物件,當然呼叫了不了他,static太牛了,只有類名可以呼叫它,static叫靜態方法,也叫類方法,就是在程式啟動的時候,就會為這個方法分配一塊記憶體空間,所以什麼時候都可以呼叫這個方法

  • this為什麼不能在靜態方法中使用?

    • 靜態方法是存放在方法區中的,此時使用this不能獲取到當前類的地址而在類的普通方法中使用this,就能得到當前物件在堆中的地址


Java中匿名程式碼塊、靜態程式碼塊以及構造方法的執行順序

package opp102502;


public class Test {


{
//匿名程式碼塊用來賦初值
System.out.println("匿名程式碼塊");
}

static {
//靜態程式碼塊只執行一次
System.out.println("靜態程式碼塊");
}

public Test(){
//構造方法
System.out.println("構造方法");
}

public static void main(String[] args) {
Test test1 = new Test();
System.out.println("=====分割線======");
Test test2 = new Test();

}
}

靜態程式碼塊

匿名程式碼塊

構造方法

=====分割線======

匿名程式碼塊

構造方法

package opp102502;

//static
//通過final繼承的類就沒有子類了-->沒後代了
//public class Student extends Person{
public class Student {
private static int age;//靜態變數 多執行緒用
private double score;//非靜態變數
public void run(){
System.out.println("run");
//非靜態方法可以呼叫靜態方法的所有東西
//go();
}

public static void shout(){
System.out.println("汪!汪!汪");
}

public static void go(){
System.out.println("go");
//靜態方法可以呼叫靜態方法的所有東西
shout();
}
public static void main(String[] args) {
Student student = new Student();
student.run();
go();
student.go();
Student.go();
//this.run();
System.out.println(student.age);
//System.out.println(this.age);

//為什麼this.go()不可以而類名.go()就可以呢
//this.go();
Student.go();
// Student student = new Student();
//
// System.out.println(Student.age);//類變數
// // System.out.println(Student.score);
//
// System.out.println(student.age);
// System.out.println(student.score);
}
}
package opp102502;
//import static java.lang.Math.random;

//靜態匯入包
import static java.lang.Math.PI;
import static java.lang.Math.pow;
import static java.lang.Math.random;

//通過final繼承的類就沒有子類了-->沒後代了
public class Application {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
System.out.println(pow(2, 3));
}
}

抽象類

  • abstract修飾符可以用來修飾方法也可以用來修飾類,如果修飾方法,如果修飾方法,那麼該方法就是抽象方法;如果修飾類,那麼該類就是抽象類。

  • 抽象類中可以沒有抽象方法,但有抽象方法的類一定要宣告為抽象類。

  • 抽象類,不能使用new關鍵字來建立物件,它是用來讓子類繼承的。

  • 抽象方法,只有方法的宣告,沒有方法的實現,它是用來讓子類實現的。

  • 子類繼承抽象類,那麼就必須要實現抽象類沒有實現的抽象方法,否則該子類也要宣告為抽象類。

package opp102503;
//abstract 抽象類
public abstract class Action {

//約束——有人幫我們實現
//abstract,抽象方法,只有方法名字,沒有方法實現。
public abstract void doSomething();
}
//類中存在不抽象的方法,但是一旦有抽象的方法就得把類宣告為抽象類
//抽象方法必須在抽象類中
//抽象的抽象:約束

//思考? 抽象類不能new一個物件,那麼存在構造器嗎? 答 存在
//抽象類存在的意義是什麼? 抽象出來-->提高開發效率,可擴充套件性提高。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package opp102503;

public abstract class Action {
public Action() {
}

public abstract void doSomething();
}
package opp102503;
//抽象類的所有方法,繼承它的子類,都必須要實現它的抽象方法,普通方法不一定要重寫
//如果子類本身是抽象的就沒必要實現繼承來的抽象方法,讓子子類去實現

//總結:繼承自抽象類的子類,必須實現父類的所有抽象方法

//extends 單繼承 Java中介面可以多繼承!
public class A extends Action {
@Override
public void doSomething() {

}
//抽象類特點
//1.不能new這個抽象類,只能靠子類實現它,約束!
}
package opp102503;

public class Application {
public static void main(String[] args) {
//new Action();
}
}

介面

  • 普通類:只有具體實現

  • 抽象類:具體實現和規範(抽象方法)都有

  • 介面:只有規範!自己無法寫方法,專業的約束!約束和實踐分離:面向介面程式設計

  • 介面就是規範,定義的是一組規則,體現了現實世界中“如果你是...則必須能...”的思想。如果你是天使則必須能飛。如果你是汽車,則必須能跑。如果你是好人則必須幹掉壞人。如果你是壞人則必須欺負好人。

  • 介面的本質是契約,就像我們人間的法律一樣。制定好後大家都遵守。

  • OO的精髓,是對物件的抽象,最能體現這一點的就是介面。為什麼我們討論設計模式都只針對具備了抽象能力的語言(比如C++,Java,C#等),就是因為設計模式所研究的,實際上就是如何合理的去抽象。

宣告類的關鍵字是class,宣告介面的關鍵字是interface

package opp102504;

//抽象的思維 Java 架構師

//interface 定義的關鍵字 介面都需要有實現類
public interface UserService {
//介面中的所有定義其實都是抽象的public

//public abstract都不必寫
//public abstract void run();
//介面定義的方法都是public abstract

//一般沒人在接口裡定義常量
//常量~public static final
public static final int AGE = 99;

void add(String name);//增
void delete(String name);//刪
void update(String name);//改
void query(String name);//查

}
package opp102504;

//public class UserServiceImpl {//implement v.實現 n.工具//java中implements是關鍵字

//抽象類:extends 單繼承
//類可以實現介面 implements 介面 多繼承
//實現了介面的類,就需要重寫介面的方法
//利用介面實現(偽)多繼承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add(String name) {

}

@Override
public void delete(String name) {

}

@Override
public void update(String name) {

}

@Override
public void query(String name) {

}

@Override
public void timer() {

}
}
package opp102504;

public interface TimeService {
void timer();
}
  • 總結作用:

    • 約束

    • 定義一些方法讓不同的人實現 10 --->

    • public abstract

    • public static final

    • 介面不能被例項化,介面中沒有構造方法

    • 抽象類可以有構造器 需要通過構造鏈來呼叫

    • implements可以實現多個介面

    • 必須要重寫介面中的方法

    • 總結部落格


內部類

  • 內部類就是在一個類的內部定義一個類,比如,A類中定義一個B類,那麼B類相對A類來說就稱為內部類,而A類相對B類來說就稱為外部類了。

  • 成員內部類

  • 靜態內部類

  • 區域性內部類

  • 匿名內部類

正常的(允許多個public出現在內部)

package opp102505;

public class Outer {

private int id = 10;
public void out(){
System.out.println("這是外部類的方法");
}


public class Inner{
public void in(){
System.out.println("這是內部類的方法");
}

//獲得外部類的私有屬性
public void getID(){
System.out.println(id);
}
}
}
package opp102505;

public class Application {
public static void main(String[] args) {
//new

Outer outer = new Outer();

//通過這個外部類來例項化內部類
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}

靜態的

package opp102505;

public class Outer {

private int id = 10;
public void out(){
System.out.println("這是外部類的方法");
}


public static class Inner{
public void in(){
System.out.println("這是內部類的方法");
}

//獲得外部類的私有屬性
public void getID(){
//一旦成為靜態類先訪問內部類,id未訪問所以報錯
//System.out.println(id);
}
}
}

區域性內部類

public class Outer {

//區域性內部類 不允許有public類
public void method(){
class Inner{
public void in(){

}

}
}
}

匿名內部類

package opp102505;

public class Test {
public static void main(String[] args) {
//有名字初始化物件
Apple apple = new Apple();

//沒有名字初始化類,不用將例項儲存在變數中
new Apple().eat();

//會返回一個UserService物件,但是這個類也沒有名字!
UserService userService = new UserService(){
@Override
public void hello() {

}
};

//匿名內部類
new UserService(){
@Override
public void hello() {

}
};

}
}

interface UserService{
void hello();
}

class Apple{
public void eat(){
System.out.println("1");
}
}