繼承是從已有的類中派生出新的類,新的類能吸收已有類的屬性和行爲,並能擴充套件新的屬性和行爲。
1)Java是單繼承的,不支援多繼承。這樣使得Java的繼承關係很簡單,一個類只能有一個父類別,易於管理程式。同時一個類可以實現多個接 口,從而克服單繼承的缺點。
java 中只支援單繼承,並且是鏈式繼承(爹不能再繼承兒子)
2)繼承關係是傳遞的
3)private修飾的成員變數或方法是不能被繼承的
提高了程式碼的效率,避免了程式碼重寫
程式碼複用
語法格式
[修飾符] class 子類 extends 父類別{
//類體
}
public static void main(String[] args){
Cat c = new Cat();
Dog d = new Dog();
Bird b = new Bird();
eat(c);
//輸出結果爲 貓吃魚
eat(d);
//輸出結果爲 狗吃肉
eat(b);
//輸出結果爲 動物吃東西
}
//建立一個動物類 ,作爲父類別
class Animals{
public void eat(){
Systeam.out.println("動物吃東西");
}
}
//建立一個貓類繼承動物類,作爲子類
class Cat extends Animal{
public void eat() {
System.out.println("貓吃魚");
}
}
//建立一個狗類繼承動物類,作爲子類
class Dog extends Animal{
public void eat() {
System.out.println("狗吃肉");
}
}
//建立一個鳥類繼承動物類,作爲子類
class Bird extends Animal{
}
上面的程式碼中,cat,dog,bird都繼承了父類別動物類,
cat和dog類進行了覆寫 所以輸出的是子類的覆寫內容,這個後面會提到
bird類繼承了動物類,繼承了父類別的屬性,沒有進行重寫,所以輸出的是父類別輸出的內容
java中的根類 : Object
如果一個類沒有顯示繼承其他類,那麼該類預設繼承 java.lang.Object
儲存了父類別型特徵,可以理解爲是父類別的物件參照(錯的)
語法
super(參數);
必須在子類構造方法的第一行
如果 子類構造方法中 沒有出現 this(xxx) 和 super(xxx)的話 會預設有一個super() 去呼叫父類別的無參構造
this(xxx) 這種寫法必須出現在構造方法第一行,所以 this(xxx) 和 super(xxx) 不能同時出現
this和super都不能出現在靜態上下文中
用法
1 用在子類成員方法,可以區分子類和父類同名的成員變數/成員方法
2 用在子類構造方法,同上
3 用在子類構造 方法中,用於呼叫父類別構造方法
public class Super_01 {
Super_01(){
//不寫,預設會有super()呼叫父類別無參構造
super();
System.out.println("子類構造方法");
}
int i = 2;
public static void main(String[] args) {
Super_01 s = new Super_01();
s.m1();
}
public void m1() {
//子類
System.out.println("i");
//父類別
System.out.println("super.i");
//子類
System.out.println("this.i");
}
}
class A{
A(){
super();
System.out.println("父類別構造方法");
}
int i = 10;
}
如果構造方法私有化,就不能再有其他類繼承該類
因爲子類想要範例化物件,必須在構造方法中,呼叫父類別的構造方法
如果父類別構造方法私有化,那麼子類呼叫不到,報錯
public class Super_02 {
public Super_02() {
super();
}
}
class B{
//private B() {}
public B() {}
}
構造方法可以和靜態方法/成員方法重名嗎?
靜態方法/成員方法的方法名可以和類名相同嗎?
可以
如何區分?
看返回值,構造方法 沒有返回值,連void都沒有
public static void main(String[] args) {
new Super_03();
}
//成員方法
public void Super_03(){
System.out.println("1111111111法");
}
//構造方法
public Super_03(){
System.out.println("22222222222");
}
package _08_Super;
public class Super_04 {
public static void main(String[] args) {
new Sub();
}
}
class Sub extends Sup{
{
System.out.println("子類範例程式碼段1");
}
static {
System.out.println("子類靜態程式碼段1");
}
Sub(){
//super();
this(2);
//---------
System.out.println("子類構造方法");
}
Sub(int i){
super();
}
}
class Sup{
static {
System.out.println("父類別靜態程式碼段1");
}
{
System.out.println("父類別範例程式碼段1");
}
Sup(){
super();
//--------
System.out.println("父類別構造方法");
}
}
繼承之後 子類必須和父類別一模一樣嗎?
不需要
概念
1 子類有特有的屬性,比如 父類別只有m1 , 子類中 還有 m2 ,這個m2 就是子類特有,父類別沒有
2 子類和父類別擁有相同名字的方法,但是功能不一樣,叫覆寫/重寫/覆蓋
覆寫 特指成員方法,和其他屬性無關
什麼時候需要進行覆寫?
當父類別方法無法滿足子類的業務需求時,需要對父類別方法進行覆寫
前提條件
1 必須有繼承關係的體系中
2 不能比原方法有更低的存取許可權 >=
3 錯誤不能越來越多,不能有更寬泛的異常 <=
4 方法名,返回值,參數列表 都必須一致
方法名不一致,說明是倆方法
參數列表不一致,是方法過載
返回值表示方法的功能,必須一樣,不能更改方法的本質
繼承的目的
程式碼重用
繼承最重要的功能
方法覆寫
重寫的意義
功能越來越強
使用範圍越來越廣
錯誤越來越少
用之前繼承舉例的程式碼來解釋
public static void main(String[] args){
Cat c = new Cat();
Dog d = new Dog();
Bird b = new Bird();
eat(c);
//輸出結果爲 貓吃魚
eat(d);
//輸出結果爲 狗吃肉
eat(b);
//輸出結果爲 動物吃東西
}
//建立一個動物類 ,作爲父類別
class Animals{
public void eat(){
Systeam.out.println("動物吃東西");
}
}
//建立一個貓類繼承動物類,作爲子類
class Cat extends Animal{
//方法覆寫,重寫了父類別的eat()方法,輸出爲子類覆寫內容
public void eat() {
System.out.println("貓吃魚");
}
}
//建立一個狗類繼承動物類,作爲子類
class Dog extends Animal{
//方法覆寫,重寫了父類別的eat()方法,輸出爲子類覆寫內容
public void eat() {
System.out.println("狗吃肉");
}
}
//建立一個鳥類繼承動物類,作爲子類
class Bird extends Animal{
//未進行方法的覆寫,所以繼承父類別的屬性,輸出父類別的內容
}
被Final修飾的
類 : 不能被繼承
成員方法 : 不能被覆寫
修飾的變數 : 不能二次賦值,並且沒有預設值,在整個程式的生命週期中,值不能被改變
常數
整個程式生命週期中,值不會被更改 / 使用final修飾的變數就是常數, 字面量也是常數
分類
靜態常數:(final修飾的靜態變數,一般是public static final ,由於是公共的,和物件沒有關係,所以應用較多)
所以 一般我們把 final修飾的靜態變數 叫常數
成員常數
區域性常數
命名規則 建議 全大寫,在eclipse中 使用 藍色、斜體 、 加粗 顯示
public class Final_01 {
public static final int C = 2;
final int i =2;
final int a;
//final修飾的變數沒有預設值,必須顯示賦值
Final_01(int i){
a = i;
}
public static void main(String[] args) {
Final_01 f = new Final_01(2);
//final修飾的變數不能被更改
//f.i = 3;
System.out.println(123);
}
}
//final class A{
class A{
//修飾的成員方法不能被覆寫
// public final void m1() {
//}
}
class B extends A{
//class B{
public void m1() {}
}