java 初始化
初始化
這裡的主要內容是
初始化
相關的內容,其中還會穿插其他的內容
- 構造器初始化
- 靜態資料初始化
- 顯示的靜態初始化
- 非靜態例項初始化
穿插內容
- 構造器
- 方法過載
- this關鍵字
- static 關鍵字
構造器初始化
構造器
構造器是在建立物件時被呼叫的特殊方法。(構造器是一個方法只不過它是特殊的),之所以特殊是因為構造器沒有返回值。與返回空(void)不同。一個簡單的說法,普通方法就算是void,還是可以掉的,但構造器沒得改。構造器是一個靜態的方法,
構造器中的方法名與它所在的類名相同。這是因為為了讓編譯器能夠知道該呼叫那個方法。在建立物件時,編譯器將為物件分配儲存空間,並呼叫相應的構造器,這保證了你在操作物件之前,恰當的初始化了。
public class Apple {
// 預設構造器
Apple(){
System.out.println("Hello Word");
}
}
class Test{
public static void main(String[] args){
Apple apple = new Apple();
}
}
沒有引數出入的構造器叫預設構造器,術語是無參構造器,有引數的叫有參構造器。
public class Apple { //有參構造器 Apple(String a){ System.out.println(a); } } class Test{ public static void main(String[] args){ Apple apple = new Apple("Hello Word"); } }
如果 Apple(String)
是類裡唯一一個構造器,那麼你在建立物件時必須傳入引數。
注意:在java中初始與建立是捆綁在一起的,二者不能分離
預設構造器在沒有其它的構造器時,編譯器會自動建立一個預設構造器,如果類中有了構造器(無論是否有引數),編譯器就不會自動建立了。如果沒有構造器,就無法建立物件。
像下邊這麼寫就會編譯器會報錯,因為 編譯器沒有找到 new Apple();
沒有引數的構造器
public class Apple { Apple(String a){ System.out.println(a); } public void t(){ return; } } class Test{ public static void main(String[] args){ Apple apple = new Apple(); } }
像下邊加一個無參構造器即可。
public class Apple {
Apple(){
System.out.println("Hello Word");
}
Apple(String a){
System.out.println(a);
}
public void t(){
return;
}
}
class Test{
public static void main(String[] args){
Apple apple = new Apple();
}
}
在上邊的 Apple
類中,兩個構造器它們名字相同,傳入的引數不同,這種寫法叫 方法過載
,在普通方法中也同樣適用
方法過載
方法過載就好比相同的詞可以表達不同的含義,過載方法名字要相同其中一個重要原因是因為構造器,的名字要與類名相同,這樣只有一個構造器名,就可用多種方式建立一個物件。普通方法的過載也和構造器一樣。
public class Apple {
/* 過載構造器 */
Apple(){
}
Apple(String name){
}
Apple(String name, Integer num){
}
Apple(Integer num, String name){
}
/* 過載的方法 */
/**
* 獲取蘋果
*/
public void getApple(){
}
/**
* 獲取特定品種的蘋果
* @param type 品種
*/
public void getApple(String type){
}
/**
* 獲取特定品種,即某一數量的蘋果
* @param type 蘋果品種
* @param num 蘋果數量
*/
public void getApple(String type, Integer num){
}
/**
* 獲取特定品種,即某一數量的蘋果
* @param num 蘋果品種
* @param type 蘋果數量
*/
public void getApple(Integer num, String type){
}
}
java區分方法名相同的方法,是根據每個方法的獨一無二的引數列表去區分的。
如下這種情況雖然java允許 ,也最好不要用,因為會使得程式難以維護
Apple(String name, Integer num){
}
Apple(Integer num, String name){
}
/**
* 獲取特定品種,即某一數量的蘋果
* @param type 蘋果品種
* @param num 蘋果數量
*/
public void getApple(String type, Integer num){
}
/**
* 獲取特定品種,即某一數量的蘋果
* @param num 蘋果品種
* @param type 蘋果數量
*/
public void getApple(Integer num, String type){
}
拓展:java為什麼不用返回區過載方法。
有的時候並不需要一個方法返回東西,只需要方法本身的作用。
public void test(){
a();
}
public void test(String name){
b(name);
}
this 關鍵字
this關鍵字只能在方法內部使用,表示“呼叫方法的那個物件”。比如在Apple類的後一個方法中使用了this,this代表的就是Apple類。
public class Apple {
public void getApple(){
}
public void juice(){
this.getApple();
}
}
注意:在上邊的 juice() 方法中有呼叫,同一個類中的方法 getApple() ,在這裡是沒有必要加 this的,因為編譯器會自動幫忙加上。雖然手動加也可以,不過高階語言之所以高階,其中一個原因就是它可以幫助我們省略一些重複的事情。
只用當需要指明當前物件時才需要使用 this
public class AppleNum {
private int appleNum = 0;
public AppleNum sumAppleNum(){
appleNum ++;
return this;
}
public void print(){
System.out.println("總和:" + appleNum);
}
public static void main(String[] args) {
AppleNum appleNum = new AppleNum();
appleNum.sumAppleNum().sumAppleNum().sumAppleNum().print();
}
}
如上程式碼 sumAppleNum() 方法返回的 appleNum 物件的引用,從而使得可以迴圈呼叫 sumAppleNum() 方法。
this 可以有引數列表用於構造器呼叫構造器,構造器不能使用方法名呼叫構造器,也不能在普通方法普通方法中。在同一個構造其中 this只能呼叫一個構造器。
AppleNum(){
this("a");
}
AppleNum(String type){
this(3);
}
AppleNum(Integer i){
}
public AppleNum sumAppleNum(){
// this(3) 編譯器會報錯
}
成員初始化
如果類中的基本型別欄位沒有初始化,那java會為他們賦上預設值
public class Apple {
boolean t ;
char c;
byte b;
short s;
int i;
long l;
float f;
double d;
Apple apple;
public void get(){
System.out.println(t);
System.out.println(c);
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(apple);
}
public static void main(String[] args) {
Apple apple = new Apple();
apple.get();
}
}
從上邊程式碼可以看出,基本型別變數沒賦值,java會預設賦上初始值。物件賦上 null
,初始化的順序,影響著程式的正確性。
靜態資料初始化
除非用 new 建立物件,否則實際上並未獲得任何物件。如果不想建立物件也能呼叫某一方法或屬性,就可以使用static 關鍵字。當宣告一個事物是 static
時,就意味著這個域或方法不會它所在的類的物件例項關聯在一起。
static關鍵字
加上了 static
關鍵字,即為靜態成員變數。
public class Apple {
static int i = 1;
public static void get(){
}
public static void main(String[] args) {
Apple.get();
int num = Apple.i;
}
}
上邊展示了 static 關鍵字的基本用法,不用 new 物件也可以呼叫方法,雖然不用建立物件也可以呼叫方法,並不是說每個方法都加上 static
, 如果你的程式碼是這樣,那你就得考慮一些你程式碼的設計問題了。
下邊是加了 static
,與沒加 static
的區別
public class Apple {
static int i = 1;
int b = 2;
public void get() {
System.out.println(i);
System.out.println(b);
}
public void set(int b){
// 這裡因為入參的名字,與欄位名相同 一般使用 this 將其區分
this.b = b;
}
public static void main(String[] args) {
Apple a = new Apple();
Apple b = new Apple();
a.get();
b.get();
/*====*/
System.out.println(" /*====*/ ");
Apple.i = 10;
b.set(3);
a.set(4);
a.get();
b.get();
}
}
通過上邊的輸出返現 , a b 兩個物件在輸出 i 時是相同的,a.i b.i指向了同一個記憶體地址。這也說明多了無論建立多少物件,靜態資料都只佔一份儲存區域。
靜態初始化只有在必要時刻才會進行,例如,如果建立 Apple 物件 或者 不呼叫 Apple.i 那靜態的 i 永遠不會被創建出來。
顯示的靜態初始化
多個靜態初始化,可以簡化成一個靜態塊
public class Apple {
static {
int i;
char a;
Apple c= new Apple()
}
}
上邊這麼寫,因為是在大括號裡,意味著是區域性變數除非將物件返回出去,否則外邊的方法,裡邊的屬性
public class Apple {
Apple c;
static {
c = new Apple();
}
}
非靜態例項初始化
非靜態例項初始化,看起來和靜態塊非常像,區別就是沒有 static
關鍵字
public class Apple {
Apple c;
{
int i;
char a;
c = new Apple();
}
}
這個寫法的非靜態初始化主要是為了匿名內部類準備的。這保證了不管呼叫那個構造器這部分程式碼都會被自行
public class Apple {
Apple(){
System.out.println("5");
}
{
System.out.println("2");
}
static {
System.out.println("1");
}
{
System.out.println("4");
}
{
System.out.println("3");
}
public static void main(String[] args) {
Apple apple = new Apple();
}
}
從上邊的程式碼執行輸出可以看出,靜態塊先被執行,然後是非靜態塊,最後是,構造器