第五章
1.構造器是什麼?
構造函數(構造器)是一種特殊的函數。其主要功能是用來在創建對象時初始化對象, 即爲對象成員變量賦初始值,總與new運算符一起使用在創建對象的語句中。構造函數與類名相同,沒有返回值,但不能聲明void,訪問權限可以爲任意,但是一般情況下使用public方法權限,構造方法中的參數可以根據需要自行定義,可重載多個不同的構造函數。在JAVA語言中,構造函數與C++語言中的構造函數相同,JAVA語言中普遍稱之爲構造方法。
2.重載和重寫有什麼區別?
重載(overloading):在同一個類中同名函數,具有不同參數個數和類型(返回值不參與),是一個類中多態性的體現。是由靜態類型確定,在類加載的時候就已經確定了,屬於靜態綁定。(當子類和父類存在同一個方法時,子類重寫父類方法時,程序在運行時調用的方法時,是調用父類(接口)的方法呢?還是調用子類的方法呢?我們將確定這種調用何種方法的操作稱之爲綁定。)
重寫(overriding):子類中含有與父類中相同的名字、返回值類型和參數表的方法,則是重寫。是在繼承中體現多態性,屬於動態綁定。
方法的重載和重寫都是實現多態的方式,區別在於前者實現的是編譯時的多態,後者實現的是運行時的多態。
3.this 和super關鍵字
this:
this 是自身的一個對象,代表對象本身,可以理解爲:指向對象本身的一個指針。
this 的用法在 Java 中大體可以分爲3種:
1.普通的直接引用
這種就不用講了,this 相當於是指向當前對象本身。
2.形參與成員名字重名,用 this 來區分:
class Person {
private int age = 10;
public Person(){
System.out.println("初始化年齡:"+age);
}
public int GetAge(int age){
this.age = age;
return this.age;
}
}
public class test1 {
public static void main(String[] args) {
Person Harry = new Person();
System.out.println("Harry's age is "+Harry.GetAge(12));
}
}
可以看到,這裏 age 是 GetAge 成員方法的形參,this.age 是 Person 類的成員變量。
super
super 可以理解爲是指向自己超(父)類對象的一個指針,而這個超類指的是離自己最近的一個父類。
super 也有三種用法:
1.普通的直接引用
與 this 類似,super 相當於是指向當前對象的父類,這樣就可以用 super.xxx 來引用父類的成員。
2.子類中的成員變量或方法與父類中的成員變量或方法同名
class Country {
String name;
void value() {
name = "China";
}
}
class City extends Country {
String name;
void value() {
name = "Shanghai";
super.value(); //調用父類的方法
System.out.println(name);
System.out.println(super.name);
}
public static void main(String[] args) {
City c=new City();
c.value();
}
}
可以看到,這裏既調用了父類的方法,也調用了父類的變量。若不調用父類方法 value(),只調用父類變量 name 的話,則父類 name 值爲默認值 null。
3.引用構造函數
- super(參數):調用父類中的某一個構造函數(應該爲構造函數中的第一條語句)。
- this(參數):調用本類中另一種形式的構造函數(應該爲構造函數中的第一條語句)。
class Person {
public static void prt(String s) {
System.out.println(s);
}
Person() {
prt("父類·無參數構造方法: "+"A Person.");
}//構造方法(1)
Person(String name) {
prt("父類·含一個參數的構造方法: "+"A person's name is " + name);
}//構造方法(2)
}
public class Chinese extends Person {
Chinese() {
super(); // 調用父類構造方法(1)
prt("子類·調用父類"無參數構造方法": "+"A chinese coder.");
}
Chinese(String name) {
super(name);// 調用父類具有相同形參的構造方法(2)
prt("子類·調用父類"含一個參數的構造方法": "+"his name is " + name);
}
Chinese(String name, int age) {
this(name);// 調用具有相同形參的構造方法(3)
prt("子類:調用子類具有相同形參的構造方法:his age is " + age);
}
public static void main(String[] args) {
Chinese cn = new Chinese();
cn = new Chinese("codersai");
cn = new Chinese("codersai", 18);
}
}
從本例可以看到,可以用 super 和 this 分別調用父類的構造方法和本類中其他形式的構造方法。
例子中 Chinese 類第三種構造方法調用的是本類中第二種構造方法,而第二種構造方法是調用父類的,因此也要先調用父類的構造方法,再調用本類中第二種,最後是重寫第三種構造方法。
從本質上講,this 是一個指向本對象的指針, 然而 super 是一個 Java 關鍵字。
4.初始化順序
正常類的加載順序:靜態變量/靜態代碼塊 -> main方法 -> 非靜態變量/代碼塊 -> 構造方法
如果是繼承關係的子類初始化順序:
父類–靜態變量/父類–靜態初始化塊
子類–靜態變量/子類–靜態初始化塊
父類–變量/父類–初始化塊
父類–構造器
子類–變量/子類–初始化塊
子類–構造器
第六章
1.JAVA中的權限關鍵字
第七章
1.組合和繼承的區別,如何選擇使用?
組合:其實一開始就接觸了但不知道這就叫組合,本質就是類的複用。我們創建一個類A,之後再創建一個新的類B,在B類中通過創建A類對象,來調用A類方法。
下面通過具體的例子來展示如何使用:
public class People {
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
}
class Student {
People people = new People();
}
這裏的Student類就是運用了組合。
繼承:這個很熟悉了,直接貼用法
public class Student extends People{
//doSomething
}
總結一下:
組合:只需在新的類中產生現有類的對象。新的類是由現有類的對象所組成的。
繼承:按照現有類的類型來創建新類,無需改變現有類的形式,並且在其中添加新的代碼。
區別:組合是顯示地允許在新類中放置子對象,而繼承是隱性的這樣做。
選擇使用問題:
從語言的邏輯上看,繼承(extend)更應該用於包含關係(sth is a sth_baby),而組合可以是並列或者說共有的關係(sth has a sth_baby)。
2.final關鍵字總結
final關鍵字可以修飾變量、方法和類。
1.用來修飾數據:包括成員變量和局部變量,該變量只能被賦值一次且它的值無法被改變。對於成員變量來講,修飾的類變量,必須在聲明時初始化;修飾的實例變量,必須在聲明時或者構造方法中對它賦值。對於基本數據類型,final會使得數值不變;而對於引用類型,final會使得引用指向的對象不變。
2.用來修飾方法:第一個原因表示該方法無法被重寫,防止繼承的子類去修改該方法;第二個原因是效率。
tips:類中所有private方法都隱式地使用了final關鍵字。
3修飾類:表示該類無法被繼承
第八章
1.爲什麼要有多態的存在?
個人簡單的理解:父類型的引用指向子類型的對象。使用多態有兩個好處:
1. 應用程序不必爲每一個派生類編寫功能調用,只需要對抽象基類進行處理即可。大大提高程序的可複用性。
2. 派生類的功能可以被基類的方法或引用變量所調用,這叫向後兼容,可以提高可擴充性和可維護性。
多態可以用在方法的參數中和方法的返回類型中。
舉個例子:
package stduy;
abstract class Animal{
abstract void eat();
}
class Dog extends Animal{
public void eat() {
System.out.println("啃骨頭!");
}
public void LookHome() {
System.out.println("看家!");
}
}
class Cat extends Animal{
public void eat() {
System.out.println("吃魚!");
}
public void catchMouse() {
System.out.println("抓老鼠!");
}
}
public class Main{
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.LookHome();
Cat cat = new Cat();
cat.eat();
cat.catchMouse();
}
}
這裏主方法分別去調用各個子類的eat方法就很麻煩,我們這裏就可以使用多態。
public class Main{
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
method(dog);
method(cat);
}
public static void method(Animal a) {
a.eat();
}
}
2.向上轉型和向下轉型是什麼,爲什麼要用它們?
向上轉型和向下轉型都非常抽象,需要舉例說明:
class Father {
String name = "爸爸";
public void sleep() {//睡覺方法
System.out.println(name + "睡覺");
}
}
/**
* 子類繼承父類
*/
class Son extends Father {
String name = "兒子";
public void p() {//調皮方法
System.out.println(name + "調皮");
}
我們先建立一堆父子類。
public class UpAndDown {
public static void main(String[] args) {
// 向上轉型:將父類引用指向子類對象
Father f = new Son();
f.sleep();//輸出“爸爸睡覺”
//如果f.p();編譯出錯,不可執行。因爲p()不是Father的方法。
}
}
很明顯,上面的就是向上轉型,將子類轉型成父類,此時子類特有的p()方法就無法調用,但這樣做,方便我統一控制多個子類。
public class UpAndDown {
public static void main(String[] args) {
// 向下轉型
Father f = new Son();
((Son)f).P();//輸出“兒子調皮”
}
}
上面就是向下轉型,將向上轉型的子類再向下轉型,這樣原本子類特有的方法p()就可以使用了。
public class UpAndDown {
public static void main(String[] args) {
// 直接向下轉型
Father f = new Father();
f.sleep();//輸出“爸爸睡覺”
((Son)f).P();//報錯!!!!!!!!!!
}
}
但如果我寫成以上的向下轉型就不行,因爲他在創建對象時創建的就是父類對象,根本就不包含子類特有的方法,無法下轉。所以下轉的前提是你本來就有,只不過由於向上轉型失去了,然後通過下轉再次恢復。
爲什麼要用它們
向上轉型:這個好理解java的繼承,多態. 利於程序擴展。這種設計方式,會讓你寫出更易維護,簡潔的代碼。
但向下轉型就有點難以理解了,爲什麼我要先上轉再下轉,多這一步呢,我子類引用指向新建的一個子類對象不就好了?
這篇博客寫的很詳細: