只要定義了,都會分配內(nèi)存空間
為什么要把內(nèi)存劃分為靜態(tài)區(qū)等四個區(qū)?
1、棧區(qū)— 由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等,具體方法執(zhí)行結(jié)束之后,系統(tǒng)自動釋放JVM內(nèi)存資源
2、堆區(qū)— 一般由程序員分配釋放,存放由new創(chuàng)建的對象和數(shù)組,jvm不定時查看這個對象,如果沒有引用指向這個對象就回收
3、靜態(tài)區(qū)— 存放全局變量,靜態(tài)變量和字符串常量,不釋放
4、代碼區(qū)— 存放程序中方法的二進制代碼,而且是多個對象共享一個代碼空間區(qū)域
博客:http://myhadoop.iteye.com/blog/2070153
https://blog.csdn.net/Jack_PJ/article/details/80545341
https://blog.csdn.net/u012572955/article/details/50290867
對象和引用:https://www.cnblogs.com/focusChen/articles/2497768.html
棧:基本類型的變量;對象的引用變量;
堆:new創(chuàng)建的對象和數(shù)組
2.java初始化
實例化變量--實例化代碼塊--實例化構(gòu)造方法
在Java里都是通過引用來操縱對象的。
既然兩個引用指向同一個對象,那么不管使用哪個引用操縱對象,對象的內(nèi)容都發(fā)生改變,并且只有一份。
通過s1和s得到的內(nèi)容自然也一樣,(String除外,因為String始終不變,String s1=”AAAA”;
String s=s1,操作s,s1由于始終不變,所以為s另外開辟了空間來存儲s,)
StringBuffer s;
s = new StringBuffer("Java");
StringBuffer s1 = s;
s1.append(" World");
System.out.println("s1=" + s1.toString());//打印結(jié)果為:s1=Java World
System.out.println("s=" + s.toString());//打印結(jié)果為:s=Java World
3.存在棧中的數(shù)據(jù)同一個線程可以共享:
假設我們同時定義 int a = 3; int b = 3;
編譯器先處理int a = 3;首先它會在棧中創(chuàng)建一個變量為a的引用,然后查找有沒有字面值為3的地址,
沒找到,就開辟一個存放3這個字面值的地址,然后將a指向3的地址。接著處理int b = 3;
在創(chuàng)建完b的引用變量后,由于在棧中已經(jīng)有3這個字面值,便將b直接指向3的地址。
這樣,就出現(xiàn)了a與b同時均指向3的情況。特別注意的是,這種字面值(基本數(shù)據(jù)類型)的引用與類對象的引用不同。
假定兩個類對象的引用同時指向一個對象,如果一個對象引用變量修改了這個對象的內(nèi)部狀態(tài),那么另一個對象引用變量也即刻反映出這個變化。
相反,通過字面值的引用來修改其值,不會導致另一個指向此字面值的引用的值也跟著改變的情況。
如上例,我們定義完a與 b的值后,再令a=4;那么,b不會等于4,還是等于3。在編譯器內(nèi)部,遇到a=4時,
它就會重新搜索棧中是否有4的字面值,如果沒有,重新開辟地址存放4的值;如果已經(jīng)有了,則直接將a指向這個地址。
因此a值的改變不會影響到b的值。
- Java只有一種參數(shù)傳遞方式:那就是按值傳遞,即Java中傳遞任何東西都是傳值。
如果傳入方法的是基本類型的東西,你就得到此基本類型的一份拷貝。如果是傳遞引用,就得到引用的拷貝。
//基本類型的參數(shù)傳遞
public static void testBasicType(int m) {
System.out.println("m=" + m);//m=50
m = 100;
System.out.println("m=" + m);//m=100
}
//參數(shù)為對象,不改變引用的值
public static void add(StringBuffer s) {
s.append("_add");
}
//參數(shù)為對象,改變引用的值
public static void changeRef(StringBuffer s) {
s = new StringBuffer("Java");
}
public static void main(String[] args) {
int i = 50;
testBasicType(i); //這里就相當于m=i,m和i都是指向50的引用,但m=100,就將m重新指向100,斷開了指向50的連接
System.out.println(i);//而i指向50的引用并沒有改變,所以i=50
StringBuffer sMain = new StringBuffer("init");
System.out.println("sMain=" + sMain.toString());//sMain=init
add(sMain); //這里就相當于s=sMain,s和sMain都指向‘’init‘’,因為是StringBuffer,所以改變對象的內(nèi)容,都會改變。
System.out.println("sMain=" + sMain.toString());//sMain=init_add
changeRef(sMain);//這里先將s=sMain,s指向‘’init‘’,再將賦值一個新對象,s就成了指向"Java"的引用,而sMain仍然指向‘’init‘’
System.out.println("sMain=" + sMain.toString());//sMain=init_add
}
}
5.java對象賦值過程:
A a1 = new A();
它代表A是類,a1是引用(變量),a1不是對象,new A()才是對象,a1引用指向new A()這個對象。
JAVA里“=”不能被看成是一個賦值語句,它不是在把一個對象賦給另外一個對象,它的執(zhí)行過程實質(zhì)上
是將右邊對象的地址傳給了左邊的引用,使得左邊的引用指向了右邊的對象,是一個傳地址的過程。
JAVA表面上看起來沒有指針,但它的引用其實質(zhì)就是一個指針,引用里面存放的并不是對象,而是該對象的地址,使得該引用指向了對象。
A a2;
它代表A是類,a2是引用,a2不是對象,a2所指向的對象為空null;
a2 = a1;
它代表,a2是引用,a1也是引用,a1所指向的對象的地址傳給了a2(傳址),使得a2和a1指向了同一對象
實例,其實就是對象的同義詞。
6.java接口的修飾符
1.接口必須為public abstract,因為接口是高度抽象的類,它的存在就是被其他類實現(xiàn)。
2.接口中聲明的變量必須為 public static final。
3.接口中定義的方法必須為public abstract,且沒有方法體。當然java8新增“default”與static方法,可以方法實現(xiàn)
4.外部接口而言,訪問修飾符不能是private和protected。但是內(nèi)部接口,四種訪問修飾符都可以的。
final不能修飾接口和抽象類。一旦被修飾,這個類不可繼承,或接口不可被實現(xiàn)。