只是記錄幾個在學習Java的過程中思考的一些問題,以及自己的理解。
1.Java 局部變量、實例變量、類變量(靜態變量)區別?
2.爲什麼“類方法中不能訪問非靜態變量”?
3.如何準確記憶Java中各個訪問修飾符的訪問範圍?
4.如何理解“重載”與“覆蓋”?
1.Java 局部變量、成員變量、類變量(靜態變量)區別?
局部變量:在Java方法中的變量。其作用域只在本方法內。
成員變量:是獨立於方法之外的,不會有static修飾,也稱作“實例變量”,它就是對象的私有變量。
類變量:類變量獨立於方法之外,也稱作“靜態變量”。用static修飾。static 表示“全局的”“靜態的”,用來修飾成員變量,成員方法,或者靜態代碼塊。
成員變量和類變量的區別?
其根本區別在於,類變量是類所實例化的所有對象的公有變量,任何一個對象對該變量進行修改以後,其他對象得到的都是被修改之後的數據;成員變量是對象私有的變量,某一對象對成員變量進行修改,隻影響該對象成員變量的數據,不影響其他對象。
Code 說明:
class Student{
int age; //成員變量,“實例變量”
static int totalAge; //類變量,“靜態變量”
public void getTime()
{
float time=2016; //局部變量,作用域在本方法以內
System.out.println("time="+time);
}
}
public class Test6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s1=new Student();
Student s2=new Student();
s1.age=1;
s1.totalAge=1;
System.out.println("s2.age="+s2.age); //結果是 0
//成員變量s1.age改變,只會影響其s1.age,對象s2的成員變量s2.age不會有任何改變
System.out.println("s2.total="+s2.totalAge); //結果是1
//s1改變類變量,其他對象會得到改變之後的數據
}
}
由引導類加載器負責加載的核心類比如 String 類在 JVM 啓動時(main 方法開始執行前)就會被加載,其它類在使用前(new 它對象或調用其靜態方法訪問靜態域等等前)會被動態加載,要注意的是子類被加載前它的所有父類要根據由父到子的順序被逐一加載。
class A1
{
public static int a=5;
}
class B1 extends A1
{
public static int a=8;
void print(){
System.out.println(super.a);
System.out.println(a);
}
}
public class TestStatic
{
public static void main(String args[])
{
System.out.println("b.a="+B1.a);
System.out.println("b.a="+A1.a);
new B1().print();
}
}
說明如下:
在doc環境下,
Java TestStatic時,
虛擬機會先加載TestStatic類,此時虛擬機會先看看TestStatic類有沒有靜態的字段,
沒有。JVM直接執行main 方法,
main方法中第一句代碼是打印B1.a,
虛擬機便會去找類B1,找到類B1時,虛擬機發現B1的父親是A1,
於是父親優先,先加載A1,
同樣,在加載A1時,會看看A1中有什麼靜態的東西,有,
static int a = 5;
a是靜態的,先加載,當把靜態的字段加載完後,一個類就算加載完了,
所以A1已經加載完畢,以後不用在加載了。
父親加載完了,輪到B1了,同樣先看看裏面有什麼靜態的字段,有,
static int a = 8;
此時B1也加載完畢了。
第一條打印語句到此時也執行完畢了,
輪到第二條打印語句了。
當執行new B1().print();這句時,
會發生動態綁定,
此時會有一個代表B1對象的this對象傳遞給print()方法,
所以print()方法中的
System.out.println(a);
其實是,
System.out.println(this.a);
會打印出一個8出來。
至於super.a就簡單了,
打印父類中的a,
結果是5.
到此,main()方法執行完,整個程序退出。
雖然學習了修飾符的訪問範圍,但是總是記憶不清楚。所以想小小總結一下,加深一下印象。
Java 裏的控制訪問範圍的修飾符總共有四個,從控制範圍從小到大依次是private,默認,protected,public。但是比如protected 其訪問範圍到底是多大,同類?同包?不同包?還是記憶不清楚。
總結了一個表,如下:
做個說明:
其實對於private,default,protected,public控制範圍由小到大早已爛熟於心,但對於同類,同包,子類,不同包還沒有達到那個地步。
將“同類,同包,子類,不同包”形象比作四種關係:自己和“自己,夫妻,子女,自己的朋友”,其親密程度是由近到遠,但是範圍在擴大。
1.private 私有的,就自己能訪問,別人誰都不行。訪問範圍最小,只能是同類之間訪問。
2.default 默認的,就像親密付,只有跟自己非常親密的人才行,比如妻子。訪問範圍比private稍擴大,在同類同包都可以訪問。
3.protected 受到保護的,就像自己家的東西只有家人(自己老婆還有孩子)纔可以分享。訪問範圍比default 更大,在同類同包子類可訪問。
4.public 公有的,除了自己和家人以外,認識自己的朋友都可以看。訪問範圍比default再大一點,在同類,同包,子類,不同包可以訪問。
4.如何理解“重載”與“覆蓋”?
重載(Overloading )
簡單來講,就是類的同一種功能的多種實現形式,具體採用哪一種,取決於調用者傳遞的參數。
再具體一點:
百度百科給出的定義:方法重載是指在一個類中定義多個同名的方法,但要求每個方法具有不同的參數的類型或參數的個數。調用重載方法時,Java編譯器能通過檢查調用的方法的參數類型和個數選擇一個恰當的方法。
歸納幾個要點:
1.重載要求,在同一個類中,定義多個同名方法。
2.同名方法具有不同的參數類型/個數。
3.返回類型,可以相同也可以不同。不能以返回類型來區分重載函數。
public class Test8 {
public static void main(String[] args) {
// TODO Auto-generated method stub
A a = new A();
System.out.println("得到較大的數字:"+a.getMax(11, 12.5f));;
}
}
class A{
//返回較大的整數
int getMax(int a,int b){
if(a>b){
return a;
}else{
return b;
}
}
//返回較大的小數
float getMax(float a,float b){
if(a>b){
return a;
}else{
return b;
}
}
}
覆蓋(Overriding)
簡單的講,就是如果子類中的某個方法和父類中的名稱、返回類型、參數都一樣。那麼我們就說子類的這個方法覆蓋了父類的那個方法。
PS:覆蓋是爲了解決,子類在繼承父類以後,雖然有了父類的所有方法,但是希望對該方法做一定的修改而產生的。覆蓋也稱作“重寫”。
要點總結如下:
1.子類中的方法和父類的某一個方法名稱、返回類型、參數都一樣,則新方法會覆蓋父類中的方法。
2.如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。
3.子類中方法的修飾符訪問範圍>=父類中該方法的訪問範圍。
public class Test9 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Cat c=new Cat();
c.speak();
}
}
class Animal{
protected void speak(){
System.out.println("作爲動物,我不知道怎麼叫!");
}
}
class Cat extends Animal{
public void speak(){ //注意:public>protected 子類方法可以擴大,但不能縮小訪問範圍
System.out.println("我是小貓,喵喵!");
}
}
class Dog extends Animal{
protected void speak(){
System.out.println("我是小狗,汪汪!");
}
}