程序導向&物件導向
- 程序導向:
- 步驟簡單清晰,第一步->第二步->....
- 程序導向適合處理一些較為簡單的問題
- 物件導向:
- 分類的思維模式
- 物件導向適合處理複雜的問題
- 對於描述複雜的事物,使用物件導向的思維去宏觀上把握、整體上分析,使用程序導向的思維去處理圍觀操作
什麼是物件導向
- 物件導向程式設計:(Object-Oriented Programming,OOP)
- 物件導向程式設計的本質就是:以類的方式組織程式碼,以物件的方式組織資料
- 3大特性:封裝,繼承和多型
- 從程式碼執行的角度考慮是先有類後有物件,類是物件的模板
回顧方法的定義
- 修飾符
- 返回型別
- break和return的區別:break 跳出switch選擇或者跳出當前迴圈;return結束方法和返回返回值
- 方法名:注意駝峰命名原則,見名知意
- 引數列表:引數型別、引數名;...可變引數->類似於可變陣列
- 異常丟擲:常見的有陣列下標越界 ArrayIndexOutOfBounds
package com.oop.demo01;
//Demo01類
public class Demo01 {
//main方法
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
String str = demo01.sayHello();
System.out.println(str);
int max = demo01.max(2,1);
System.out.println(max);
}
/*
修飾符 返回值型別 方法名(引數列表){
//方法體
return 返回值;
}
*/
public String sayHello(){
return "hello!";
}
public int max(int a,int b){
return a>b ? a : b; //三元運算子
}
}
回顧方法的呼叫:遞迴
- 靜態方法、非靜態方法
package com.oop.demo01;
//情況1
public class Student {
//非靜態方法
public void say(){
System.out.println("學生說話了");
}
}
public class Demo02 {
public static void main(String[] args) {
//例項化這個類 new
//物件型別 物件名 = 物件值
Student student = new Student();
student.say();
Demo02.a();
}
//靜態方法和類一起載入
public static void a(){
Demo02.b();
}
//靜態方法和類一起載入
public static void b(){
System.out.println("b");
}
}
package com.oop.demo01;
//情況2
public class Student {
//非靜態方法
public void say(){
System.out.println("學生說話了");
}
}
public class Demo02 {
public static void main(String[] args) {
//例項化這個類 new
//物件型別 物件名 = 物件值
Student student = new Student();
student.say();
Demo02.a();
}
//靜態方法和類一起載入
public static void a(){
Demo02 demo02 = new Demo02();
demo02.b();
}
//類例項化後才存在
public void b(){
System.out.println("b");
}
}
- 形參和實參
package com.oop.demo01;
public class Demo03 {
//實際引數與形式引數要對應
public static void main(String[] args) {
int add = Demo03.add(1,2); //1,2是實際引數
System.out.println(add);
}
public static int add(int a, int b){ //a,b是形式引數
return a+b;
}
}
- 值傳遞和引用傳遞
package com.oop.demo01;
public class Demo04 {
public static void main(String[] args) {
int a = 1;
System.out.println(a); //1
Demo04.change(a); //值傳遞
System.out.println(a); //1
}
//返回值為空
public static void change(int a){ //a是區域性變數,只能在方法裡生存
a = 10;
}
}
package com.oop.demo01;
//引用傳遞:物件,本質還是值傳遞
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
System.out.println(person.age);
Demo05.change(person);
System.out.println(person.name);
System.out.println(person.age);
}
public static void change(Person person){ //person是例項變數,從屬於物件Demo05
person.name = "huangshen";
person.age = 20;
}
}
//定義了一個Person類,有一個屬性:name
class Person{
String name; //null
int age; //0
}
類與物件的建立
- 類是一種抽象的資料型別,它是對某一類事物整體描述/定義,但是並不能代表某一個具體的事物
- 物件是抽象概念的具體例項
package com.oop.demo02;
public class Student {
//屬性
String name; //null
int age; //0
//方法
public void study(String name){
System.out.println(this.name+"在學習");
}
}
public class Aplication {
public static void main(String[] args) {
//類:抽象的,需要例項化
//類例項化後會返回一個自己的物件
//student物件就是一個Student類的具體例項
Student xm = new Student(); //建立小明
xm.name = "小明";
xm.age = 3;
System.out.println(xm.name);
System.out.println(xm.age);
xm.study(xm.name);
Student xh = new Student(); //建立小紅
xh.name = "小紅";
xh.age = 3;
System.out.println(xh.name);
System.out.println(xh.age);
xh.study(xh.name);
}
}
構造器詳解
- 使用new關鍵字建立物件
- 使用new關鍵字建立的時候,除了分配記憶體空間之外,還會給建立好的物件,進行預設的初始化以及對類中構造器的呼叫
- 類中的構造器也稱為構造方法,是在進行建立物件的時候必須要呼叫的。
- 並且構造器有以下兩個特點:
- 必須和類的名字相同
- 必須沒有返回型別,也不能寫void
- 構造器的作用:
- new本質在呼叫構造方法
- 初始化物件的值
- 注意點:
- 定義有參構造後如果想使用無參構造,必須顯示的定義一個無參構造
-
Alt + Insert:可以快速定義構造器
-
this. = 可以快速初始化物件的值
package com.oop.demo02;
//java->class
public class Person {
//一個類即使什麼都不寫,它也會存在一個方法
//顯示的定義構造器
String name;
int age;
//無參構造
public Person() {
}
//含有一個引數的有參構造
public Person(String name) {
this.name = name;
}
//含有兩個引數的有參構造
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
//一個專案只存一個main方法
public class Aplication {
public static void main(String[] args) {
//new例項化一個物件
Person person = new Person("huangshen",20);
System.out.println(person.name);
System.out.println(person.age);
}
}
建立物件記憶體分析
package com.oop.demo03;
public class Pet {
String name;
int age;
//無參構造
public void shout(){
System.out.println("叫了一聲");
}
}
package com.oop.demo03;
public class Aplication {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺財";
dog.age = 3;
System.out.println(dog.name);
System.out.println(dog.age);
dog.shout();
Pet cat = new Pet();
System.out.println(cat.name);
System.out.println(cat.age);
cat.shout();
}
}
封裝
- 屬性私有,get/set
- 封裝作用:
- 提高程式的安全性,保護資料
- 隱藏程式碼的實現細節
- 統一介面
- 系統可維護性增強
package com.oop.demo04;
public class Pet {
private String name;
private int age;
//無參構造
public void shout(){
System.out.println("叫了一聲");
}
//getName
public String getName() {
return name;
}
//setName
public void setName(String name) {
this.name = name;
}
//getAge
public int getAge() {
return age;
}
//setAge
public void setAge(int age) {
this.age = age;
}
}
package com.oop.demo04;
public class Aplication {
public static void main(String[] args) {
Pet dog = new Pet();
dog.setName("旺財");
System.out.println(dog.getName());
dog.setAge(3);
System.out.println(dog.getName()+dog.getAge()+"歲了");
dog.shout();
Pet cat = new Pet();
cat.setName("嘟嘟");
System.out.println(cat.getName());
cat.setAge(3);
System.out.println(cat.getName()+cat.getAge()+"歲了");
cat.shout();
}
繼承
- 繼承的特點:
- 繼承的本質是對某一批類的抽象
- extends的意思是"擴充"。子類是父類的擴充
- JAVA中只有單繼承,沒有多繼承
- 繼承是類和類的一種關係。除此以外,類和類之間的關係還有依賴、組合、聚合等
- 繼承關係的兩個類,一個為子類,一個為父類。子類繼承父類,使用關鍵字extends來表示
- 子類和父類之間,從意義上應該具有"is a"的關係
object類
package com.oop.demo05;
//在JAVA中,所有的類都預設直接或者間接繼承Object類
//Person是父類
//Ctrl + H 可以檢視繼承樹
public class Person {
//屬性一般是私有的
//要想使用屬性則需要使用封裝時留下的方法get/set
private int money = 10_0000_0000;
public void say(){
System.out.println("我喜歡錢!");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
package com.oop.demo05;
public class Student extends Person{
}
package com.oop.demo05;
public class Aplication {
public static void main(String[] args) {
Student student = new Student();
student.say();
student.setMoney(10_0000);
System.out.println("student有"+student.getMoney()+"元");
}
}
super
super注意點:
1.super呼叫父類的構造方法,必須在構造方法的第一個
2.super 必須只能出現在子類的方法和或者構造方法中!
3.super和this 不能同時呼叫構造方法
VS this:
1.代表的物件不同:
this:本身呼叫者這個物件
super: 代表父類物件的引用
2.前提:
this: 沒有繼承也可以使用
super: 只能在繼承條件才可以使用
3.構造方法:
this();本類的構造
super();父類的構造
package com.oop.demo06;
public class Person {
public Person(){ //Person的無參構造
System.out.println("Person的無參構造");
}
/*Person的有參構造,如果在子類Student預設呼叫,則無法呼叫,除非呼叫Person的無參構造
public Person(String name){
System.out.println("Person的無參構造");
}*/
//如果name是私有的則子類無法繼承
protected String name = "huangshen";
public void print(){
System.out.println("Person");
}
}
package com.oop.demo06;
public class Student extends Person {
public Student(){ //Student的無參構造
//隱藏程式碼:呼叫了父類的無參構造
//super("Student"); //呼叫父類的構造器,必須在子類構造器的第一行
//this(); //呼叫自己的構造器也必須放在第一行但是必須先呼叫父類的構造器
System.out.println("Student的無參構造");
}
private String name = "huangyilin";
public void print(){
System.out.println("Student");
}
//this表示當前類,super表示父類
public void test1(){
print(); //Student
this.print(); //Student
super.print(); //Person
}
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
package com.oop.demo06;
public class Aplication {
public static void main(String[] args) {
Student student = new Student();
student.test("hyl");
student.test1();
}
}
方法重寫
重寫:需要有繼承關係,子類重寫父類的方法
1.方法名必須相同
2.引數列表必須相同
3.修飾符:範圍可以擴大但不能縮小:public>protected>default>private
4.丟擲的異常:範圍可以縮小但不能擴大:ClassNotFoundException-->Exception大
重寫:子類的方法和父類必須一致,方法體不同!
為什麼需要重寫:
1.父類的功能,子類不一定需要或者不一定滿足
Alt + Insert : override;
package com.oop.demo07;
//重寫都是方法的重寫與屬性無關!!!
public class B {
public void test(){
System.out.println("B->test");
}
}
package com.oop.demo07;
//繼承
public class A extends B {
@Override //註解:有功能的註釋
public void test() {
System.out.println("A->test");
}
}package com.oop.demo07;
//靜態方法:方法的呼叫只和左邊的資料型別有關
//非靜態方法: 重寫
public class Aplication {
public static void main(String[] args) {
A a = new A();
a.test(); //A
//父類的引用指向了子類
B b = new A(); //子類重寫了父類的方法
b.test(); //B
}
}
多型
- 多型的注意事項:
- 多型是方法的多型,屬性沒有多型
- 父類和子類,有聯絡 ,型別轉化異常!ClassCastException
- 存在條件:繼承關係,方法需要重寫,父類引用指向子類物件!Father f1 = new Son();
-
static 方法,屬於類,不屬於例項
-
final 常量
-
private方法
-
型別轉換:
-
父類引用指向子類的物件
-
把子類轉換為父類,向上轉型;
-
把父類轉換為子類,向下轉型;強制轉換
-
方便方法的呼叫,減少重複的程式碼!
package com.oop.demo08;
public class Person {
public void run(){
System.out.println("run");
}
}
package com.oop.demo08;
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package com.oop.demo08;
public class Aplication {
public static void main(String[] args) {
//一個物件的實際型別是確定的
//new Student
//new Person
//可以指向的引用型別就不確定了:父類的引用指向子類
//Student 能呼叫的方法都是自己的或者繼承父類的!
Student s1 = new Student();
//Person 父型別,可以指向子類,但是不能呼叫子類獨有的方法
Person s2 = new Student();
Object s3 = new Student();
//物件能執行哪些方法,主要看物件左邊的型別,和右邊關係不大!
s1.eat();
s2.run(); //子類會重寫父類的方法,執行子類的方法
}
}
instanceof
- 判斷兩個型別之間是否存在父子關係
- (物件)instanceof(型別)
static關鍵字詳解
package com.oop.demo09;
//public final class Person {},則Person沒有子類
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();
Person person2 = new Person();
}
}
package com.oop.demo09;
public class Student {
private static int age; //靜態的變數,多執行緒!
private double score; //非靜態變數
public void run(){ //非靜態方法,從屬於物件
go();
}
public static void go(){ //靜態方法從屬於類,只載入一次
System.out.println("go!");
}
public static void main(String[] args) {
Student.go();;
}
}
package com.oop.demo09;
//靜態匯入包~
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);
}
}
抽象類
package com.oop.demo10;
//abstract 抽象類:extends: 單繼承 (介面可以多繼承)
public abstract class Action {
//約束~有人幫我們實現
//abstract ,抽象方法,只有方法名字 , 沒有方法的實現
private String name = "Action";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Action(){
System.out.println("Action 的構造器");
}
public abstract void doSomething();
public void print(){
System.out.println("print");
}
public void run(){
System.out.println("run");
}
/* 抽象類的特點:
* 1.不能new這個抽象類,只能靠子類去實現!
* 2.抽象類中可以寫普通的方法!
* 3.抽象方法必須在抽象類中!
* 思考:
* 1.new 抽象類的子類,原抽象類中存在構造器嗎?
* 存在構造器,而且如果new 子類的一個物件會先呼叫抽象類的構造器,然後呼叫子類的構造器
* 2.抽象類存在的意義是什麼?
* 抽象類有很多的抽象方法,子類必須根據自己的要求重寫這些抽象方法,而不同於抽象類的普通方法
*/
}
package com.oop.demo10;
public class B extends Action {
//抽象類的所有抽象方法,繼承了它的子類,都必須要實現~除非該類又是一個抽象類
public B(){
System.out.println("B 的構造器");
}
@Override
public void doSomething() {
System.out.println("BdoSomething");
}
@Override
public void print() {
System.out.println("Bprint");
}
}
package com.oop.demo10;
public class A extends Action{
//抽象類的所有抽象方法,繼承了它的子類,都必須要實現~除非該類又是一個抽象類
public A(){
System.out.println("A 的構造器");
}
@Override
public void doSomething() {
System.out.println("AdoSomething");
}
@Override
public void print() {
System.out.println("Aprint");
}
}
package com.oop.demo10;
public class Test {
public static void main(String[] args) {
A a = new A(); //a屬於A類
a.doSomething(); //a呼叫子類重寫抽象類的抽象方法
B b = new B(); //B屬於B類
b.doSomething(); //b呼叫子類重寫抽象類的抽象方法
Action a1 = new A(); //a1屬於A類
a1.print(); //a1呼叫子類重寫抽象類的方法(多型)
Action b1 = new B(); //b1屬於B類
b1.print(); //b1呼叫子類重寫抽象類的方法(多型)
b1.run(); //b1呼叫繼承父類的方法
b1.setName("B"); //name屬於Action類的私有屬性,故只能採用封裝的思想使用
System.out.println(b1.getName());
}
}
介面的定義和實現
- 普通類:只有具體實現
- 抽象類:具體實現和規範(抽象方法)都有!
- 介面:只有規範!以自己無法寫方法~專業的約束! 約束和實現分離:面向介面程式設計~
- 介面就是規範,定義的是一組規則,體現了現實世界中"如果你是...則必須能..."的思想
- 介面的本質是契約,就像人間的法律一樣,如果制定,必須遵守
- OO的精髓,是對物件的抽象,最能體現這一點的就是介面。為什麼討論設計模式都只針對具備抽象能力的語言(比如C++,Java,C#等),就是因為設計模式所研究的,實際上就是如何合理的去抽象
package com.oop.demo11;
public interface TimeService {
void timer();
}
package com.oop.demo11;
//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.demo11;
//抽象類: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() {
}
}
介面的作用
1.約束,只能規範
2.介面中定義的方法:public abstract
3.介面中定義的屬性:public static final
4.介面不能被例項化,介面不是類沒有構造方法
5.implements 可以實現多個介面
6.一旦繼承了介面,必須要重寫介面中的方法
N種內部類
成員內部類、靜態內部類
- 成員內部類:外部類裡包含一個內部類,直接載入內部類(可以獲得外部類的私有屬性)解決一些問題(封裝)
- 靜態內部類:外部類裡包含一個內部類,直接載入內部類(不可以獲得外部類的私有屬性)解決一些問題(封裝)
package com.oop.demo12;
public class Outer {
private int id = 10086;
public void out(){
System.out.println("外部類方法");
}
//成員內部類
//public static Inner{} 靜態內部類 -> 無法使用外部類的非靜態屬性
public class Inner{
public void in(){
System.out.println("內部類方法");
}
//可以獲得外部類的私有屬性
public void getID(){
System.out.println(id);
}
}
}
package com.oop.demo12;
public class Aplication {
public static void main(String[] args) {
Outer outer = new Outer();
outer.out();
//透過外部類Outer來例項化內部類Inner
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
區域性內部類、匿名內部類
- 匿名內部類:載入類的方法,使用區域性內部類解決問題(封裝細節)
/*區域性內部類*/
package com.oop.demo13;
public class Outer {
public void method(){
//區域性內部類
class Inner{
public void in(){
System.out.println("區域性內部類");
}
}
Inner inner = new Inner();
inner.in();
}
}
package com.oop.demo13;
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
- 匿名內部類:節省空間
/*匿名內部類*/
package com.oop.demo14;
public class Outer {
public static void main(String[] args) {
//沒有名字初始化類,不用將例項儲存到變數中
new Apple().eat();
UserService userService = new UserService(){
@Override
public void hello() {
System.out.println("hello");
}
};
userService.hello();
}
}
//匿名內部類
class Apple{
public void eat(){
System.out.println("eat Apple");
}
}
//匿名內部介面
interface UserService{
void hello();
}
異常
捕獲和丟擲異常
- 異常處理機制
- 丟擲異常
- 捕獲異常
- 異常處理五個關鍵字
- try、catch、finally、throw、throws
package com.exception;
public class Demo01 {
public static void main(String[] args) {
int a = 1;
int b = 0;
try { // try監控區域
System.out.println(a/b);
}catch (ArithmeticException e){ //catch 捕獲異常
System.out.println("程式出現異常,變數b不能為0");
}finally { //finally可以不要,假設I/O,資源出現異常,可以使用finally關閉
System.out.println("finally");
}
}
}
package com.exception;
public class Demo02 {
public static void main(String[] args) {
int a = 1;
int b = 0;
//假設要捕獲多個異常,從小到大!
try {
Demo02 demo02 = new Demo02();
demo02.a();
}catch (Exception e){
System.out.println("Exception");
}catch (Error e){
System.out.println("Error");
}catch (Throwable e){
System.out.println("Throwable");
}finally {
System.out.println("finally");
}
}
public void a(){b();}
public void b(){a();}
}
package com.exception;
public class Demo03 {
public static void main(String[] args) {
int a = 1;
int b = 0;
//選中要監控的程式碼 Ctrl + Alt + T
try {
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace(); //列印錯誤的棧資訊
} finally { // finally處理善後資訊
}
}
}
package com.exception;
public class Demo04 {
public static void main(String[] args) {
new Demo04().test(1,0);
}
public void test(int a,int b){
if (b==0){ //throw
throw new ArithmeticException();//主動丟擲異常,一般在方法中使用
}
}
}
package com.exception;
public class Demo05 {
public static void main(String[] args) {
new com.exception.Demo04().test(1,0);
}
//假設這個方法中,處理不了這個異常,就在方法上丟擲異常
public void test(int a,int b) throws ArithmeticException {}
}
自定義異常及經驗小結
package com.exception.finaldemo;
//定義的異常類
public class MyException extends Exception{
//傳遞數字10;
private int detail;
public MyException(int a){
this.detail = a;
}
//返回異常的資訊
@Override
public String toString() {
return "MyException{" + detail + '}';
}
}
package com.exception.finaldemo;
public class Test {
//可能會存在異常的方法
public static void test(int a)throws MyException{
System.out.println("傳遞的引數為:"+a);
if (a>10){
//在這個方法中處理不了這個異常,,就在方法上丟擲異常
throw new MyException(a);
}
System.out.println("ok!");
}
public static void main(String[] args) {
try {
test(20);
} catch (MyException e) {
//增加一些處理異常的程式碼
System.out.println(e);
}
}
}