欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java類的繼承實(shí)例詳解(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)

 更新時(shí)間:2017年04月11日 17:08:38   投稿:mrr  
在Java開發(fā)中,我們常常用到繼承這一概念,可以說(shuō)繼承是Java這類面向?qū)ο缶幊陶Z(yǔ)言的基石,今天小編一起和大家一起學(xué)習(xí)java類的繼承

一.你了解類嗎?

  在Java中,類文件是以.java為后綴的代碼文件,在每個(gè)類文件中最多只允許出現(xiàn)一個(gè)public類,當(dāng)有public類的時(shí)候,類文件的名稱必須和public類的名稱相同,若不存在public,則類文件的名稱可以為任意的名稱(當(dāng)然以數(shù)字開頭的名稱是不允許的)。

  在類內(nèi)部,對(duì)于成員變量,如果在定義的時(shí)候沒(méi)有進(jìn)行顯示的賦值初始化,則Java會(huì)保證類的每個(gè)成員變量都得到恰當(dāng)?shù)某跏蓟?/p>

  1)對(duì)于  char、short、byte、int、long、float、double等基本數(shù)據(jù)類型的變量來(lái)說(shuō)會(huì)默認(rèn)初始化為0(boolean變量默認(rèn)會(huì)被初始化為false);

  2)對(duì)于引用類型的變量,會(huì)默認(rèn)初始化為null。

  如果沒(méi)有顯示地定義構(gòu)造器,則編譯器會(huì)自動(dòng)創(chuàng)建一個(gè)無(wú)參構(gòu)造器,但是要記住一點(diǎn),如果顯示地定義了構(gòu)造器,編譯器就不會(huì)自動(dòng)添加構(gòu)造器。注意,所有的構(gòu)造器默認(rèn)為static的。

  下面我們著重講解一下 初始化 順序:

  當(dāng)程序執(zhí)行時(shí),需要生成某個(gè)類的對(duì)象,Java執(zhí)行引擎會(huì)先檢查是否加載了這個(gè)類,如果沒(méi)有加載,則先執(zhí)行類的加載再生成對(duì)象,如果已經(jīng)加載,則直接生成對(duì)象。

  在類的加載過(guò)程中,類的static成員變量會(huì)被初始化,另外,如果類中有static語(yǔ)句塊,則會(huì)執(zhí)行static語(yǔ)句塊。static成員變量和static語(yǔ)句塊的執(zhí)行順序同代碼中的順序一致。記住,在Java中,類是按需加載,只有當(dāng)需要用到這個(gè)類的時(shí)候,才會(huì)加載這個(gè)類,并且只會(huì)加載一次??聪旅孢@個(gè)例子就明白了:

public class Test {
 public static void main(String[] args) throws ClassNotFoundException {
 Bread bread1 = new Bread();
 Bread bread2 = new Bread();
 }
}
class Bread {
 static{
 System.out.println("Bread is loaded");
 }
 public Bread() {
 System.out.println("bread");
 }
}

  運(yùn)行這段代碼就會(huì)發(fā)現(xiàn)"Bread is loaded"只會(huì)被打印一次。

  在生成對(duì)象的過(guò)程中,會(huì)先初始化對(duì)象的成員變量,然后再執(zhí)行構(gòu)造器。也就是說(shuō)類中的變量會(huì)在任何方法(包括構(gòu)造器)調(diào)用之前得到初始化,即使變量散步于方法定義之間。

public class Test {
 public static void main(String[] args) {
 new Meal();
 }
}
class Meal {
 public Meal() {
 System.out.println("meal");
 }
 Bread bread = new Bread();
}
class Bread {
 public Bread() {
 System.out.println("bread");
 }
}

  輸出結(jié)果為:

bread
meal

二.你了解繼承嗎?

  繼承是所有OOP語(yǔ)言不可缺少的部分,在java中使用extends關(guān)鍵字來(lái)表示繼承關(guān)系。當(dāng)創(chuàng)建一個(gè)類時(shí),總是在繼承,如果沒(méi)有明確指出要繼承的類,就總是隱式地從根類Object進(jìn)行繼承。比如下面這段代碼:

class Person {
 public Person() {
 }
}
class Man extends Person {
 public Man() {
 }
}

  類Man繼承于Person類,這樣一來(lái)的話,Person類稱為父類(基類),Man類稱為子類(導(dǎo)出類)。如果兩個(gè)類存在繼承關(guān)系,則子類會(huì)自動(dòng)繼承父類的方法和變量,在子類中可以調(diào)用父類的方法和變量。在java中,只允許單繼承,也就是說(shuō) 一個(gè)類最多只能顯示地繼承于一個(gè)父類。但是一個(gè)類卻可以被多個(gè)類繼承,也就是說(shuō)一個(gè)類可以擁有多個(gè)子類。

  1.子類繼承父類的成員變量

  當(dāng)子類繼承了某個(gè)類之后,便可以使用父類中的成員變量,但是并不是完全繼承父類的所有成員變量。具體的原則如下:

  1)能夠繼承父類的public和protected成員變量;不能夠繼承父類的private成員變量;

  2)對(duì)于父類的包訪問(wèn)權(quán)限成員變量,如果子類和父類在同一個(gè)包下,則子類能夠繼承;否則,子類不能夠繼承;

  3)對(duì)于子類可以繼承的父類成員變量,如果在子類中出現(xiàn)了同名稱的成員變量,則會(huì)發(fā)生隱藏現(xiàn)象,即子類的成員變量會(huì)屏蔽掉父類的同名成員變量。如果要在子類中訪問(wèn)父類中同名成員變量,需要使用super關(guān)鍵字來(lái)進(jìn)行引用。

  2.子類繼承父類的方法

  同樣地,子類也并不是完全繼承父類的所有方法。

  1)能夠繼承父類的public和protected成員方法;不能夠繼承父類的private成員方法;

  2)對(duì)于父類的包訪問(wèn)權(quán)限成員方法,如果子類和父類在同一個(gè)包下,則子類能夠繼承;否則,子類不能夠繼承;

  3)對(duì)于子類可以繼承的父類成員方法,如果在子類中出現(xiàn)了同名稱的成員方法,則稱為覆蓋,即子類的成員方法會(huì)覆蓋掉父類的同名成員方法。如果要在子類中訪問(wèn)父類中同名成員方法,需要使用super關(guān)鍵字來(lái)進(jìn)行引用。

  注意:隱藏和覆蓋是不同的。隱藏是針對(duì)成員變量和靜態(tài)方法的,而覆蓋是針對(duì)普通方法的。(后面會(huì)講到)

  3.構(gòu)造器

  子類是不能夠繼承父類的構(gòu)造器,但是要注意的是,如果父類的構(gòu)造器都是帶有參數(shù)的,則必須在子類的構(gòu)造器中顯示地通過(guò)super關(guān)鍵字調(diào)用父類的構(gòu)造器并配以適當(dāng)?shù)膮?shù)列表。如果父類有無(wú)參構(gòu)造器,則在子類的構(gòu)造器中用super關(guān)鍵字調(diào)用父類構(gòu)造器不是必須的,如果沒(méi)有使用super關(guān)鍵字,系統(tǒng)會(huì)自動(dòng)調(diào)用父類的無(wú)參構(gòu)造器??聪旅孢@個(gè)例子就清楚了:

class Shape {
 protected String name;
 public Shape(){
 name = "shape";
 }
 public Shape(String name) {
 this.name = name;
 }
}
class Circle extends Shape {
 private double radius;
 public Circle() {
 radius = 0;
 }
 public Circle(double radius) {
 this.radius = radius;
 }
 public Circle(double radius,String name) {
 this.radius = radius;
 this.name = name;
 }
}

  這樣的代碼是沒(méi)有問(wèn)題的,如果把父類的無(wú)參構(gòu)造器去掉,則下面的代碼必然會(huì)出錯(cuò):

改成下面這樣就行了: 

  4.super

  super主要有兩種用法:

  1)super.成員變量/super.成員方法;

  2)super(parameter1,parameter2....)

  第一種用法主要用來(lái)在子類中調(diào)用父類的同名成員變量或者方法;第二種主要用在子類的構(gòu)造器中顯示地調(diào)用父類的構(gòu)造器,要注意的是,如果是用在子類構(gòu)造器中,則必須是子類構(gòu)造器的第一個(gè)語(yǔ)句。

三.常見的面試筆試題

1.下面這段代碼的輸出結(jié)果是什么?

public class Test {
 public static void main(String[] args) {
 new Circle();
 }
}
class Draw {
 public Draw(String type) {
 System.out.println(type+" draw constructor");
 }
}
class Shape {
 private Draw draw = new Draw("shape");
 public Shape(){
 System.out.println("shape constructor");
 }
}
class Circle extends Shape {
 private Draw draw = new Draw("circle");
 public Circle() {
 System.out.println("circle constructor");
 }
}
shape draw constructor
shape constructor
circle draw constructor
circle constructor

  這道題目主要考察的是類繼承時(shí)構(gòu)造器的調(diào)用順序和初始化順序。要記住一點(diǎn):父類的構(gòu)造器調(diào)用以及初始化過(guò)程一定在子類的前面。由于Circle類的父類是Shape類,所以Shape類先進(jìn)行初始化,然后再執(zhí)行Shape類的構(gòu)造器。接著才是對(duì)子類Circle進(jìn)行初始化,最后執(zhí)行Circle的構(gòu)造器。

2.下面這段代碼的輸出結(jié)果是什么?

public class Test {
 public static void main(String[] args) {
 Shape shape = new Circle();
 System.out.println(shape.name);
 shape.printType();
 shape.printName();
 }
}
class Shape {
 public String name = "shape";
 public Shape(){
 System.out.println("shape constructor");
 }
 public void printType() {
 System.out.println("this is shape");
 }
 public static void printName() {
 System.out.println("shape");
 }
}
class Circle extends Shape {
 public String name = "circle";
 public Circle() {
 System.out.println("circle constructor");
 }
 public void printType() {
 System.out.println("this is circle");
 }
 public static void printName() {
 System.out.println("circle");
 }
}
shape constructor
circle constructor
shape
this is circle
shape

  這道題主要考察了隱藏和覆蓋的區(qū)別(當(dāng)然也和多態(tài)相關(guān),在后續(xù)博文中會(huì)繼續(xù)講到)。

  覆蓋只針對(duì)非靜態(tài)方法(終態(tài)方法不能被繼承,所以就存在覆蓋一說(shuō)了),而隱藏是針對(duì)成員變量和靜態(tài)方法的。這2者之間的區(qū)別是:覆蓋受RTTI(Runtime type  identification)約束的,而隱藏卻不受該約束。也就是說(shuō)只有覆蓋方法才會(huì)進(jìn)行動(dòng)態(tài)綁定,而隱藏是不會(huì)發(fā)生動(dòng)態(tài)綁定的。在Java中,除了static方法和final方法,其他所有的方法都是動(dòng)態(tài)綁定。因此,就會(huì)出現(xiàn)上面的輸出結(jié)果。

以上所述是小編給大家介紹的Java類的繼承實(shí)例詳解(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論