Android工作室開發學習筆記——3
今天繼續深入Java知識,鞏固這門面向物件的語言。
1、this 與super
this 指代當前物件,主要應用場合:
在一些容易混淆的場合,如成員方法的引數名與資料成員同名;
成員方法的區域性變數名與資料成員同名。
Public class test{
int i;
Public othermethod(){
int i=3;
this.i=i+2;
}
}
this(引數)——引用過載的構造方法
this指代當前物件。
super本文指代父類中的域變數或方法,super訪問當前類的直接父類,主要應用場合:
子類的資料成員或成員方法與父類的資料成員或成員方法名字相同時,當要呼叫父類的同名方法或同名數據成員時則可用super來指明。即super.資料成員;super.成員方法
super(引數)//呼叫父類建構函式
2、構造方法的多型與繼承
構造方法的多型
構造方法的多型指構造方法可以被過載和被子類覆蓋。
一個類的若干個過載的構造方法之間可以相互呼叫。當一個構造方法需要呼叫另一個構造方法時,可以使用關鍵字 this,同時這個呼叫語句應該是整個構造方法的第一個可執行語句。構造方法的呼叫不能直接使用其名稱,必須使用this進行相互呼叫,而且必須為構造方法中的第一句
使用關鍵字this來呼叫同類的其它構造方法,優點同樣是 以最大限度地提高對已有程式碼的利用程度,減少程式的維護 工作量。
class AddClass { public int x=0,y=0,z=0; AddClass() { this.x=1; } AddClass (int x) { this.x=x; } AddClass (int x,int y) { this(x); this.y=y; } //呼叫第一個構造方法 AddClass (int x,int y,int z) { this(x,y); this.z=z; } //呼叫第二個構造方法 public int add() {return x+y+z; } } public class RunAddClass { public static void main(String[] args) { AddClass p1=new AddClass(2,3,5); AddClass p2=new AddClass(10,20); AddClass p3=new AddClass(1); AddClass p4=new AddClass(); System.out.println("x+y+z="+p1.add()); System.out.println("x+y="+p2.add()); System.out.println("x="+p3.add()); } }
結果:
x+y+z=10
x+y=30
x=1
構造方法的繼承
構造方法的繼承遵循以下的原則:
① 父類構造方法,子類可以在自己的構造方法中使用super來呼叫,但必須是子類構造方法的第一個可執行語句。
② 若子類構造方法中沒有顯式呼叫父類構造方法,也沒有用 this呼叫過載的其它構造方法,則在產生子類的物件時, 系統在呼叫子類構造方法的同時,預設呼叫父類無參構造方法。若子類構造方法中顯式呼叫了父類構造方法,或使 用了this,則不會預設呼叫父類無參構造方法。
綜上兩點:子類的構造方法必定呼叫父類的構造方法。如果不顯式用super方法,必然隱含呼叫super()。
例如:
class AddClasse
{
public int x=0,y=0,z=0;
AddClasse (int x)
{ this.x=x; }
AddClasse (int x,int y)
{ this(x); this.y=y; } //呼叫第一個構造方法
AddClasse (int x,int y,int z)
{ this(x,y); this.z=z; } //呼叫第二個構造方法
public int add()
{return x+y+z; }
}
public class SonAddClass extends AddClasse
{ int a=0,b=0,c=0;
SonAddClass (int x)
{ super(x); a=x+7; }
SonAddClass (int x,int y)
{ super(x,y); a=x+5; b=y+5; }
SonAddClass (int x,int y,int z)
{ super(x,y,z); a=x+4; b=y+4; c=z+4;}
public int add()
{System.out.println("super:x+y+z="+super.add());
return a+b+c;
}
public static void main(String[] args)
{ SonAddClass p1=new SonAddClass (2,3,5);
SonAddClass p2=new SonAddClass (10,20);
SonAddClass p3=new SonAddClass (1);
System.out.println("a+b+c="+p1.add());
System.out.println("a+b="+p2.add());
System.out.println("a="+p3.add());
}
}
結果:
super:x+y+z=10
a+b+c=22
super:x+y+z=30
a+b=40
super:x+y+z=1
a=8
class Pare
{int i;
Pare(){i=6;}
}
class Construct extends Pare
{ Construct(){}
Construct(int num){}
public static void main(String[] args){
Construct ct = new Construct(9);
System.out.println(ct.i);
}
}
6
3、抽象類
抽象類注意以下幾個方面:
① 抽象類中可以有零個或多個抽象方法,也可以包含非抽象方法。
② 只要有一個抽象方法,類前就必須有abstract修飾。若沒有抽象方法,類前也可有abstract修飾。
③ 抽象類不能建立物件,建立物件必須由具體子類來實現,但可以有宣告,宣告能引用所有具體子類的物件。
④ 對於抽象方法來說,在抽象類只指定其方法及其型別,而不書寫其實現程式碼。抽象類必定要派生子類,若派生的子類是具體類,則具體子類中必須實現抽象類中定義的所有抽象方法(覆蓋);若子類還是抽象類,父類中已有的abstract方法,則子類中就不能再有。
⑤ 在抽象類中,非抽象方法可以呼叫抽象方法。
⑥ abstract不能與final並列修飾同一個類;abstract 不能與private ,static,final或native並列修飾同一個方法;abstract 類中不能有private成員 。
4、介面
介面的兩種含義:
① 可以被引用呼叫的方法(public方法或同包中的protected方法或預設方法);
② 另一種是同“類”概念地位相當的專有概念interface, interface是功能方法說明的集合。
介面的特性:
① 介面定義,使用關鍵字 interface,而不是 Class,interface前的修飾符要麼是public,要麼是預設。
② 介面中定義的域變數全是final static ,即靜態常量。即使沒有任何修飾符,其效果完全等效。
③ 介面沒有構造方法,介面中所有方法自動屬於 abstract,即使沒有任何修飾符,其效果完全等效。
④ 介面中不能包含靜態方法,因為static 修飾的方法必然被直接呼叫,所以不能宣告為抽象方法。
⑤ 介面中只能定義靜態常量,不能含有例項域。
⑥ 不能在介面中實現方法。
⑦ 介面具有繼承性,可通過extends關鍵字宣告介面的父介面。
介面和子介面都不能有自己的例項物件,但可以有自己的宣告,可引用那些實現本介面或子介面的類物件。因此介面中的常量必須定義為static,以表明其沒有物件這一特點。
介面實現要注意幾點:
① 在類中,用implements關鍵字來實現介面。一個類可以實現多個介面,在implements後用逗號隔開多個介面的名字。一個介面也可被多個類來實現。
② 介面的實現者可以繼承介面中定義的常量,其效果等效於在這個實現類當中定義了一個靜態常量。
public interface Caculator
{ static final double PI=3.1415926;
static final double E=2.71828183 ;
double sum;//介面中的域自動設為static final
}
③ 如果實現某介面的類不是abstract的抽象類,則在類的定義部分必須實現介面的所有抽象方法,而且方法頭部分應該與介面中的定義完全一致。
④ 如果實現介面的類是abstract類,則它可以不實現該介面的所有方法。但對於抽象類的任何一個非抽象的子類而言,介面中的所有抽象方法都必須實現。這些方法體可以來自抽象的父類(被子類繼承),也可以來自子類自身的實現,這主要體現了非抽象類中不能存在抽象方法的原則。
⑤ 介面的抽象方法的訪問限制符如果為預設或public時,類在實現方法時,必須顯式使用public修飾符,否則將被警告為縮小了介面中定義的方法的訪問控制範圍。即所有實現interface中的方法必須被申明為public。
抽象類 | 介面 | ||
共同點 | 二者都可具有抽象方法,都不能例項化,但都可以有自己的宣告,並能引用子類或實現類物件。 | ||
不同點 | 屬性變數 | 可以有變數 | 不能有,只能是靜態常量。 |
成員方法 | 可以有具體方法(而且具體方法可以呼叫抽象方法)。 | 如果有方法,則全部是抽象方法。 | |
實現策略 | 必須有子類繼承 | 必須有實現類實現 | |
擴充套件性 | 弱 | 強 |
5、引用
抽象類宣告進行引用:
引用的形成:先宣告、後賦予物件、成為引用
抽象類宣告進行引用的特點:抽象類宣告可以引用所具體子類物件
父類宣告和子類宣告都引用同一個子類物件時的區別:父類宣告是從父類的角度去引用物件,而子類宣告是從子類角度去引用物件。父類宣告所引用的子類物件可以經過顯式的轉化賦值給予子類宣告。但子類宣告所引用的子類物件賦值給父類的宣告則不需要顯示的轉化。
介面宣告進行引用:
介面宣告進行引用的特點:只能引用實現類物件的介面方法。
如:
A a=new A(); //a引用A的物件
a=new A1();//a又引用A1的物件,放棄引用A物件
A1 a1=(A1) a ;//通過 a,a1也應用了A1物件,但是需要顯式轉化。
a=new A2(); //a放棄引用A1物件,而引用了A2物件
A aa=a1 ;//將A1物件通過a1賦值給父類宣告aa,此時aa也引用了A1物件。
非法:A1 a1=new A2(); A1 a1=new A();
6、內部類
區域性內部類:
定義在方法中的內部類稱為區域性類
定義形式:
void f(){
class Inner{…..}
}
與方法的區域性變數類似,區域性類不能用public或private修飾
區域性類的作用域被限定在宣告這個區域性類的塊中
區域性類可以對外部世界完全隱藏,除了f()方法外,其他程式碼方法都不能訪問區域性類
區域性類可以訪問外部類的所有屬性和方法,包括private屬性
區域性類只能引用方法體內的常量,不能訪問方法體內的區域性變數
成員內部類
定義在外部類的中,作為外部類的一個成員存在,與外部類的屬性、方法並列
定義形式:
class Outer{
class Inner{….}
}
成員類可以引用外部類的所有成員,包括被private修飾的
class Outer{
private int a=10;
void f(){…}
class Inner{int d;
public Inner(){ d=a; f();}
}
}
外部類與成員類定義的成員重名時,利用關鍵字this引用成員
class Outer{
int a;
class Inner{
int a=20;
void f(){
int a=10;
System.out.println(a);
System.out.println(this.a);
System.out.println(Outer.this.a); }
}
}
結果:
10
20
0
成員類的不能被static修飾,但允許靜態常量存在成員
class Outer{
class Inner{
int a; //可以
void f(){…} //可以
static final int b=10; //可以
static int c; //錯誤
static void g(){….} //錯誤
}
}
只有建立了外部類物件之後,才能建立內部類物件,才能使用內部類的成員
Outer out=new Outer();
Outer.Inner in=out.new Inner();
匿名內部類
沒有取名的內部類就是匿名類
定義形式:
new 類A() {
方法體
}
此時產生的物件是類A的子類物件
new 介面A() {
方法體
}
此時產生的物件是介面A的實現類的物件
匿名內部類的使用原則:
匿名內部類不能定義構造方法
不能定義任何靜態成員、方法
不能被public、protected、private、static修飾
只能建立一個例項物件
只用到類的一個例項
類在定義後馬上用到
類非常小
靜態內部類
被static修飾的成員類,稱為靜態內部類
定義形式:
class Outer{
static class Inner{
}
}
靜態類只能引用外部類的static成員,不能引用普通成員
class Outer{
static int a=10;
void f(){…}
static class Inner{
int d=a;//static變數
void g(){f(); //不能引用普通方法}
}
}
靜態類作為外部類的靜態成員,可以在不建立外部類物件的條件下,直接建立Inner類物件
Outer.Inner in=new Outer.Inner();