8、構造方法&匿名內部類&許可權
1、構造方法
概念及功能:用來建立例項物件的方法, 給物件的資料進行初始化 。Person p = new Person(); 呼叫構造方法 Person()只是我們沒有寫這個方法,而是Java自動補齊了這個方法,是方法就可以傳入引數。建立物件時,可以直接為成員變數賦值,無需再在物件產生後再賦值。
格式:一般定義在其他方法前,成員變數後。沒有返回值型別定義,方法名與類名相同,引數依據需求而定。
注意:構造方法是必須存在的,如果沒有手動給出構造方法 ,java會為我們自動補齊一個空參的構造方法。如果手動給出任意構造方法 java將不會為我們補齊空參構造。修飾符:public 代表公共的 ,任何包下都可以訪問。 預設什麼都不寫代表預設許可權,當前包下可以訪問。private代表私有,本類中可以訪問。空參構造是習慣上存在的,帶參的構造方法通常是為了給屬性賦值的。構造方法不能被繼承。介面沒有構造方法,抽象類具有構造方法。
繼承關係中的構造方法:在每次建立子類物件時,我們均會先建立父類物件,再建立其子類物件本身。目的在於子類物件中包含了其對應的父類物件,便可以包含其父類物件的成員,如果父類成員非private修飾,則子類可以隨意使用父類成員。反之,如果沒有先建立父類物件就使用了子類物件,則子類無法使用父類的成員。抽象類包含構造方法的原因就在於其僅僅是為了給成員變數賦值,供子類使用。這裡我們需要注意的是,記憶體當中實際是存在抽象類的物件空間的,我們無法直接建立抽象類物件,但是子類可以,在子類的記憶體空間中包括了這個抽象父類物件。
super關鍵字:super代表本類物件中包含的父類物件空間的引用。在子類的任意位置,均可以使用super.屬性名或者super.方法名()的方式訪問父類空間的非私有成員。在子類的每個構造方法中,第一行具有預設呼叫父類空參構造程式碼,即super().所以在每次建立子類物件時,會先建立父類的構造。使用super(引數)可以訪問父類任意引數的構造,當手動呼叫父類任意的構造方法後,Java將不再提供預設呼叫父類空參的構造方法。
this呼叫本類其他構造:使用this(引數)可以訪問子類任意其他引數的構造方法,當手動呼叫子類任意的構造方法後,Java將不再提供預設呼叫父類空參的構造方法。this呼叫構造方法與super呼叫構造方法不能同時出現。無論以哪種方式完成構造方法的定義,均會先建立父類物件,再建立子類物件。
public class Test {
public static void main(String[] args) {
Student a=new Student();
System.out.println(a.name);//人類
Student b=new Student("高手");
System. out.println(b.name);//高手
}
}
class Person{
public String name="人類";
}
class Student extends Person{
public String name;
public Student(){this.name=super.name;}
public Student(String s){//定義帶參構造一般都是為了給成員變數賦值
this();//呼叫本類無參空構造方法
this.name=s;//此局沒有則會把name賦值為父變數的name
}
}
變數訪問的就近原則:當多個位置出現相同名稱的變數時,訪問時會根據就近原則依次訪問。其先後順序為:區域性位置>本類成員位置>父類成員位置 >父類的父類成員位置 …
public class Test {
public static void main(String[] args) {
Student a=new Student();
a.findName();//現在區域性變數找name,沒有定義則在本類找,否則就在父類……本例列印高手
}
}
class Person{
public String name="人類";
}
class Student extends Person{
public String name="學生";
public void findName(){
public String name="高手";
System.out.println(name);}
}
2、關鍵字
final:些類在描述完之後,不想被繼承,或者有些類中的部分方法功能是固定的,不想讓子類重寫。要解決上述的這些問題,需要使用到一個關鍵字final,final的意思為最終,不可變。final是個修飾符,它可以用來修飾類,類的成員,以及區域性變數。
☆ 特點:final修飾類不可以被繼承,但是可以繼承其他類。final修飾的方法不可以被覆蓋,但父類中沒有被final修飾方法,子類覆蓋後可以加final。final修飾的變數稱為常量,這些變數只能賦值一次。引用型別的變數值為物件地址值,地址值不能更改,但是地址內的物件屬性值可以修改。修飾成員變數,需要在建立物件前賦值,否則報錯。(當沒有顯式賦值時,多個構造方法的均需要為其賦值。)
class Person{
final int n;//final修飾的成員變數,需要在建立物件前賦值,否則報錯。但可以在建立物件時所呼叫的構造方法中,為變數n賦值
public Person(){n=2;}
}
static:被static修飾的成員可以並且建議通過類名直接訪問。也可以通過某個物件訪問到屬於類的靜態成員,多個物件共享使用同一個靜態成員。
☆ 特點:static是靜態修飾符,一般修飾成員。被static修飾的成員屬於類,不屬於單個這個類的某個物件。static修飾的成員被多個物件共享。static修飾的成員屬於類,但是會影響每一個物件。被static修飾的成員又叫類成員,不叫物件的成員。靜態內容是優先於物件存在,只能訪問靜態,不能使用this/super。靜態修飾的內容存於靜態區。同一個類中,靜態成員只能訪問靜態成員。main方法為靜態方法僅僅為程式入口,不屬於任何一個物件,所以可以定義在任意類中。
☆ 通常使用public static final來修飾某個類中的靜態常量。此時識別符號用全部大寫,多個單詞使用下劃線連線。
public class Test {
public static void main(String[] args) {
Person a=new Person();
System.out.println(a.ADDRESS);//物件名.靜態成員------不建議,出現警告應該用Person.ADDRESS
a.method();
}
}
class Person {//靜態內容是優先於物件存在,只能訪問靜態,不能使用this/super。靜態修飾的內容存於靜態區。
static int age;//被static修飾的成員屬於類,不屬於單個這個類的某個物件。
public static final String ADDRESS ="中國";
public static void method(){
System.out.println(age);//不能使用this.age
//System.out.println(name);靜態只能訪問靜態 不能用已存在的去訪問還沒出現的,靜態內容優於物件存在
}
}
3、匿名物件與內部類
匿名物件 ☆概念:匿名物件是指建立物件時,只有建立物件的語句,卻沒有把物件地址值賦值給某個變數。建立一個普通物件:Person p = new Person();建立一個匿名物件:new Person();。
☆特點:建立匿名物件直接使用,沒有變數名。匿名物件在沒有指定其引用變數時,只能使用一次。匿名物件可以作為方法接收的引數、方法返回值使用(使用可以在任意位置)
內部類: ☆概念:將類寫在其他類的內部,可以寫在其他類的成員位置和區域性位置,這時寫在其他類內部的類就稱為內部類。其他類也稱為外部類。內部類分為成員內部類與區域性內部類。
成員內部類:
//定義格式
修飾符 class 外部類 {
修飾符 class 內部類 {//其他程式碼}
//其他程式碼}
*********************
//訪問方式
外部類名.內部類名 變數名 = new 外部類名().new 內部類名();
區域性內部類:
//定義格式
修飾符 class 外部類 {
修飾符 返回值型別 方法名(引數) {
修飾符 class 內部類 {//其他程式碼}}
}
//訪問方式
在外部類方法中,建立內部類物件,進行訪問
匿名內部類:
public class Test {
public static void main(String[] args) {
Person p = new Person(){//定義並建立該父類的子類物件,並用多型的方式賦值給父類引用變數
public void eat() {System.out.println(“我吃了”);}
};
p.eat();
}
//匿名內部類如果不定義變數引用,則也是匿名物件。
//new Person(){
//public void eat() {System.out.println(“我吃了”);}
//}.eat();
}
public abstract class Person{
public abstract void eat();
}
4、包
概念:java的包,其實就是我們電腦系統中的資料夾,包裡存放的是程式生成的.class檔案。當.class檔案很多的時候,通常我們會採用多個包進行存放管理他們,這種方式稱為分包管理,分包管理是組織軟體專案結構的基本方式。通常使用公司網址反寫,可以有多層包,包名採用全部小寫字母,多層包之間用”.”連線類中包的宣告格式。
訪問:在訪問類時,為了能夠找到該類,必須使用含有包名的類全名(包名.類名)。建立物件格式:包名.類名 變數名 = new包名.類名();當我們要使用一個類時,這個類與當前程式在同一個包中(即同一個資料夾中),或者這個類是java.lang包中的類時通常可以省略掉包名,直接使用該類。當我們要使用的類,與當前程式不在同一個包中(即不同資料夾中),要訪問的類必須用public修飾才可訪問。
導包:可以通過導包的方式使用該類,可以避免使用全類名編寫(即,包類.類名)。import導包程式碼書寫的位置:在宣告包package後,定義所有類class前,使用導包import包名.包名.類名;。
訪問許可權:
public | protected | default | private | |
---|---|---|---|---|
同一類中 | ✔ | ✔ | ✔ | ✔ |
同一包中 | ✔ | ✔ | ✔ | |
不同包的子類 | ✔ | ✔ | ||
不同包中的無關類 | ✔ |
要想僅能在本類中訪問使用private修飾;要想本包中的類都可以訪問不加修飾符即可;要想本包中的類與其他包中的子類可以訪問使用protected修飾;要想所有包中的所有類都可以訪問使用public修飾。如果類用public修飾,則類名必須與檔名相同。一個檔案中只能有一個public修飾的類。
class Person{
public void method1(){System.out.println("公共方法");}
protected void method2(){System.out.println("受保護的方法");}
void method3(){System.out.println("預設許可權方法");}
private void method4(){System.out.println("私有方法");}
public void method(){method1();method2();method3();method4();}
}
public class Test {//同一類中
public static void main(String[] args) {
Person p = new Person();
p.method();//列印四種方法
}
}
public class Test {//同一個包下子類或者無關類
public static void main(String[] args) {
Person p = new Person();
//p.method4();不會列印
}
}
public class Test {//不同包下的子類
public static void main(String[] args) {
Person p = new Person();
//p.method3();不會列印
//p.method4();不會列印
}
}
public class Test {//不同包下的無關類
public static void main(String[] args) {
Person p = new Person();
//p.method2();不會列印
//p.method3();不會列印
//p.method4();不會列印
}
}
程式碼塊:區域性程式碼塊:普通程式碼塊就是直接定義在方法或語句中,以”{}”劃定的程式碼區域,此時只需要關注作用域的不同即可,方法和類都是以程式碼塊的方式劃定邊界的。構造程式碼塊:又叫成員程式碼塊,直接定義在類中成員位置的程式碼塊,優先於構造方法執行,構造程式碼塊用於執行所有物件均需要的初始化動作,每建立一個物件均會執行一次構造程式碼塊。靜態程式碼塊:靜態程式碼塊是定義在成員位置,使用static修飾的程式碼塊,它優先於主方法執行、優先於構造程式碼塊執行,當以任意形式第一次使用到該類時執行。該類不管建立多少物件,靜態程式碼塊只執行一次。可用於給靜態變數賦值,用來給類進行初始化。