42.Inheritance 继承

Subclass and Superclass
超类包含子类
父类与子类 我们可以在父类的实例上调用继承的公共方法
public class Pillar extends Swordsman { 
}

其中Pillar是子类,Swordman是父类
Subclass Constructor and super()

在子分支中重新定义超类方法

43.Final Instance Variable

实例变量final abstract ● If the instance variable will never be changed after it is initialized, we can declare it to be final:
public class Pillar extends Swordsman { 
}
public class Pillar extends Swordsman { 
public Pillar(String name) { 
super(name); //继承了父类的变量
} 
public static void main(String[] args) { 
Pillar kyojuro = new Pillar("Kyojuro"); 
} 
}

abstract可以用来修饰类和方法,不能用来修饰属性和构造方法;使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要被子类重写。
final可以用来修饰类、方法和属性,不能修饰构造方法。使用final修饰的类不能被继承,使用final修饰的方法不能被重写,使用final修饰的变量的值不能被修改,所以就成了常量。
To define a constant, we use keywords static final
public class Swordsman { 
private int healthPoint; 
public static final int MAX_HP = 100; 
public Swordsman(String name) { 
this.name = name; 
alive = true; 
numDemonsKilled = 0; 
numSwordsman++; 
healthPoint = MAX_HP; 
} 
} 

定义常数
补:W13 lab内容 abstract的用法。
我们要设计一个银行系统,要求有三个类,是一个abstract类的子类。
/**
 * Bank.java
 */
public abstract class Bank {
    protected String bankName;
    protected String bankAddress;
    public abstract String getBankName();
    public String getBankAddress() {
        return bankAddress;
    }
    // Constructor with parameters
    public Bank(String bankName, String bankAddress) {
        this.bankName = bankName;
        this.bankAddress = bankAddress;
    }
}
//调整抽象类bank:在bank类中,添加getBankAddress()方法来检索银行地址。
/**
 * BankA.java
 */
public class BankA extends Bank {
    public BankA(String bankName, String bankAddress) {
        super(bankName, bankAddress);
    }
    @Override
    public String getBankName() {
        return bankName;
    }
}
//重构BankA类:BankA类现在扩展了Bank并实现了父类的抽象方法。字段bankName和bankAddress从父类继承。
/**
 * Main.java
 */
public class Main {
    public static void main(String[] args) {
        BankA A = new BankA("cvcxs", "safafgs");
        System.out.println(A.getBankName());
        System.out.println(A.getBankAddress());
    }
}
Output:
cvcxs
Safafgs
//将getBankName() getBankAddress()父子类的不同表达想提示abstract的等效地位。父类abstract,子类重构,不同子类也可以用不同的方法。

44.@Override Annotation

@Override 是一个 Java 注解(Annotation),它用于表示一个方法(包括构造方法和非静态、非私有的方法)重写(覆盖)了其父类或实现的接口中的方法。@Override注解是伪代码,用于表示被标注的方法是一个重写方法。
只能用于标记方法,并且它只在编译期生效,不会保留在class文件中。
使用@Override注解主要有两个好处:
1)帮助自己检查是否正确的重写父类方法

2)明显的提示看代码的人,这是重写的方法
public class Pillar extends Swordsman { 
public static void main(String[] args) { 
Swordsman kyojuro = new Pillar("Kyojuro", 10000, "Fire"); 
System.out.println(kyojuro); 
} 

public class Successor extends Swordsman { 
private String apprenticedTo; 
public Successor(String name, String apprenticedTo) { 
super(name); 
this.apprenticedTo = apprenticedTo; 
} 

@Override 
public String toString() { 
return "Successor " + getName() + " apprenticed to " + apprenticedTo + 
" has killed " + getNumDemonsKilled() + " demons"; 
} 
}

public class DemonSlayerCorps { 
public static void main(String[] args) { 
Swordsman[] swordsmanTroop = new Swordsman[3]; 
swordsmanTroop[0] = new Swordsman("Tanjiro"); 
swordsmanTroop[1] = new Pillar("Kyojuro", 10000, "Fire"); 
swordsmanTroop[2] = new Successor("Kanao", "Shinobu"); 
for (int i = 0; i < swordsmanTroop.length; i++) { 
System.out.println(swordsmanTroop[i]); 
} 
} 
}

46.E.G

以下是lab的代码,要求制作一个图书馆书籍分类代码的分为科幻与非科幻,具体细节不限,展现本节课的多态性和子父类。
package com.mycompany.lib;

class Book {
    protected String author;
    protected String title;
    protected int numOfBooks;
    @Override
    public String toString() {
        return "Title: " + title + "\n" +
               "Author: " + author + "\n" +
               "Number of books: " + numOfBooks;
    }
    public Book(String author, String title, int numOfBooks) {
        this.author = author;
        this.title = title;
        this.numOfBooks = numOfBooks;
    }

    public String getAuthor() {
        return author;
    }

    public String getTitle() {
        return title;
    }

    public int getNumOfBooks() {
        return numOfBooks;
    }

    public void setNumOfBooks(int numOfBooks) {
        this.numOfBooks = numOfBooks;
    }

    public void details() {
        System.out.println("Title: " + title);
        System.out.println("Author: " + author);
        System.out.println("Number of books: " + numOfBooks);
    }
}

// Fiction subclass
class Fiction extends Book {
    private final String genre;

    public Fiction(String author, String title, int numOfBooks, String genre) {
        super(author, title, numOfBooks);
        this.genre = genre;
    }

    public String getGenre() {
        return genre;
    }

    @Override
    public void details() {
        super.details();
        System.out.println("Genre: " + genre);
    }
     @Override
    public String toString() {
        return super.toString() + "\n" +
               "Genre: " + genre;
    }
}


// NonFiction subclass
class NonFiction extends Book {
    private final String topic;

    public NonFiction(String author, String title, int numOfBooks, String topic) {
        super(author, title, numOfBooks);
        this.topic = topic;
    }

    public String getTopic() {
        return topic;
    }

    @Override
    public void details() {
        super.details();
        System.out.println("Topic: " + topic);
    }
    @Override
    public String toString() {
        return super.toString() + "\n" +
               "Topic: " + topic;
    }
}

// Client class
public class Lib {
    public static void main(String[] args) {

           Book[] books = new Book[4];
        // Create instances of Fiction and NonFiction books
        books[0] = new Fiction("Author 1", "Fiction Book 1", 5, "Science Fiction");
        books[1] = new Fiction("Author 2", "Fiction Book 2", 3, "Science Fiction");
        books[2] = new NonFiction("Author 3", "Non-Fiction Book 1", 2, "History");
        books[3] = new NonFiction("Author 4", "Non-Fiction Book 2", 1, "Biology");
       for(int i = 0; i < books.length; i++){
       System.out.println(books[i]);
       }
        // Iterate through the array and display book details
        }
}

47.Sixth class Review

1.Encapsulation

在Java中,=操作符用于赋值,而==操作符用于比较
This用于引用实例变量,而不带This的参数则引用构造函数的局部参数。

2.Review: Overloading

● To overload a constructor (method):
○ keep the same name
○ change at least one:
■ number of parameters
■ type of parameters
■ order of parameters
● Try yourself: what if you change (only) the return type instead?
● Overloading increases readability of the code

3.Inheritance

Another OOP feature of Java is called inheritance or subclassing
● Pillar is the subclass or child class that inherits variables and methods from Swordsman, its superclass or parent class
○ enabling code reuse
● We will also overrides a method of Swordsman in Pillar
○ same signature (name + parameters)

4.Overriding

A Pillar only receives half of the damage point reducing their health point
@Override 
public double receiveDamage(double damagePoint) { 
damagePoint = 0.5 * damagePoint; 
return super.receiveDamage(damagePoint) ; 
} 

5.Polymorphism

Polymorphism ≈ many forms
Polymorphism in Java ≈ perform a single action ○ executed in different ways
Example
class Animal {
    public void sound() {
        System.out.println("动物发出声音");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("狗发出汪汪声");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("猫发出喵喵声");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog(); // 父类引用指向子类对象
        Animal animal2 = new Cat(); // 父类引用指向子类对象

        animal1.sound(); // 输出:狗发出汪汪声
        animal2.sound(); // 输出:猫发出喵喵声
    }
}
//这就是多态。

6.In-Class Quiz 9.7: Polymorphism

public static void main(String[] args) { 
Swordsman kyojuro = new Pillar("Kyojuro", 1000, "Fire"); 
System.out.println(kyojuro.receiveDamage(10)); 
}
95.0 since receiveDamage of Pillar is called
Swordsman类有一个receiveDamage方法,而Pillar类扩展了Swordsman并覆盖了receiveDamage方法,那么即使变量kyojuro被声明为Swordsman,在Pillar类中被覆盖的方法也会在运行时被调用。

7.In-Class Quiz 9.6: Overriding (The reason of 95)

@Override
public double receiveDamage(double damagePoint) { 
damagePoint = 0.5 * damagePoint; 
return ... ; 
}

48.Protected key word

被其修饰的类成员能被所有的类直接访问;
It can directly access inherited instance variable from 父类 in 子类 subclass.
1.父类的被protected修饰的类成员包内可见,并且对其子类可见。
2.父类与子类不在同一个包里,子类只可以访问从父类继承的protected成员,不能访问父类实例化的成员。
参考
在Java中有四个访问修改器,可见性按顺序增加:
private → default (no modifier) → protected → public pFGsiW9.png

49.dynamic type / static type

动态与静态
When the Java Virtual Machine calls an instance method, it locates the method of the implicit class based on the dynamic type
○ this form of dynamic polymorphism is called dynamic method selection
public class User {
 
 //静态属性,属于整个类,被整个类的所有对象共享!
 static int num = 10;
  
 //普通属性,属于某个对象,是对象私有的!
 private int age=20;
  
 //静态代码块,在类被加载时自动调用,且只会被调用一次。比普通代码块先执行!
 static {
  
 //无论创建几个User对象,本静态代码块都只会执行一次,num++变成11
 System.out.println("这是静态代码块,num="+(num++));
 } 
  
 //非静态代码块,在对象被创建时自动调用,每次创建对象时都会执行,比构造方法先执行!
 { 
 //每创建一个User对象,就会执行一次本代码块,num++变成12,age=20.
 System.out.println("这是非静态代码块,num="+(num++)+",age="+(age++));
 }
  
 //构造方法
 public User(){ 
 //每创建一个User对象,就会执行一次构造方法,num++变成13,age=21.
 System.out.println("这是无参构造方法,num="+(num++)+",age="+(age++));
 }
 
}
------------------------------------------------------------
public class UserTest {
 
	public static void main(String[] args) {
	 	//创建第一个User对象
		User user1=new User();
 
	 	//创建第2个User对象
		User user2=new User();
 
	 	//创建第3个User对象
		User user3=new User();
 
	}
}
------------------------------------------------------------
Output:
这是静态代码块,num=10
这是非静态代码块,num=11,age=20
这是无参构造方法,num=12,age=21
这是非静态代码块,num=13,age=20
这是无参构造方法,num=14,age=21
这是非静态代码块,num=15,age=20
这是无参构造方法,num=16,age=21

50.Exception

Exception 1:ArrayIndexOutOfBoundsException<

阵列索引超出边界异常 We have seen an exception getting thrown before! ○ an ArrayIndexOutOfBoundsException object is thrown during runtime ○ since we are trying to access an invalid array index when we run the program pFGyRDP.png因为myArray[0]-[4]没有5所以超出异常。

Exception 2:Runtime Error

运行时错误 When something unexpected happens while the program is running, JVM throws an exception object ○ instead of returning a special value, such as -1 when String method indexOf does not find the search value E.g.
Scanner sc = new Scanner(System.in); 
int n = Integer.parseInt(sc.nextLine()); Entering a zero
System.out.println(1/n);

Exception 3:Throwing exception object

We can throw an exception object in our function (static method) or method (instance method) whenever something unexpected happens 例如,创建整数除法函数,只要除数为零时,它就会抛出一个算术异常对象。
try和catch是用于处理异常的语句,它们构成了一种异常处理机制。
Try捕获,catch处理。
try block后必须接catch block(try后必须接catch、finally或资源声明)
try block : put the risky method call here, and what to do next if execution turns out to be normal
将可能异常的部分放于try块里执行。
if an exception is thrown anywhere in try block, the program execution jumps to catch block.
Try块执行错误,跳转到catch block
代码示例如下:

public class Exception {
public static int myIntDiv(int a, int b) {
/*if (b == 0)
*throw new ArithmeticException("Cannot divide by zero!");
*else
*/
return a / b;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
try {
System.out.println(myIntDiv(1, n));
}
catch (ArithmeticException e) {
System.out.println("You entered a zero!");
}
/**catch (ArithmeticException e) { 
*System.out.println(e.getMessage()); 
*}
*如果想输出Cannot divide by zero!用此catch block 
注意throw和getMessage对应用法 throw new xx(“aa”) yy.getMessage()
*/
}
}
Input:
0
Output:
You entered a zero!
>>返回总目录<<