Java面向物件
面向程序&面向物件
面向程序:
- 步驟清晰簡單,第一步做什么,第二步做什么......
- 面向程序適合處理一些較為簡單的事情
面向物件:
- 物以類聚,分類的思維模式,思考問題首先會解決問題需要哪些分類,然后對這些分類進行單獨思考,最后,才對某個分類下的細節進行面向程序的思索,
- 面向物件適合處理復雜的問題,適合處理需要多人協作的問題,
概述:對于描述復雜的事物,為了從宏觀上把握、從整體上合理分析,我們需要使用面向物件的思路來分析整個系統,但是,具體到微觀操作,仍然需要面向程序的思路去處理,
什么是面向物件?
面向物件(Object-Oriented Programming, OOP)的本質是以類的方式組織代碼,以物件的方式封裝資料,
三大特性:
- 封裝
- 繼承
- 多型
注意:
- 從認識論的角度考慮,是先有物件后有類,因為物件是具體的,而類是抽象的,類是對物件的抽象,
- 從代碼運行的角度考慮,是先有類后有物件,類是物件的模板,
類與物件的關系
類是一種抽象的資料型別,它是對某一類事物的整體描述或定義,但并不能代表某一個具體的事物,
- 如:人、動物、植物、電腦、手機,等等......
物件是抽象概念的具體實體,
- 如:張三、隔壁家的小花貓咪咪、《唐伯虎點秋香》里的那只名叫旺財的狗
初始化與創建物件
創建的方式:使用new關鍵字創建物件
使用new關鍵字創建物件的時候,除了分配記憶體空間之外,還會給創建好的物件賦默認值進行初始化,以及呼叫類中的構造器,
示例:
Student類
package com.wmwx.oop.Demo01;
//學生類
public class Student {
//屬性:欄位
String name;
int age;
//方法
public void study(){
System.out.println("學生"+this.name+"在學習,");
}
}
Application類(啟動類)
package com.wmwx.oop.Demo01;
//啟動類
public class Application {
//一個專案應該只存在一個main方法
public static void main(String[] args) {
//類是抽象的,需要實體化
//類實體化后會回傳一個自己的物件
//student物件是Student類的一個實體
Student student = new Student();
student.study(); //輸出"學生null在學習,"
student.name = "小明";
student.study(); //輸出"學生小明在學習,"
}
}
構造方法
當一個物件被創建時候,構造方法用來初始化該物件,構造方法和它所在類的名字相同,但構造方法沒有回傳值,
一個類即使什么都不寫,也會存在一個構造方法,因為 Java 自動提供了一個默認構造方法,其訪問修飾符和類的訪問修飾符相同,
一旦自己定義了構造方法,默認的構造方法就會失效,
示例:
Person類:
package com.wmwx.oop.Demo01;
public class Person {
String name;
//使用快捷鍵alt+insert可以自動生成構造方法
//無參構造
public Person(){
this.name = "一個無名氏";
}
//有參構造(一旦定義有參構造,就必須顯式定義無參構造)
public Person(String name){
this.name = name;
}
}
Application類:
package com.wmwx.oop.Demo01;
public class Application {
public static void main(String[] args) {
//使用new關鍵字,本質是在呼叫構造方法
Person person1 = new Person(); //呼叫無參構造
System.out.println(person1.name); //輸出"一個無名氏"
//利用構造方法,可以初始化物件
Person person2 = new Person("惟妙惟霄"); //呼叫有參構造
System.out.println(person2.name); //輸出"惟妙惟霄"
}
}
記憶體分析
程序如下:
- 創建類
- 在堆中存放類和類中的靜態方法
- 創建物件
- 在堆中為物件開辟空間
- 在堆疊中存放物件的參考變數名
- 令物件的參考變數名指向堆中開辟的空間
封裝
所謂封裝,即該露的露,該藏的藏,程式設計要追求“高內聚,低耦合”,
高內聚:類的內部資料操作細節自己完成,不允許外部干涉,
低耦合:僅暴露少量的方法給外部使用,
對于代碼而言,總結起來就一句話:屬性私有,get/set,
意義:
- 提升程式的安全性,保護資料
- 隱藏代碼的實作細節
- 統一介面
- 提高了系統的可維護性
示例:
Student類:
package com.wmwx.oop.Demo03;
public class Student {
//屬性私有
private String name;
private int id;
private String gender;
private int age;
//需要提供共有的get和set方法
//get方法:獲取資料
public String getName() {
return name;
}
//set方法:設定資料
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age<0||age>120){
this.age = 3;
}else{
this.age = age;
}
}
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo03.Student;
//啟動類
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.setName("惟妙惟霄");
student.setId(123456);
student.setGender("男");
student.setAge(130);
System.out.println(student.getAge()); //輸出3
}
}
繼承
繼承的本質是對某一批類的抽象,從而實作對現實世界更好的建模,
在 Java 中通過 extends 關鍵字可以宣告一個類是從另外一個類繼承而來的,其語法如下:
class 子類 extends 父類 {
}
extends的意思是擴展,子類是對父類的擴展,
繼承的注意事項:
-
Java只有單繼承,沒有多繼承,
-
在Java中,所有類都默認直接或間接繼承自Object類,
在Java中,可以使用this指代當前類,并使用super指代父類,
super的注意事項:
- super呼叫父類的構造方法,必須在構造方法的第一行,
- super只能出現在子類的方法或構造方法中,
- super和this不能同時呼叫構造方法,
重寫是子類對父類的允許訪問的方法的實作程序進行重新撰寫, 回傳值和形參都不能改變,重寫的好處在于子類可以根據需要,定義特定于自己的行為, 也就是說,子類能夠根據需要實作父類的方法,重寫需要遵守以下規則:
- 方法名必須相同
- 引數串列必須相同
- 修飾符的范圍可以擴大,但不能縮小
- 拋出的例外可以被縮小,但不能擴大
示例:
Person類:
package com.wmwx.oop.Demo04;
//父類:人類
public class Person {
private int money = 10_0000_0000;
protected String name = "惟妙惟霄";
public Person() {
System.out.println("Person的無參構造方法執行了!");
}
public void say(){
System.out.println("說了一句話,");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void print(){
System.out.println("Person");
}
}
Student類:
package com.wmwx.oop.Demo04;
//子類:學生類
public class Student extends Person{
private String name = "妙霄";
public Student() {
//隱藏代碼:super();
//父類的構造方法必須要在子類的構造方法的第一行
System.out.println("Student的無參構造方法執行了!");
}
public void test1(String name){
System.out.println(name); //輸出引數
System.out.println(this.name); //輸出當前類的name
System.out.println(super.name); //輸出父類的name
}
//重寫都是方法的重寫,與屬性無關
//只允許重寫public方法
//可以使用快捷鍵alt+insert來插入重寫方法
@Override
public void print() {
System.out.println("Student");
}
public void test2(){
print();
this.print();
super.print();
}
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo04.Person;
import com.wmwx.oop.Demo04.Student;
//啟動類
public class Application {
public static void main(String[] args) {
Student student = new Student();
//第一行輸出"Person的無參構造方法執行了!"
//第二行輸出"Student的無參構造方法執行了!"
student.say(); //子類繼承父類,就會擁有父類的public方法
System.out.println(student.getMoney()); //可以用父類的get/set方法對屬性進行操作
//可以使用快捷鍵ctrl+H來查看繼承樹
student.test1("MiaoXiao");
//第一行輸出"MiaoXiao"
//第二行輸出"妙霄"
//第三行輸出"惟妙惟霄"
student.test2();
//第一行輸出"Student"
//第二行輸出"Student"
//第三行輸出"Person"
Student stu1 = new Student();
stu1.print(); //輸出"Student"
//父類的參考指向了子類
Person stu2 = new Student();
stu2.print(); //輸出"Student"
}
}
多型
多型是同一個行為具有多個不同表現形式或形態的能力,當使用多型方式呼叫方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,再去呼叫子類的同名方法,
多型存在的三個必要條件:
- 繼承
- 重寫
- 父類參考指向子類物件:
Parent p = new Child();
不能被重寫的方法:
- static 方法
- final 方法
- private 方法
示例:
Person類:
package com.wmwx.oop.Demo05;
public class Person {
public void run(){
System.out.println("人在跑步,");
}
}
Student類:
package com.wmwx.oop.Demo05;
public class Student extends Person{
@Override
public void run() {
System.out.println("學生在跑步,");
}
public void eat(){
System.out.println("學生在吃東西,");
}
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo05.Person;
import com.wmwx.oop.Demo05.Student;
//啟動類
public class Application {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//但可以指向的參考型別是不確定的
Student s1 = new Student();
Person s2 = new Student(); //父類的參考指向子類
Object s3 = new Student();
s1.run(); //輸出"學生在跑步"
s2.run(); //子類重寫父類方法,將執行子類方法,輸出"學生在跑步,"
s1.eat(); //輸出"學生在吃東西"
//s2.eat(); //不能呼叫,物件能使用哪些方法,要看左邊的型別,
((Student)s2).eat(); //強制型別轉換,輸出"學生在吃東西,"
}
}
instanceof
Java中的instanceof關鍵字可以用來判斷某一個物件是不是某一個類是實體,如果是,回傳true;如果不是,回傳false;如果二者無關,則編譯不通過,
示例:
package com.wmwx.oop;
import com.wmwx.oop.Demo06.Person;
import com.wmwx.oop.Demo06.Student;
import com.wmwx.oop.Demo06.Teacher;
//啟動類
public class Application {
public static void main(String[] args) {
//繼承關系如下:
//Object -> Person -> Student
//Object -> Person -> Teacher
//Object -> String
Object object = new Student();
System.out.println(object instanceof Student); //輸出true
System.out.println(object instanceof Person); //輸出true
System.out.println(object instanceof Object); //輸出true
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); //輸出true
System.out.println(person instanceof Person); //輸出true
System.out.println(person instanceof Object); //輸出true
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); //輸出true
System.out.println(student instanceof Person); //輸出true
System.out.println(student instanceof Object); //輸出true
//System.out.println(student instanceof Teacher);//編譯時報錯
//System.out.println(student instanceof String); //編譯時報錯
}
}
型別轉換
- 子類轉換為父類,是向上轉型,可自動轉換,
- 父類轉換為子類,是向下轉型,需強制轉換,
示例:
Person類:
package com.wmwx.oop.Demo06;
public class Person {
public void run(){
System.out.println("人在跑步,");
}
}
Student類:
package com.wmwx.oop.Demo06;
public class Student extends Person{
public void walk(){
System.out.println("學生在走路,");
}
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo06.Person;
import com.wmwx.oop.Demo06.Student;
//啟動類
public class Application {
public static void main(String[] args) {
//高 ----------------- 低
Person person = new Student();
((Student)person).walk(); //強制型別轉換
Student student = new Student();
Person obj = student; //子類轉換為父類,可能會丟失一些方法
//obj.walk(); //編譯時報錯
}
}
靜態代碼塊
靜態代碼塊會在類加載時執行,且只會執行一次,
示例:
Person類:
package com.wmwx.oop.Demo07;
public class Person {
//第二個執行,可在這里賦初始值
{
System.out.println("匿名代碼塊");
}
//第一個執行,只執行一次
static {
System.out.println("靜態代碼塊");
}
//第三個執行
public Person() {
System.out.println("構造方法");
}
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo07.Person;
//啟動類
public class Application {
public static void main(String[] args) {
Person person = new Person();
//第一行輸出"靜態代碼塊"
//第二行輸出"匿名代碼塊"
//第三行輸出"構造方法"
}
}
抽象類
在Java語言中使用abstract 來定義抽象類,其基本語法如下:
abstract class 類名{
//屬性
//方法
}
抽象類除了不能實體化物件之外,類的其它功能依然存在,成員變數、成員方法和構造方法的訪問方式和普通類一樣,
由于抽象類不能實體化物件,所以抽象類必須被繼承,才能被使用,在Java中一個類只能繼承一個抽象類,但一個類可以實作多個介面,
在Java語言中使用abstract 來定義抽象方法,其基本語法如下:
abstract 訪問修飾符 回傳值型別 方法名(引數);
抽象類與抽象方法的規則:
- 抽象類不能被實體化(即不能被 new ),只有抽象類的非抽象子類可以創建物件,
- 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類,
- 抽象類中的抽象方法只是宣告,不包含方法體,也就是不給出方法的具體實作,
- 構造方法、類方法(用 static 修飾的方法)不能宣告為抽象方法,
- 抽象類的子類必須給出抽象類中的抽象方法的具體實作,除非該子類也是抽象類,
示例:
Action類:
package com.wmwx.oop.Demo08;
//使用abstract宣告抽象類
public abstract class Action {
//抽象方法,只有方法名,沒有方法體
//僅作約束,期待他人實作
public abstract void doSomething();
}
A類:
package com.wmwx.oop.Demo08;
public class A extends Action{
//子類必須實作父類的抽象方法
//除非該子類是抽象類
@Override
public void doSomething() {
}
}
介面
介面在JAVA編程語言中是一個抽象型別,是抽象方法的集合,通常以 interface 來宣告,其基本語法如下:
[訪問修飾符] interface 介面名稱 [extends 其他的介面名稱] {
// 抽象方法
}
介面的特性:
- 介面中每一個方法都是隱式抽象的,介面中的方法會被隱式地指定為 public abstract,并且只能是 public abstract,
- 介面中可以含有變數,但是介面中的變數會被隱式地指定為 public static final ,并且只能是 public static final,
- 介面中的方法不能在介面中實作,只能由實作介面的類來實作介面中的方法,
- 一個介面能繼承另一個介面,使用 extends 關鍵字.子介面會繼承父介面的方法,
當類實作介面的時候,需要實作介面中所有的方法,否則,類必須宣告為抽象的類,Java中使用 implements 關鍵字實作介面,其基本語法如下:
class 類名 implements 方法名{
//實作介面中的抽象方法
}
示例:
UserService介面:
package com.wmwx.oop.Demo09;
//定義介面使用關鍵字interface
public interface UserService {
//介面中的所有屬性都是public static final
//一般不在介面中定義屬性
int age = 60;
//介面中的所有方法都是public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
TimeService介面:
package com.wmwx.oop.Demo09;
public interface TimeService {
void timer();
}
UserServiceImpl類:
package com.wmwx.oop.Demo09;
//類使用關鍵字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() {
}
}
內部類
所謂內部類,就是在一個類的內部再定義一個類,
示例:
Outer類:
package com.wmwx.oop.Demo10;
//外部類
public class Outer {
private int id=10;
public void out(){
System.out.println("這是外部類的方法!");
}
public class Inner{
public void in(){
System.out.println("這是內部類的方法!");
}
//獲得外部類的私有屬性
public int getId(){
return id;
}
}
public void method(){
//區域內部類,在外部類的方法之中
class Inner{
}
}
}
//一個java檔案可以有多個class,但是只能有一個public class
class A{
}
Application類:
package com.wmwx.oop;
import com.wmwx.oop.Demo09.UserService;
import com.wmwx.oop.Demo10.Outer;
//啟動類
public class Application {
public static void main(String[] args) {
//外部類使用new關鍵字
Outer outer = new Outer();
outer.out();
//內部類通過外部類來實體化
Outer.Inner inner = outer.new Inner();
inner.in();
System.out.println(inner.getId());
//匿名類,不用將實體保存到變數中
new Outer().out();
//使用匿名類實作介面
UserService userService = new UserService() {
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/265028.html
標籤:Java
