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()
,可有參可無參,必須放在建構函式中的第一行)
-
類與物件
類是一個模板:抽象的 物件是一個具體的例項
-
方法
定義,呼叫!
-
物件的引用
引用型別: 基本型別(8)
物件是通過引用來操作的 棧--->堆(地址)
-
屬性:欄位 Field 成員變數
預設初始化:
數字:0 0.0
char:u0000
boolean:false
引用:null
修飾符 屬性型別 屬性名 = 屬性值!
-
物件的建立和使用
-
必須使用new關鍵字創造物件,構造器 Person ergouzi = new Person();
-
物件的屬性 ergouzi.name
-
物件的方法 ergouzi.sleep()
-
-
類:
-
靜態的屬性 屬性
-
動態的行為 方法
封裝,繼承,多型
-
封裝
-
該露的露,該藏的藏
-
我們程式設計要求"高內聚,低耦合"。高內聚就是類的內部資料操作細節自己完成,不允許外部干涉;低耦合:僅暴露少量的方法給外部使用。
-
-
封裝(資料的隱藏)
-
通常,應禁止直接訪問一個物件中資料的實際表示,而應通過操作介面來訪問,這稱為資訊隱藏。
-
-
記住這句話就夠了:屬性私有,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注意點
-
super呼叫父類的構造方法,必須在構造方法的第一個
-
super必須只能出現在子類的方法或者構造方法中!
-
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 {
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 {
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{
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(){