Java中構造方法以及各種關鍵字小結
1、構造方法
1)構造方法的語法
public class Deom{ private int a; public static void main(String[] args) { new Demo(); } //無參的構造方法 public Deom(){ System.out.println("無參的構造方法被呼叫!!"); } //帶參的構造方法 相當於構造方法過載 public Demo(int a){ this.a=a; System.out.println("帶參的構造方法被呼叫!!"); } }
2)每個類都隱式自帶一個無參的構造方法,當我們new一個例項時,JVM就會預設呼叫這個無參的構造方法。需要注意的是構造方法是可以被過載的,當我們顯式過載了一個構造方法時,自帶的隱式無參構造方法就會消失,所以,我們一般都顯式的將無參的構造方法寫出來。
3)構造方法如何被呼叫?
上面說到構造方法是在new例項時JVM自動呼叫,在普通方法中無法被呼叫,除了JVM呼叫之外,我們還可以在其他過載的構造方法中呼叫另一個構造方法,呼叫時不是使用方法名進行呼叫而是使用this關鍵字進行呼叫,this代表當前類的引用。
public class Deom{ private int a; public static void main(String[] args) { new Demo(); } //無參的構造方法 public Deom(){ this(6);//呼叫下面帶參的建構函式 System.out.println("無參的構造方法被呼叫!!"); } //帶參的構造方法 相當於構造方法過載 public Demo(int a){ this.a=a; System.out.println("帶參的構造方法被呼叫!!"); } }
上面程式碼可以看出,JVM在呼叫無參的構造方法後,無參的構造方法中又使用this呼叫了下面的帶參的構造方法,帶參的構造方法中將這個類的例項給初始化了。
4)關於構造方法的修飾符問題
如果一個類中的構造方法全部私有了(被private修飾),那在類的外部是不可以產生該類的例項的。
2、static 關鍵字
1)為什麼會有static關鍵字?
這個關鍵字可以修飾成員變數,成員方法,用這個關鍵字修飾之後的成員會儲存在JAVA記憶體中的靜態方法區中,也就是說所有new的物件都共享這塊記憶體(節省記憶體)。
注意: static 不能修飾區域性變數
2)static修飾成員變數
當一個類中的所有物件的某個屬性的值都一樣的話,那麼我們常常把這個屬性用static來修飾。
如果static修飾一個成員變數後,我們就需要在類中就給這個成員變數初始化,那以後在其他地方new這個類的例項的時候就不需要給這個變數初始化了。因為所有new的例項都會去靜態方法區中找到這個變數的值,這樣節省了記憶體(如果沒用static修改,那這個變數就不會出現在靜態方法區中,而是跟著new例項的時候放在棧記憶體中,每new一個例項堆記憶體中就會存一遍這個變數,浪費記憶體)。
3)static修飾成員方法
當一個成員方法中沒有使用到非靜態成員變數的話,就可以使用static來修飾這個方法。
注意: 靜態方法中不能使用非靜態的成員(靜態的先於非靜態載入,如果非靜態成員還沒初始化就尷尬了)
4)靜態成員變數與靜態成員方法的呼叫
a 跟非靜態的呼叫方法一樣
b 通過類名直接呼叫
package cn.com.kingc.eoms.controller;
public class Ceshi {
public int a;
public static String str;
public static void sleep(){
System.out.println("正在睡覺............");
}
}
class OtherClass{
public static void main(String[] args) {
//直接使用類名呼叫
Ceshi.sleep();
//普通方法呼叫
Ceshi ce=new Ceshi();
ce.sleep();
}
}
5)靜態成員變數與非靜態成員變數的區別?
a.儲存區域
靜態成員變數---》 靜態方法區
非靜態成員變數--》 堆記憶體
b. 生命週期
靜態成員變數--》類載入時開始初始化,類解除安裝時進行消毀。
非靜態成員變數--》在堆記憶體中為物件開闢空間時開始進行初始化,當沒有引用指向物件時,此時垃圾回收器會把非靜態成員變數的記憶體空間消毀。
c.呼叫方式
靜態成員變數-》可以通過類名,物件名來呼叫
非靜態成員變數-》只能通過物件名來呼叫
3、靜態程式碼塊
1)為什麼會有靜態程式碼塊
物件初始化(對物件中的非靜態成員進行初始化)使用的方法是構造方法,如果對類進行初始化(物件中的靜態成員的初始化)那麼該怎麼辦?這裡用到靜態程式碼塊
2)什麼叫對類進行初始化
類的初始化的意思是對類中的靜態成員進行附值。
物件的初始化的意思是對類中非靜態成員進行的附值。 new完產生物件後才能用構造方法對非靜態成員進行賦值
3)靜態程式碼塊的使用如下圖:直接在宣告靜態變數的時候初始化跟使用靜態程式碼塊初始化是一樣的
package cn.com.kingc.eoms.controller;
public class Ceshi {
public static int a;
public static String str;
static {
a=1;
str="哈哈";
}
}
class OtherClass{
public static void main(String[] args) {
//呼叫類中的靜態成員變數,檢視值
String str = Ceshi.str;
System.out.println(str);
}
}
4、final 關鍵字
1)final 修飾的類 不能被繼承
2)final 修飾的方法不能被覆寫(重寫),可以過載(引數個數、型別不同)
3)final 修飾的變數會變成常量,也就是說在宣告這個變數的時候就要將這個變數初始化,並且該值不能被修改
注意:一般來說用final修飾的變數,它的變數名字一般都要全部大寫
5、extends 繼承關鍵字
1)使用extends關鍵字來繼承一個父類
package cn.com.kingc.eoms.controller;
public class Person {
public String sex;
public String name;
public Person(){
System.out.println("呼叫父類建構函式!!!!!!!!!");
}
}
class Worker extends Person{
public Worker(){
super();//預設隱式呼叫父類的無參的建構函式,要放在第一句,super()本身可以傳參
System.out.println("呼叫子類建構函式!!!!");
}
}
class Ceshi{
public static void main(String[] args) {
Worker worker=new Worker();
}
}
2)父類與子類變數覆蓋問題
當父類中的變數與子類中的變數一樣時,會取子類中的變數值(包括靜態與非靜態)
3)當父類方法邏輯不滿足子類需求時,我們需要在子類中進行方法的複寫,被複寫的方法上要加@Override註解
6、abstract 抽象類關鍵字(說白了一個抽象類就是用來被繼承的,繼承之後我們要重寫裡面抽象方法)
1)語法格式
public abstract class Person{
//抽象類中的抽象方法用abstract 修飾
public abstract void run();
//抽象類中可以有具體方法
public void eat(){
System.out.println("正在吃飯...............");
}
}
2) 抽象類的注意事項:
宣告抽象類時,不需要許可權修飾符修飾(public 、private)
1)一個類中如果有抽象方法,那麼這個類必須是抽象類,抽象類中可以有具體方法和抽象方法。
2)一個類如果繼承了一個抽象類,那麼這個類必須實現抽象類中的抽象方法,如果不實現那麼這個類也必須是抽象類。
3)抽象類不可以產生物件。
4)抽象類中可以有構造方法。
5)抽象類不能new出物件
6)抽象方法不能使用 private、static、final修飾。因為抽象方法就是要被繼承重寫的
7)抽象類不能被 final修飾,因為抽象類就是要被繼承的
7、interface 介面關鍵字
1)當一個抽象類中的方法全是抽象方法時,我們就不能把這個類叫抽象類了,而應該叫介面
2)語法格式
//這個是介面的定義,注意定義的時候class關鍵字不需要寫
public interface Person{
//介面中的成員變數預設被public static final修飾,所以可以這樣定義變數
int NUM=78;
//顯式定義變數如下
public static final String SXE="男";
//抽象方法
public abstract void run();
//抽象方法
public void eat();
//在介面中抽象方法預設被 public adstract 關鍵字修飾,所以可以寫成如下格式
void sleep();
}
3)類和抽象類都可以被繼承,且子類只能單繼承。而介面是用來實現的,並且可以多實現,請看8
8、implements 實現介面的關鍵字
package cn.com.kingc.eoms.controller;
//介面1
public interface Person{
public abstract void run();
public void eat();
void sleep();
}
//介面2
interface Person1{
public void eat1();
}
//介面3可以多繼承其他介面
interface Person2 extends Person,Person1{
public abstract void run2();
}
//普通類可以多實現介面,並必須要實現介面中的所有方法
class Ceshi implements Person,Person1,Person2{
@Override
public void run() {
}
@Override
public void eat() {
}
@Override
public void sleep() {
}
@Override
public void eat1() {
}
@Override
public void run2() {
}
}