轉發請在文章中提供本文的鏈接,謝謝!
一、 數組
1.1 一維數組定義方式
*C++的數組既可以在堆上分配內存(用malloc方法或者new操作符),並由指針來承接,也可以在棧上提前分配(如int a[10] = {0};)。與C++不同,Java的數組都是在堆上分配內存空間,使用new操作符:
int[] arr1 = new int[10];
int[] arr2 = {11,22,33,44,55};
int[] arr3 = new int[]{1,2,3,4,5};
1.2 二維數組定義方式
*C中,在棧上開闢二維數組十分簡單快捷,而在堆上調用malloc方法來開闢二維數組時,其過程簡直是一場災難,我們不僅僅需要利用一個二級指針來指向所開闢的指針數組,接下來還需要用指針數組的每個成員來指向所開闢的一維數組,在此期間我們常常還需要考慮到一旦內存開闢到一半出現問題的應對策略……同理,調用free方法對這些內存進行釋放的過程也是比較繁瑣。而在Java中,雖然開闢二維數組的原理與C基本相同(先開闢指針數組,然後開闢多條一維數組),但其開闢的過程是輕鬆加愉快的:
int[][] arr1 = new int[5][6];
int[][] arr2 = new int[5][];//注意,這裏arr2和arr1的含義是完全不同的
arr2[0] = new int[3];
arr2[1] = new int[5];
int[][] arr3 = {{1,2,3},{4,5},{6,7,8,9}};
二、 面向對象
2.1 面向對象的三大特徵
*地球人都知道,封裝(encapsulation),繼承(inheritance), 多態(polymorphism)是面向對象的三大特徵。
*其中封裝爲我們帶來了封裝數據與方法的概念,Java的封裝方式與C++大同小異,常見區別主要在於構造方法的格式以及析構方法的有無;
*繼承則帶來了超類與子類的概念,與C++不同,Java並不支持多繼承,某種程度上作爲相應的補償,Java引入了接口interface。另外,Java中也並沒有C++那樣複雜的public、private、protected繼承之分;
*多態簡單說就是父類引用指向子類對象時,仍可根據其實際調用對象的不同,動態地決定調用哪個函數。在C++中,多態是通過virtual聲明虛函數實現的,這樣每個對象維護了一個虛函數指針及其指向的虛函數表。而在Java中,無需virtual聲明,所有成員方法都可以被重寫。
以上對Java中面向對象的特點做了一個簡單的綜述,後面我們會對這些特性進行詳細介紹。
2.2 對象中成員變量和方法中局部變量的區別
* ①在類中的位置不同
* 成員變量:在類中方法外
* 局部變量:在方法定義中或者方法聲明上
* ②在內存中的位置不同
* 成員變量:在堆內存(成員變量屬於對象,對象本來就是存儲在堆內存上的)
* 局部變量:在棧內存(局部變量屬於方法,方法執行時執行進棧和彈棧操作)
* ③生命週期不同
* 成員變量:隨着對象的創建而存在,隨着對象的消失而消失
* 局部變量:隨着方法的調用而存在,隨着方法的調用完畢而消失(注意,final修飾的變量不在此列中)
* ④初始化值不同
* 成員變量:有默認初始化值
* 局部變量:沒有默認初始化值,必須定義,賦值,然後才能使用(請在定義局部變量時賦一個確定值)
2.3 匿名對象
就是沒有名字的對象(即沒有引用類型去指向它),當只需要調用一次時就可以聲明匿名對象,從而節省代碼。但是多次調用同一個對象時就不適合使用匿名對象了。
2.4 this關鍵字
*與python在成員方法第一個參數裏顯式地聲明一個本對象的引用不同,Java、C++默認提供了this關鍵字,並在非靜態成員方法中利用this來調用其它成員方法。
class Person {
private String name; //姓名
public void setName(String name) { //設置姓名
this.name = name;
}
public String getName() {//獲得姓名
return this.name;
}
}
2.5 構造方法
*作用是對成員變量進行“初始化”。請注意,這裏的“初始化”本質上是賦值。與C++構造方法體的作用相同,而與C++初始化列表在本質上是不同的。C++初始化列表執行的纔是貨真價實的“初始化”。
*構造方法的生成原則是“需要纔會存在”。也就是說:
*①當我們沒有定義構造方法時,編譯器默認提供一個無參構造方法;
*②當我們定義了有參構造方法時,編譯器不提供無參構造方法,除非我們自行定義。
2.6 static關鍵字
*static可以聲明靜態成員方法和靜態成員變量。經staitc修飾的靜態成員變量和方法隨着類的加載而加載,優先於對象存在(即使對象從未存在也是如此),並被該類的所有對象所共享(即所有的對象具有同一份靜態成員變量)。
*從邏輯上來講,我們可以認爲靜態成員方法和靜態成員變量是屬於類而非對象的。因此,我們可以直接通過“類名.靜態成員方法()”以及“類名.靜態成員變量”的方式來調用(當然,前提是它們應該是public的)。
*“靜態只能訪問靜態”,也就是說,靜態方法只能訪問靜態方法和靜態成員變量;而非靜態方法則靜態和非靜態方法、變量都可以訪問。
2.7 靜態變量和成員變量的區別
*①所屬不同
* 靜態變量屬於類,所以也稱爲爲類變量
* 成員變量屬於對象,所以也稱爲實例變量(對象變量)
* ②:內存中位置不同
* 靜態變量存儲於方法區的靜態區
* 成員變量存儲於堆內存
* ③:生命週期不同
* 靜態變量隨着類的加載而加載,隨着類的消失而消失
* 成員變量隨着對象的創建而存在,隨着對象的消失而消失
* ④:調用方式不同
* 靜態變量可以通過類名調用,也可以通過對象調用
* 成員變量只能通過對象名調用
2.8 代碼塊
*在Java中,使用{}括起來的代碼被稱爲代碼塊。根據其位置和聲明的不同,可以分爲①局部代碼塊,②構造代碼塊,③靜態代碼塊,以及④同步代碼塊。
* ①:局部代碼塊
* 在方法中出現;限定變量生命週期,及早釋放,提高內存利用率
* ②:構造代碼塊 (初始化塊)
* 在類中方法外出現;多個構造方法方法中相同的代碼存放到一起,每次調用構造都執行,並且在構造方法前執行
* ③:靜態代碼塊
* 在類中方法外出現,並加上static修飾;用於給類進行初始化,在加載的時候就執行,並且只執行一次。一般用於加載驅動。
class Student {
static {
System.out.println("Student 靜態代碼塊");//3,
}
{
System.out.println("Student 構造代碼塊");//4,6
}
public Student() {
System.out.println("Student 構造方法");//5,7
}
}
class Demo {
static {
System.out.println("主類靜態代碼塊");//1,
}
public static void main(String[] args) {
System.out.println("main方法");//2,
Student s1 = new Student();
Student s2 = new Student();
}
}
輸出結果:
主類靜態代碼塊
main方法
Student 靜態代碼塊
Student 構造代碼塊
Student 構造方法
Student 構造代碼塊
Student 構造方法