本文主要是收錄一些人們可能經常會忽略辜膝,但又挺重要的Java方面的小知識爱葵。有推薦的也可以在下方留言错维,大家一起進步呀敷待!
目錄:
1.a=a+b和a+=b的區(qū)別
2.String str1 = new String("a"); String str2 = "a"+"b"; 這兩行代碼分別創(chuàng)建了幾個對象场仲,是什么
3.啟動線程的方式以及如何更好地結束一個線程和悦?
4.Java 中 == 和 equals 和 hashCode的區(qū)別
5.Java浮點數(shù)的默認類型是什么
6.多態(tài)成員訪問特點
7.用來實現(xiàn)線程間通知和喚醒的方式
8.初始化過程
9.值傳遞和引用傳遞
10.線程共享的內容和私有的內容
11.Thread和Runnable的區(qū)別
12.迭代器遍歷元素的時候,通過集合是不能修改元素的
13.EditText中的值為手機號時不能轉為int
2019-7-7
1.a=a+b和a+=b的區(qū)別
(1)從效率上看
a+=b要略高于a=a+b
(2)從運算符上看
a+=b的執(zhí)行過程是先計算出a的值渠缕,然后用一個temp對象存儲鸽素,之后和b進行相加,然后將值賦給a引用亦鳞。
a=a+b的執(zhí)行過程是先計算a+b馍忽,然后再賦值給a引用棒坏,賦值給a引用的時候如果引用a有計算過程,則會再次計算遭笋。
(3)從類型自動轉換上看
當a和b的數(shù)據類型不一樣時坝冕,a+=b會自動進行類型轉換;而a=a+b不會瓦呼,需要手動進行類型轉換
比如:
byte a = 1;
int b = 4;
a = a + b;//此時編譯會報錯喂窟,因為a為byte,b為int央串,
//a+b的時候默認會向大類型即int轉換磨澡,則a+b的類型為int,而a為byte蹋辅,所以報錯
a += b;//此時編譯不會報錯钱贯,因為+=會自動進行類型轉換挫掏,并且向低轉換
2.String str1 = new String("a"); String str2 = "a"+"b"; 這兩行代碼分別創(chuàng)建了幾個對象侦另,是什么
(1)首先第一行代碼中創(chuàng)建了兩個對象(因為字符串池中沒有a字符串),一個是new String創(chuàng)建出來的str1對象尉共,一個是在字符串池中創(chuàng)建的a對象褒傅。
(2)然后因為a字符串已經在常量池中存在了,所以在第二行代碼中就不會再創(chuàng)建a對象了袄友。接著創(chuàng)建的就是b對象殿托,最后是str2對象,值為ab剧蚣。
總結:要先看字符串池中有沒有該字符串支竹,有的話會直接拿過來,沒有再重新創(chuàng)建鸠按。
3.啟動線程的方式以及如何更好地結束一個線程礼搁?
(1)啟動線程的方式
- 繼承Thread類
- 實現(xiàn)Runnable接口
- 實現(xiàn)Callable接口通過FutureTask包裝器來創(chuàng)建Thread線程
- 匿名內部類
(2)如何更好地結束一個線程
線程中調用interrupt()方法僅僅是在當前線程中打了個停止的標記,并不是真的停止線程目尖。
如何判斷線程的狀態(tài)是否是停止馒吴,主要包含以下兩種方法:
1、this.interrupted():測試當前線程是否已經是中斷狀態(tài)瑟曲,執(zhí)行后具有將狀態(tài)標志置清除為false的功能饮戳。
2、this.isInterrupted():測試線程thread對象是否已經是中斷狀態(tài)洞拨,但不具備清除狀態(tài)標志扯罐。
注:使用stop()方法停止線程是非常暴力的,該方法已經作廢烦衣,不考慮歹河。
注意:官方文檔中說明If this thread is blocked in an invocation of the [
wait()
], [wait(long)
], or [wait(long, int)
] methods of the [Object
] class, or of the [join()
], [join(long)
], [join(long, int)
], [sleep(long)
], or [sleep(long, int)
], methods of this class, then its interrupt status will be cleared and it will receive an [InterruptedException
].
也就是說齿椅,在run方法里面調用Object類的wait或線程的join/sleep方法之后,這個標記會被清空并拋出InterruptedException異常启泣。解決方法:可在調用的方法的catch中再this.interrupt一次涣脚。(不是下文例子中的catch)
① 拋異常法
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
t1.start();
Thread.sleep(100);
t1.interrupt();
}
public static class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 5000000; i++) {
if (this.isInterrupted()) {
System.out.println("Thread Stop!");
throw new InterruptedException();
}
System.out.println("i: " + i);
}
System.out.println("我在for下面");
} catch (InterruptedException e) {
System.out.println("進入到catch了寥茫!");
}
}
}
運行結果:
...
i: 11759
i: 11760
i: 11761
i: 11762
Thread Stop遣蚀!
進入到catch了!
② 使用return
public static void main(String[] args) throws InterruptedException {
MyThread t1 = new MyThread();
t1.start();
Thread.sleep(100);
t1.interrupt();
}
public static class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5000000; i++) {
if (this.isInterrupted()) {
System.out.println("Thread Stop纱耻!");
return;
}
System.out.println("i: " + i);
}
System.out.println("我在for下面");
}
}
運行結果:
...
i: 12301
i: 12302
i: 12303
i: 12304
i: 12305
Thread Stop芭梯!
③ 使用退出標志
和上面兩種方法差不多,只不過是用一個布爾變量代替this.isInterrupted()弄喘,然后要想停止線程玖喘,賦值該布爾變量為false即可。
2019-8-2
4.Java 中 == 和 equals 和 hashCode的區(qū)別
(1)==
對于八種基本數(shù)據類型蘑志,比較的是他們的值
對于引用數(shù)據類型(類累奈,接口和數(shù)組),比較的是他們在內存中的地址急但,所以澎媒,除非是同一個new出來的對象,他們比較之后的結果為true波桩,否則為false戒努。eg:
Integer a = new Integer(127);
Integer b = 127;
Integer c = 127;
//a==b為false,b==c為true
Integer d = 128;
Integer e = 128;
//d==e為false
//這里為什么b==c為true而d==e為false呢镐躲?
//Integer b = 127在編譯時會被翻譯成Integer.valueOf(127)储玫,該方法對于[-128,127]之間
//的數(shù)會進行緩存,如果已經有的話會直接從緩存中拿出萤皂,不會再new
//因為128不在該區(qū)間撒穷,那么d和e就只是new出來的兩個不同的對象了,所以就為false
Java中堆和棧的區(qū)別
最主要的區(qū)別就是:new出來的對象和數(shù)組是存放在堆中的敌蚜,基本數(shù)據類型的變量和對象的引用變量是存放在棧中的桥滨。
Java的內存機制:
棧:當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間弛车,當該變量超過它的作用域后齐媒,Java會自動釋放掉為該變量所分配的內存空間。
堆:在堆中分配的內存纷跛,由GC來管理喻括。在堆中產生了一個數(shù)組或對象之后,還可以在棧中定義一個特殊的變量贫奠,讓棧中這個變量的值等于該數(shù)組或者對象在堆內存中的首地址唬血,棧中的這個變量就成了數(shù)組或者對象的引用變量望蜡,以后可以在程序中使用棧中的引用變量來訪問數(shù)組或者對象。
(2)equals
默認情況下的equals方法是沒有被覆蓋的拷恨,調用的都是Object類的equals方法脖律,這種情況下的equals方法和==是等效的。
public boolean equals(Object obj) {
return (this == obj);
}
如果equals方法被覆蓋腕侄,則按照新的方法來判斷小泉,覆蓋后一般
都是通過對象的內容是否相等來判斷對象是否相等。比如String類的equals方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
String類的equals方法總結為:
首先看是不是同一個對象冕杠,是的話返回true
然后看對比對象是不是String類型微姊,
接著看長度是否一致
最后比較逐個字符是否相同
實現(xiàn)高質量的equals方法的技巧如下:
首先比較兩個是否==,
然后檢查對比對象是否是該類型分预,
接著比較他們的域是否相同
最后檢查對稱性兢交,傳遞性,一致性
(3)hashCode
hashCode()方法也是Object類的一個方法笼痹,返回的是一個int型的整數(shù)配喳。在集合類操作中使用,主要是為了提高查詢速度与倡。
兩者的hashCode相同界逛,他們不一定equals昆稿。
兩者的hashCode不相同纺座,他們一定不equals。
他們equals溉潭,hashCode一定相同净响。
他們不equals,hashCode有可能相同喳瓣。
2019-8-9
5.Java浮點數(shù)的默認類型是什么
答案:double馋贤。
6.多態(tài)成員訪問特點
成員變量:編譯看左邊,運行看左邊
靜態(tài)變量:編譯看左邊畏陕,運行看左邊
成員方法:編譯看左邊配乓,運行看右邊
靜態(tài)方法:編譯看左邊,運行看左邊
7.用來實現(xiàn)線程間通知和喚醒的方式
① Object.wait/notify/notifyAll
② Condition.await/signal/signalAll
2019-8-10
8.初始化過程
① 首先惠毁,初始化父類中的靜態(tài)成員變量和靜態(tài)代碼塊犹芹,按照在程序中出現(xiàn)的順序初始化;
② 然后鞠绰,初始化子類中的靜態(tài)成員變量和靜態(tài)代碼塊腰埂,按照在程序中出現(xiàn)的順序初始化;
③ 其次蜈膨,初始化父類的普通成員變量和代碼塊屿笼,在執(zhí)行父類的構造方法牺荠;
④ 最后,初始化子類的普通成員變量和代碼塊驴一,在執(zhí)行子類的構造方法休雌;
比如:
class C {
C() {
System.out.print("C");
}
}
class A {
C c = new C();
A() {
this("A");
System.out.print("A");
}
A(String s) {
System.out.print(s);
}
}
class Test extends A {
Test() {
super("B");
System.out.print("B");
}
public static void main(String[] args) {
new Test();
}
}
Output:
CBB
(1)初始化父類的普通成員變量和代碼塊,執(zhí)行 C c = new C(); 輸出C
(2)super("B"); 表示調用父類的構造方法肝断,不調用父類的無參構造函數(shù)挑辆,輸出B
(3) System.out.print("B");
所以輸出CBB
2019-8-23
9.值傳遞和引用傳遞
“在Java里面參數(shù)傳遞都是按值傳遞”這句話的意思是:按值傳遞是傳遞的值的拷貝,按引用傳遞其實傳遞的是引用的地址值孝情,所以統(tǒng)稱按值傳遞鱼蝉。
簡單的說,
基本類型是按值傳遞箫荡,方法的實參是一個原值的副本魁亦。
類對象是按對象的引用地址(內存地址)傳遞地址的值,那么在方法內對這個對象進行修改是會直接反應在原對象上的(或者說這兩個引用指向同一內存地址)羔挡。
但是String類除外洁奈,其規(guī)則和基本類型是一樣的,因為String是final關鍵字修飾的绞灼,不可變的
eg:
public static void main(String[] args){
String x = new String("LongSh1z");
change(x);
System.out.println(x);
}
public static void change(String x){
x = "changed";
}
輸出結果應該是LongSh1z利术,而不是changed。
解釋如下:
當執(zhí)行到change方法時低矮,Main就入棧印叁,change開啟一片棧空間军掂,x是形參轮蜕,在change的棧內有一份拷貝引用x。(這時Main棧上的x和change棧上的是指向同一片堆空間蝗锥,即“LongSh1z”)跃洛。接著執(zhí)行x = "changed",此時change棧上的x會指向新的一片空間(方法區(qū)上的常量池)终议,而Main棧上的x沒有改變汇竭。
還不懂的同學可以去看看這一篇,講的巨詳細
https://blog.csdn.net/bntx2jsqfehy7/article/details/83508006
2019-9-5
10.線程共享的內容和私有的內容
(1)線程共享的內容包括:
進程代碼段
進程 數(shù)據段
進程打開的文件描述符
信號的處理器
進程的當前目錄
進程用戶 ID 與進程組 ID
(2)線程獨有的內容包括:
線程 ID
寄存器組的值
線程的堆棧
錯誤返回碼
線程的信號屏蔽碼
2019-9-17
11.Thread和Runnable的區(qū)別
(1)Runnable方式可以避免Thread方式由于Java單繼承的特性帶來的缺陷
(2)Runnable的代碼可以被多個線程(Thread實例)共享穴张,適合于多個線程處理同一資源(這里的同一資源指的是同一個Runnable對象)的情況
2019-10-26
12.迭代器遍歷元素的時候细燎,通過集合是不能修改元素的
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(6);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
list.add(6);
System.out.println(iterator.next());
}
//會報Exception in thread "main" java.util.ConcurrentModificationException異常
//正確做法:
//①使用ListIterator(List集合特有的迭代器。該迭代器繼承了Iterator迭代器)
ListIterator iterator= list.listItertor();
while(lit.hasNext()){
String s = (String)lit.next();
if(s.equals("java")){
iterator.add("love");
//注意:此處是利用迭代器進行添加元素陆馁,剛添加的元素處于剛才迭代的元素的后面找颓。
//!67贰击狮!是iterator添加佛析,不是list添加。1肱睢4缒!
}
}
//②使用普通循環(huán)方法档冬,即使用get()方法
for(int i = 0;i<list.size();i++){
String s = (String)list.get(i);
if(s.equals("java")){
list.add("love");//注意:此處是將新的元素添加到了集合的最后
}
}
//③要想繼續(xù)使用Iterator而不是ListIterator 膘茎,可以將ArrayList改為CopyOnWriteArrayList
2019-10-27
13.EditText中的值為手機號時不能轉為int
很多時候我們都需要拿到editText里面的值,并且轉為int酷誓,但是每次Integer.parseInt()時拿到的值都為0披坏。
參照了網上的方法(比如轉化之前判斷呀,try-catch呀盐数,在監(jiān)聽器里面寫呀等等)都沒用棒拂。
網上的方法可以點擊這個看看:http://blog.sina.com.cn/s/blog_a4dda2480101asy3.html
但是最重要的如果editText里面的是String類型的手機號碼轉為int的話,可以將int改為long玫氢。
因為在Java中int的范圍是從-2147483648到2147483647(10位),即2的31次方帚屉,而手機號碼為11位