JavaSE知識-08(面向對象_繼承&方法&final)


代碼塊的概述和分類

  • 根據其位置和聲明的不同,代碼塊可以分為局部代碼塊,構造代碼塊,靜態代碼塊,同步代碼塊。

  • 常見代碼塊的應用

    • a:局部代碼塊
      • 在方法中出現;限定變量生命周期,及早釋放,提高內存利用率
    • b:構造代碼塊 (初始化塊)
      • 在類中方法外出現;多個構造方法方法中相同的代碼存放到一起,每次調用構造都執行,並且在構造方法前執行
    • c:靜態代碼塊
      • 在類中方法外出現,並加上static修飾;用於給類進行初始化,在加載的時候就執行,並且只執行一次。
      • 一般用於加載驅動
class Demo1_Code {
	public static void main(String[] args) {
		{
			int x = 10;						//限定變量的聲明周期
			System.out.println(x);
		}
		
		Student s1 = new Student();
		System.out.println("---------------");
		Student s2 = new Student("張三",23);
	
	}

	static {
		System.out.println("我是在主方法類中的靜態代碼塊");
	}
}


class Student {
	private String name;
	private int age;

	public Student(){
		//study();
		System.out.println("空參構造");
	}					//空參構造

	public Student(String name,int age) {//有參構造
		//study();
		this.name = name;
		this.age = age;
		System.out.println("有參構造");
	}

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

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	{											//構造代碼塊:每創建一次對象就會執行一次,優先於構造函數執行
		//System.out.println("構造代碼塊");
		study();
	}

	public void study() {
		System.out.println("學生學習");
	}

	static {									//隨着類加載而加載,且只執行一次
		System.out.println("我是靜態代碼塊");	//作用:用來給類進行初始化,一般用來加載驅動
	}											//靜態代碼塊是優先於主方法執行
}

運行結果

繼承

class Demo1_Extends {
	public static void main(String[] args) {
		Cat c = new Cat();
		c.color = "花";
		c.leg = 4;
		c.eat();
		c.sleep();

		System.out.println(c.leg  + "..." + c.color);
	}
}

class Animal {
	String color;					//動物的顏色
	int leg;						//動物腿的個數

	public void eat() {				//吃飯的功能
		System.out.println("吃飯");
	}

	public void sleep() {			//睡覺的功能
		System.out.println("睡覺");
	}
}

class Cat extends Animal {
	
}

class Dog extends Animal {
	
}

/*
extends是繼承的意思
Animal是父類
Cat和Dog都是子類
*/
  • A:繼承的好處

    • a:提高了代碼的復用性
    • b:提高了代碼的維護性
    • c:讓類與類之間產生了關系,是多態的前提
  • B:繼承的弊端

    • 類的耦合性增強了。

    • 開發的原則:高內聚,低耦合。

    • 耦合:類與類的關系

    • 內聚:就是自己完成某件事情的能力

  • Java中類的繼承特點

    • a:Java只支持單繼承,不支持多繼承。(一個兒子只能有一個爹)
      • 有些語言是支持多繼承,格式:extends 類1,類2,...
    • b:Java支持多層繼承(繼承體系)
      • 如果想用這個體系的所有功能用最底層的類創建對象
      • 如果想看這個體系的共性功能,看最頂層的類
  • 繼承的注意事項

    • a:子類只能繼承父類所有非私有的成員(成員方法和成員變量)
    • b:子類不能繼承父類的構造方法,但是可以通過super關鍵字去訪問父類構造方法。
    • c:不要為了部分功能而去繼承
    • 項目經理 姓名 工號 工資 獎金
    • 程序員 姓名 工號 工資

this和super的區別和應用

  • this:代表當前對象的引用,誰來調用我,我就代表誰
  • super:代表當前對象父類的引用
  • this和super的使用區別
    • a:調用成員變量
      • this.成員變量 調用本類的成員變量,也可以調用父類的成員變量
      • super.成員變量 調用父類的成員變量
    • b:調用構造方法
      • this(...) 調用本類的構造方法
      • super(...) 調用父類的構造方法
    • c:調用成員方法
      • this.成員方法 調用本類的成員方法,也可以調用父類的方法
      • super.成員方法 調用父類的成員方法
class Demo4_Extends {
	public static void main(String[] args) {
		Son s = new Son();
		s.print();
	}
}

class Father {
	int num1 = 10;
	int num2 = 30;
}

class Son extends Father {
	int num2 = 20;

	public void print() {
		System.out.println(this.num1);				//this既可以調用本類的,也可以調用父類的(本類沒有的情況下)
		System.out.println(this.num2);				//就近原則,子類有就不用父類的了
		System.out.println(super.num2);
	}
}

運行結果

繼承中構造方法的關系

  • 子類中所有的構造方法默認都會訪問父類中空參數的構造方法
    • 因為子類會繼承父類中的數據,可能還會使用父類的數據。

    • 所以,子類初始化之前,一定要先完成父類數據的初始化。

    • 其實:

      • 每一個構造方法的第一條語句默認都是:super() Object類最頂層的父類。
class Demo5_Extends {
	public static void main(String[] args) {
		Son s = new Son();
	}
}

class Father extends Object {
	public Father() {
		super();
		System.out.println("Father 的構造方法");
	}
}

class Son extends Father {
	public Son() {
		super();				//這是一條語句,如果不寫,系統會默認加上,用來訪問父類中的空參構造
		System.out.println("Son 的構造方法");
	}
}

繼承中構造方法的注意事項

class Demo6_Extends {
	public static void main(String[] args) {
		Son s1 = new Son();
		System.out.println("--------------------");
		Son s2 = new Son("張三",23);
	}
}

class Father {
	private String name;			//姓名
	private int age;				//年齡

	public Father() {				//空參構造
		System.out.println("Father 空參構造");
	}

	public Father(String name,int age) {	//有參構造
		this.name = name;
		this.age = age;
		System.out.println("Father 有參構造");
	}

	public void setName(String name) {	//設置姓名
		this.name = name;
	}

	public String getName() {			//獲取姓名
		return name;
	}

	public void setAge(int age) {		//設置年齡
		this.age = age;
	}

	public int getAge() {				//獲取年齡
		return age;
	}
}

class Son extends Father {
	public Son() {						//空參構造	
		System.out.println("Son 空參構造");
	}

	public Son(String name,int age) {	//有參構造
		System.out.println("Son 有參構造");
	}
}

運行結果

System.out.println上一行隱藏了Super();

/*
	* 父類沒有無參構造方法,子類怎么辦?
	* super解決
	* this解決
* 注意事項
	* super(…)或者this(….)必須出現在構造方法的第一條語句上
*/
class Demo6_Extends {
	public static void main(String[] args) {
		Son s1 = new Son();
		System.out.println(s1.getName() + "..." + s1.getAge());
		System.out.println("--------------------");
		Son s2 = new Son("張三",23);
		System.out.println(s2.getName() + "..." + s2.getAge());
	}
}

class Father {
	private String name;			//姓名
	private int age;				//年齡

	public Father() {				//空參構造
		System.out.println("Father 空參構造");
	}

	public Father(String name,int age) {	//有參構造
		this.name = name;
		this.age = age;
		System.out.println("Father 有參構造");
	}

	public void setName(String name) {	//設置姓名
		this.name = name;
	}

	public String getName() {			//獲取姓名
		return name;
	}

	public void setAge(int age) {		//設置年齡
		this.age = age;
	}

	public int getAge() {				//獲取年齡
		return age;
	}
}

class Son extends Father {
	public Son() {						//空參構造
		this("王五",25);				//本類中的構造方法
		//super("李四",24);				//調用父類中的構造方法
		
		System.out.println("Son 空參構造");
	}

	public Son(String name,int age) {	//有參構造
		super(name,age);
		System.out.println("Son 有參構造");
	}
}

this和super只能存在一個
運行結果

看程序寫結果1

		class Fu{
			public int num = 10;
			public Fu(){
				System.out.println("fu");
			}
		}
		class Zi extends Fu{
			public int num = 20;
			public Zi(){
				System.out.println("zi");
			}
			public void show(){
				int num = 30;
				System.out.println(num);
				System.out.println(this.num);
				System.out.println(super.num);
			}
		}
		class Test1_Extends {
			public static void main(String[] args) {
				Zi z = new Zi();
				z.show();
			}
		}

結果為 fu zi 30 20 10
不要忘了public Zi() { 隱藏的Super()

看程序寫結果2

class Fu {
			static {
				System.out.println("靜態代碼塊Fu");
			}
	
			{
				System.out.println("構造代碼塊Fu");
			}
	
			public Fu() {
				System.out.println("構造方法Fu");
			}
		}
	
		class Zi extends Fu {
			static {
				System.out.println("靜態代碼塊Zi");
			}
	
			{
				System.out.println("構造代碼塊Zi");
			}
	
			public Zi() {
				System.out.println("構造方法Zi");
			}
		}
	

class Test2_Extends {
	public static void main(String[] args) {
		Zi z = new Zi();
	}
}

結果為
靜態代碼塊Fu
靜態代碼塊Zi
構造代碼塊Fu
構造方法Fu
構造代碼塊Zi
構造方法Zi

1.jvm調用了main方法,main先進棧
2.遇到Zi z = new Zi();會先將Fu.class和Zi.class分別加載進內存,再創建對象,當Fu.class加載進內存父類的靜態代碼塊會隨着Fu.class一起加載,當Zi.class加載進內存子類的靜態代碼塊會隨着Zi.class一起加載,
3.走Zi類的構造方法,因為java中是分層初始化的,先初始化父類,再初始化子類,所以先走的父類構造,但是在執行父類構造時,發現父類有構造代碼塊,構造代碼塊是優先於構造方法執行的
4.Fu類初始化結束,子類初始化

繼承中成員方法關系

class Demo7_Extends {
	public static void main(String[] args) {
		Son s = new Son();
		s.print();
		s.method();
	}
}
/*
* a:不同名的方法
* b:同名的方法
*/

class Father {
	public void print() {
		System.out.println("Fu print");
	}
}

class Son extends Father {
	public void method() {
		System.out.println("Zi Method");
	}

	public void print() {
		super.print();							//super可以調用父類的同名成員方法
		System.out.println("Zi print");
	}
}

運行結果為
Fu print
Zi print
Zi Method

方法重寫概述及其應用

  • 重寫:子父類出現了一模一樣的方法
  • 方法重寫的應用:
    • 當子類需要父類的功能,而功能主體子類有自己特有內容時,可以重寫父類中的方法。這樣,即沿襲了父類的功能,又定義了子類特有的內容。

定義一個手機類

class Demo7_Phone {
	public static void main(String[] args) {
		Ios8 i = new Ios8();
		i.siri();
		i.call();
	}
}

/*
	ios7系統 siri speak English
	ios8系統 siri 說中文
*/

class Ios7 {
	public void call() {
		System.out.println("打電話");
	}

	public void siri() {
		System.out.println("speak English");
	}
}

class Ios8 extends Ios7 {
	public void siri() {
		
		System.out.println("說中文");
		super.siri(); //保留原來的,不需要的話注釋掉即可
	}
}
  • 方法重寫注意事項
    • a:父類中私有方法不能被重寫

      • 因為父類私有方法子類根本就無法繼承
    • b:子類重寫父類方法時,訪問權限不能更低

      • 最好就一致
    • c:父類靜態方法,子類也必須通過靜態方法進行重寫

      • 其實這個算不上方法重寫,但是現象確實如此,至於為什么算不上方法重寫,多態中我會講解(靜態只能覆蓋靜態)
    • 子類重寫父類方法的時候,最好聲明一模一樣。

使用繼承后的學生和老師案例

class Test4_Person {
	public static void main(String[] args) {
		Student s1 = new Student();
		s1.setName("張三");
		s1.setAge(23);
		System.out.println(s1.getName() + "..." + s1.getAge());
		s1.eat();
		s1.study();

		System.out.println("------------------");
		Student s2 = new Student("李四",24);
		System.out.println(s2.getName() + "..." + s2.getAge());
		s2.eat();
		s2.study();
	}
}
/*
* 使用繼承后的學生和老師案例
*/

class Person {
	private String name;					//姓名
	private int age;						//年齡

	public Person() {}						//空參構造

	public Person(String name,int age) {	//有參構造
		this.name = name;
		this.age = age;
	}

	public void setName(String name) {		//設置姓名
		this.name = name;
	}

	public String getName() {				//獲取姓名
		return name;
	}

	public void setAge(int age) {			//設置年齡
		this.age = age;
	}

	public int getAge() {					//獲取年齡
		return age;
	}

	public void eat() {						//吃飯
		System.out.println(name  + "吃飯");
	}
}

class Student extends Person {
	public Student() {}						//空參構造

	public Student(String name,int age) {
		super(name,age);
	}

	public void study() {
		System.out.println(this.getName() + "學習");
		//直接getName()或super.getName()也行
	}
}

class Teacher extends Person {
	public Teacher() {}						//空參構造

	public Teacher(String name,int age) {
		super(name,age);
	}

	public void teach() {
		System.out.println(this.getName() + "講課");
		//直接getName()或super.getName()也行
	}
}

貓狗案例分析,實現及測試

class Demo5_Animal {
	public static void main(String[] args) {
		Cat c1 = new Cat("白",4);
		System.out.println(c1.getColor()+"  "+c1.getLeg());
		c1.eat();
		c1.catchMouse();

		Dog d1 = new Dog("黑",4);
		System.out.println(d1.getColor()+"  "+d1.getLeg());
		d1.eat();
		d1.lookHouse();
	}
}
/*
	* 貓狗案例繼承版
	* 屬性:毛的顏色,腿的個數
	* 行為:吃飯
	* 貓特有行為:抓老鼠catchMouse
	* 狗特有行為:看家lookHome
*/

class Animal {
	private String color;
	private int leg;

	public Animal(){
	}

	public Animal(String color,int leg){
		this.color = color;
		this.leg = leg;
	}

	public void setColor(String color){
		this.color = color;
	}

	public void setLeg(int leg){
		this.leg = leg;
	}

	public String getColor(){
		return color;
	}

	public int getLeg(){
		return leg;
	}

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

class Cat extends Animal{
	public Cat(){
	}

	public Cat(String color,int leg){
		super(color,leg);
	}

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

	public void catchMouse(){
		System.out.println("抓老鼠");
	}
}

class Dog extends Animal{
	public Dog(){
	}

	public Dog(String color,int leg){
		super(color,leg);
	}

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

	public void lookHouse(){
		System.out.println("看家");
	}
}

final關鍵字

  • final修飾特點
    • 修飾類,類不能被繼承
      final class Father {class Son extends Father {
      會報錯: 無法從最終Father進行繼承

    • 修飾變量,變量就變成了常量,只能被賦值一次
      final int NUM = 10;NUM = 20
      會報錯: 無法為最終變量NUM分配值
      //常量命名規范,如果是一個單詞,所有字母大寫,如果是多個單詞,每個單詞都大寫,中間用下划線隔開如MAX_VALUE

    • 修飾方法,方法不能被重寫

class Demo2_Final {
	public static void main(String[] args) {
		final int num = 10;
		//num = 20; //基本類型,是值不能被改變
		System.out.println(num);

		final Person p = new Person("張三",23);
		//p = new Person("李四",24);// 引用類型,是地址值不能被改變
		p.setName("李四");//對象中的屬性可以改變
		p.setAge(24);

		System.out.println(p.getName() + "..." + p.getAge());

	}
}

class Person {
	private String name;			//姓名
	private int age;				//年齡

	public Person()

	public Person(String name,int age) 

	public void setName(String name) 

	public String getName()

	public void setAge(int age) 

	public int getAge() 
}

final修飾變量的初始化時機

  • 顯示初始化
  • 在對象構造完畢前即可

兩種只能選擇一種

class Demo3_Final {
	public static void main(String[] args) {
		Demo d = new Demo();
		d.print();
	}
}


class Demo {
	//final int num = 10;	//顯示初始化			
	
	public Demo() {
		num = 10;//在對象構造完畢前
	}
	public void print() {
		System.out.println(num);
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM