Java面向物件簡單筆記
面向物件程式設計(oop)
面向過程&面向物件
- 面向過程思想(線性思維)
步驟清晰簡單,第一步做什麼,第二步做什麼.....面
對過程適合處理一些較為簡單的問題
- 面向物件思想
物以類聚,分類的思維模式,思考問題首先會解決問題需要哪些分類,然後對這些分類進行單獨思考。最後,才對某個分類下的細節進行面向過程的思索。
面向物件適合處理複雜的問題,適合處理需要多人協作的問題!
- 對於描述複雜的事物,為了從巨集觀上把握、從整體上合理分析,我們需要使用面向物件的思路來分析整個系統。但是,具體到微觀操作,仍然需要面向過程的思路去處理。
什麼是面向物件
面向物件程式設計(Object-Oriented Programming, OOP)
面向物件程式設計的本質就是:以類的方式組織程式碼,以物件的形式組織(封裝)資料。
抽象 程式設計思想,持續的學習
三大特性:
封裝:包裝
繼承
多型
從認識論角度考慮是先有物件後有類。物件,是具體的事物。類,是抽象的,是對物件的抽象
從程式碼執行角度考慮是先有類後有物件。類是物件的模板。
方法及加深:
方法的定義:
-
修飾符
-
返回型別
/* 修飾符 返回值型別 方法名(...){ //方法體 return 返回值; } */ public String sayHello() { return "Hello world"; }
-
break和return的區別:break跳出語句,結束迴圈;return結束方法,返回一個結果!
-
方法名:注意規範,駝峰命名,見名知意
-
引數列表:(引數型別,引數名)...
-
異常丟擲,
方法的呼叫:遞迴
-
靜態方法
-
非靜態方法
-
形參和實參
程式碼:
package com.oop.demo01; public class Demo03 { public static void main(String[] args) { //實際引數和形式引數的型別要對應! int add = Demo03.add(1, 5); System.out.println(add); } public static int add(int a, int b) { return a + b; } }
-
值傳遞和引用傳遞
引用傳遞:
package com.oop.demo01; //引用傳遞:物件,本質還是值傳遞 public class Demo05 { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); //輸出null Demo05.change(person); System.out.println(person.name); //ljy } public static void change(Person person) { //person是一個物件,指向的--->Person person = new Person();這是一個具體的人,可以改變屬性 person.name = "ljy"; } } //定義一個Person類,有一個屬性: class Person { String name; //預設值為null }
值傳遞:
package com.oop.demo01;
//值傳遞
public class Demo04 {
public static void main(String[] args) {
int a = 1;
System.out.println(a);
Demo04.change(a);
System.out.println(a);
}
//返回值為空
public static void change(int a) {
a = 10;
}
}
- this關鍵字
類與物件的關係
類是一種抽象的資料型別,它是對某一類事物整體描述/定義,但是並不能代表某一個具體的事物
- 動物、植物、手機
- Person類、Pet類、Car類,這些類都是用來描述/定義某一類具體的事物應該具備的特點和行為
物件是抽象概念的具體例項
- 張三就是人的一個具體例項,張三家裡的旺財就是狗的一個具體例項。
- 能夠體現出特點,展現出功能的是具體的例項,而不是一個抽象的概念.
建立與初始化物件
使用new關鍵字建立物件
使用new關鍵字建立的時候,除了分配記憶體空間之外,還會給建立好的物件進行預設的初始化以及對類中構造器的呼叫。
類中的構造器也稱為構造方法,是在進行建立物件的時候必須要呼叫的。並且構造器有以下倆個特點:
- 必須和類的名字相同
- 必須沒有返回型別,也不能寫void
構造器必須要掌握
構造器作用:
-
使用new關鍵字,本質是在呼叫構造器
-
用來初始化值
構造器:
- 和類名相同
- 沒有返回值
注意點:定義有參構造之後,如果想使用無參構造,顯示的定義一個無參構造
程式碼練習:
package com.oop.Demo02;
//學生類
public class Student {
//屬性:欄位
String name; //預設null
int age; // 預設0
//方法
public void stduy() {
System.out.println(this.name + "在學習");
}
}
/* //這個專案測試類 可以在Application中直接使用
public static void main(String[] args) {
//類:抽象的,例項化
//類例項化後會返回一個自己的物件!
//student物件就是一個Student類的具體例項
Student 小明 = new Student();
小明.name="小明明";
小明.age=3;
System.out.println(小明.name);
System.out.println(小明.age);
}
*/
package com.oop.Demo02;
//java--->class
public class Person {
//一個類即使什麼都不寫 它也會存在一個方法
//顯示的定義構造器
String name;
//例項化初始值
public Person() {
this.name = "ljy";
}
//有參構造:一旦定義了有參構造,無參就必須顯示定義
public Person(String name) {
this.name = name;
}
}
/*
public static void main(String[] args) {
//new 例項化了一個物件
Person person = new Person();
System.out.println(person.name);
}
*/
練習程式碼:
package com.oop.Demo03;
public class Pet {
public String name;
public int age;
//無參構造
public void shout() {
System.out.println("叫了一聲");
}
}
/*
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "xzl";
dog.age = 20;
dog.shout();
System.out.println(dog.age);
System.out.println(dog.name);
}
*/
alt+insert 自動生成構造器
簡單小結類與物件
-
類與物件
類是一個模板:抽象 ,物件是一個具體的
-
方法:
定義、呼叫!
-
物件的引用
引用型別: 對應的基本型別(8個)
物件是通過引用來操作的:棧----->堆
-
屬性:欄位(field) 成員變數
預設初始化:
數字: 0 0.0
char:u0000
boolean:false
引用:null
屬性的定義:
修飾符 屬性型別 屬性名= 屬性值!
-
物件的建立和使用
-必須使用new關鍵字創造物件,構造器 Person ljy= new Person();
物件的屬性 ljy.name
物件的方法 ljy.sleep()
- 類:
靜態的屬性 屬性
動態的行為 方法
封裝
高內聚,低耦合(高內聚就是類的內部資料操作細節自己完成,不允許外部干涉;低耦合:僅暴露少量的方法給外部使用。)
封裝(資料的隱藏)
通常,應禁止直接訪問一個物件中資料的實際表示,而應通過操作介面來訪問,這稱為資訊隱藏。
記住:屬性私有,get/set
意義:
-
提高程式的安全性,保護資料
-
隱藏程式碼的實現細節
-
統一介面
-
系統可維護提高了
練習程式碼:
package com.oop.Demo04;
//類 private:私有
public class Student {
//屬性私有
private String name;//名字
private int id; //學號
private char sex;//性別
private int age;
//提供一些可以操作這個屬性的方法
//提供一些public的get、set方法
//get 獲得這個資料
public String getName() {
return this.name;
}
//set給這個資料設定值
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 120 && age > 0) {
this.age = age;
} else {
this.age = 3;
}
}
}
/*
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("ljy");
System.out.println(s1.getName());
s1.setAge(500); //不合法
System.out.println(s1.getAge());
}
*/
繼承
繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模。
extands的意思是"拓展"。子類是父類的擴充套件
Java中類只有單繼承,沒有多繼承(兒子只能一個有一個爸爸,但是爸爸可以有多個兒子)
繼承是類和類之間的一種關係。除此之外,類和類之間的關係還有依賴、組合、聚合等。
繼承關係的倆個類,一個為子類(派生類),一個為父類(基類)。子類繼承父類,使用關鍵字extends來表示。
子類和父類之間,從意義上講應該具有"is a"的關係.
子類繼承了父類就會擁有父類的全部方法
object類
supber
私有的可以被繼承,但是不能被訪問
package com.oop.Demo05extends;
//繼承
//Person 人 父類
public class Person {
//public (修飾符)
//protected
// default
//private
protected String name = "ljy";
public void print() {
System.out.println("Person");
}
}
package com.oop.Demo05extends;
//學生is人 派生類,子類
public class Student extends Person {
private String name = "lijinyu";
public void test(String name) {
System.out.println(name); //李晉宇
System.out.println(this.name); //lijinyu
System.out.println(super.name);//ljy
}
}
package com.oop;
import com.oop.Demo05extends.Student;
public class Application {
public static void main(String[] args) {
Student student=new Student();
student.test("李晉宇");
}
}
練習2:
package com.oop.Demo05extends;
//繼承
//Person 人 父類
public class Person {
//public (修飾符)
//protected
// default
//private
public Person(){
System.out.println("Person無參構造執行");
}
protected String name = "ljy";
public void print() {
System.out.println("Person");
}
}
package com.oop.Demo05extends;
//學生is人 派生類,子類
public class Student extends Person {
public Student() {
//隱藏程式碼;呼叫了父類的無參構造
// super() 隱藏的 呼叫父類的構造器,必須要在子類構造器的第一行
System.out.println("Student無參執行");
}
private String name = "lijinyu";
public void print() {
System.out.println("Student");
}
public void test1(String name) {
print();//Student
this.print();//Student
super.print();//Person
}
public void test(String name) {
System.out.println(name); //李晉宇
System.out.println(this.name); //lijinyu
System.out.println(super.name);//ljy
}
}
package com.oop;
import com.oop.Demo05extends.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
//student.test("李晉宇");
// student.test1("李晉宇");
}
}
重點筆記:
super注意點:
1. super呼叫父類的構造方法,必須在構造方法的第一個
2. super必須只能出現在子類的方法或者構造方法中!
3. super和this不能同時呼叫構造方法
vs this.
代表的物件不同
this:本事呼叫者這個物件
super:代表父類物件的應用
前提:
this:沒有繼承也可以使用
super:只能在繼承條件下才能使用
構造方法:
this():呼叫的本類的構造
super:父類的構造!
方法重寫
重寫都是方法的重寫,和屬性無關
總結:
重寫:需要有關係,子類重寫父類的方法
1. 方法名必須相同
2. 引數列表必須相同
3. 修飾符:範圍可以擴大, public>protected>default>private
4.丟擲的異常:範圍可以被縮小,但不能擴大:ClassNotFoundException-->Exception(大)
重寫,子類的方法和父類必須一致:方法體不同!
為什麼需要重寫:
1. 父類的功能子類不一定需要,或者不滿足
2. alt+insert ; override
重寫程式碼:
package com.oop.Demo05extends;
//重寫都是方法的重寫,和屬性無關
public class B {
public void test() {
System.out.println("B=>test()");
}
}
package com.oop.Demo05extends;
public class A extends B {
//override 重寫
@Override
public void test() {
System.out.println("A=>test()");
}
}
package com.oop;
import com.oop.Demo05extends.A;
import com.oop.Demo05extends.B;
public class Application {
//靜態方法和非靜態的方法區別很大
//靜態方法:方法的呼叫只和左邊有關,定義的資料型別有關
//非靜態:重寫
public static void main(String[] args) {
//方法的呼叫紙盒左邊,定義的資料型別有關
A a = new A();
a.test(); //A
//父類的引用指向了子類
B b = new A(); // 子類重寫了父類的方法
b.test(); //B
}
}
多型
即同一方法可以根據傳送物件的不同而採用多種不同的行為方式。
一個物件的實際型別是確定的,但可以指向物件的引用的型別有很多
多型存在的條件:
- 有繼承關係
- 子類重寫父類方法
- 父類引用指向子類物件
注意事項:
-
多型是方法的多型,屬性沒有多型
-
父類和子類,有聯絡, 轉換異常 ClassCastException!
-
存在條件:繼承關係,方法需要重寫,父類的引用指向子類物件
static 方法,屬性類,不屬於例項
final 常量; private方法 三種都不可以重寫 更不能多型
package com.oop.Demo06;
public class Person {
public void run() {
System.out.println("run");
}
}
package com.oop.Demo06;
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat() {
System.out.println("eae");
}
}
package com.oop;
import com.oop.Demo06.Person;
import com.oop.Demo06.Student;
public class Application {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//new student();
// new Person();
//可以指向的引用型別就不確定了:父類的引用指向子類
//Student能呼叫的方法都是自己的或者繼承父類的!
Student s1 = new Student();
//Person父型別,可以指向子類,但是不能呼叫子類獨有的方法
Person s2 = new Student();
//物件能執行哪些方法,主要看物件左邊的型別,和右邊關係不大
s1.run(); //子類重寫了父類的方法,執行子類
s2.run();
}
}
instanceof(型別轉換)
System.out.println(x instanceof y); //能不能編譯通過,看是否存在父子關係,存在就是true反正false
練習程式碼:
public static void main(String[] args) {
//object>string
//object>Person>Teacher
//object>Person>student
Object object = new Student();
System.out.println(object instanceof Student);//trun
System.out.println(object instanceof Person);//trun
System.out.println(object instanceof Object);//trun
System.out.println(object instanceof Teacher);//False
System.out.println(object instanceof String);//False
System.out.println("============================");
Person person = new Student();
System.out.println(person instanceof Student);//trun
System.out.println(person instanceof Person);//trun
System.out.println(person instanceof Object);//trun
System.out.println(person instanceof Teacher);//False
//System.out.println(person instanceof String);//編譯報錯!
System.out.println("============================");
Student student = new Student();
System.out.println(student instanceof Student);//trun
System.out.println(student instanceof Person);//trun
System.out.println(student instanceof Object);//trun
// System.out.println(student instanceof Teacher);//編譯報錯!
// System.out.println(student instanceof String);//編譯報錯!
}
小結:
- 父類的引用指向子類的物件
- 把子類轉換為父類(向上轉型)
- 把父類轉換為子類(向下轉型) 需要強制轉換
- 方便方法的呼叫,減少重複程式碼!
程式碼練習:
package com.oop.Demo07;
public class Person {
public void run() {
System.out.println("run");
}
}
package com.oop.Demo07;
public class Student extends Person {
public void go(){
System.out.println("go");
}
}
package com.oop;
import com.oop.Demo07.Person;
import com.oop.Demo07.Student;
public class Application {
public static void main(String[] args) {
//型別之間的轉換: 父 子
// 高 低
Person obj = new Student();
//student將這個物件轉換為student型別,我們就可以使用student型別的方法了
//子類轉換為父類,可能丟失自己本來的一些方法
Student student = (Student) obj;
student.go();
// ((Student) obj).go(); 和上面兩行程式碼一樣
/*
Student ss = new Student();
ss.go();
Person person = student;
*/
}
}
static關鍵詞
注意:非靜態的可以直接訪問靜態的,靜態的不能直接訪問非靜態的。
package com.oop.Demo08;
//static
public class Student {
private static int age; //靜態變數 多執行緒
private double score; //非靜態變數
public void run() {
}
public static void go() {
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
// 非靜態的不能這樣訪問 推薦類名訪問 System.out.println(Student.score);
// System.out.println(s1.age);
// System.out.println(s1.score);
//非靜態可以訪問靜態的 靜態的不能直接訪問非靜態的。
}
}
package com.oop.Demo08;
public class Person {
//2:賦初值~
{
//程式碼塊(匿名程式碼塊)
System.out.println("匿名程式碼塊");
}
// 1 只執行一次~
static {
System.out.println("靜態程式碼塊");
}
//3
public Person() { //構造器
System.out.println("構造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("======================");
Person person2 = new Person();
}
}
package com.oop.Demo08;
//靜態匯入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象類
abstract修飾符可以用來修飾方法也可以修飾類,如果修飾方法,那麼該方法就是抽象方法;如果修飾類,那麼該類就是抽象類。
抽象類中可以沒有抽象方法,但是有抽象方法的類一定要宣告為抽象類。
抽象類,不能使用new關鍵字來建立物件,它是用來讓子類繼承的。
抽象方法,只有方法的宣告,沒有方法的實現,它是用來讓子類實現的。
子類繼承抽象類,那麼就必須要實現抽象類沒有實現的抽象方法,否則該子類也要宣告為抽象類。
package com.oop.Demo09;
//abstract 抽象類:類 extends:單繼承 (介面可以多繼承)
public abstract class Action {
//約束~ 有人幫我們實現
//abstract,抽象方法,只有方法的名字,沒有方法的實現
public abstract void doSometing();
//1.不能new這個類,只能靠子類去實現它:約束
//2.抽象類可以寫普通的方法
//3.抽象方法必須在抽象類中
//思考: new 存在構造器? 存在的意義。
}
package com.oop.Demo09;
//abstract 抽象類:類 extends:單繼承 (介面可以多繼承)
public abstract class Action {
//約束~ 有人幫我們實現
//abstract,抽象方法,只有方法的名字,沒有方法的實現
public abstract void doSometing();
//1.不能new這個類,只能靠子類去實現它:約束
//2.抽象類可以寫普通的方法
//3.抽象方法必須在抽象類中
//思考: new 存在構造器? 存在的意義:抽象出來,提高開發效率
}
介面
普通類:只有具體的實現
抽象類:具體實現和規範(抽象方法)都要
介面:只有規範,自己無法寫方法。 專業的約束,約束與實現分離,面對介面程式設計
介面就是規範,定義的是一組規則,體現了現實世界中“如果你是...則必須能..”的思想。如果你是天使,則必須能飛。如果你是汽車,則必須能跑。如果你好人,則必須幹掉壞人;如果你是壞人,則必須欺負好人。
介面的本質是契約,就像我們人間的法律一樣。制定好後大家都遵守。
OO(面向物件)的精髓,是對物件的抽象,最能體現這一點的就是介面。為什麼我們討論設計模式都只針對具備了抽象能力的語言(比如c++、java、c#等),就是因為設計模式所研究的,實際上就是如何合理的去抽象。
** 宣告類的關鍵詞是class,宣告介面的關鍵詞是interface**
作用:
- 約束
- 定義一些方法,讓不同的人實現
- 方法都是預設 public abstract
- 常量都是 public static final
- 介面不能被例項化~,介面中沒有構造方法
- implements可以實現多個介面
- 必須要重寫介面中的方法
練習程式碼:
package com.oop.Demo10;
public interface TimeService {
void time();
}
package com.oop.Demo10;
//抽象的思維 ~ Java
//interface 定義關鍵字 介面都需要實現類
public interface UserService {
//常量~ public static final(預設的)
int age = 99;
//介面中的所有定義都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package com.oop.Demo10;
//抽象類:extends
//類 可以實現介面 implements 介面
//實現了介面的類 必須要重寫介面中的方法
//多繼承~利用介面實現多繼承~
public class UserServiceImpl implements UserService,TimeService {
@Override
public void time() {
}
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
內部類
內部類就是在一個類的內部在定義一個類,不如:A類中定義一個B類,那麼B類相對A類來說就稱為內部類,而A類相對B類來說就是外部類了。
- 成員內部類
- 靜態內部類
- 區域性內部類
- 匿名內部類
程式碼:
package com.oop.Demo11;
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 com.oop;
import com.oop.Demo11.Outer;
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 com.oop.Demo11;
public class Outer {
//區域性內部類
public void method(){
class Inner{
public void in(){
}
}
}
}
//一個Java類中可以有多個class類,但只能有一個public class
package com.oop.Demo11;
public class Test {
public static void main(String[] args) {
//沒有名字初始化類,不用降例項儲存到變數中
new Apple().eat();
UserService userService= new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}
有要一起學習Java的小夥伴可以留下聯絡方法·