沈陽(yáng)市建設(shè)工程項(xiàng)目管理中心網(wǎng)站優(yōu)化大師官網(wǎng)
Java編程問(wèn)題top100---基礎(chǔ)語(yǔ)法系列一
- 一、Java += 操作符實(shí)質(zhì)
- 二、將InputStream轉(zhuǎn)換為String
- 使用IOUtils
- 自己寫(xiě)輪子
- 三、將數(shù)組轉(zhuǎn)換為L(zhǎng)ist
- 四、如何遍歷map對(duì)象
- 使用For-Each迭代entries(方法一)
- 使用For-Each迭代keys和values(方法二)
- 使用Iterator迭代(方法三)
- 使用泛型
- 不使用泛型
- 迭代keys并搜索values(低效的)(方法四)
- 總結(jié)
- 五、public,protected,private,不加修飾符。有什么區(qū)別呢?
- Java編程問(wèn)題top100---基礎(chǔ)語(yǔ)法系列導(dǎo)航
記得這個(gè)是當(dāng)時(shí)剛?cè)雽W(xué)那會(huì)嘗試去看的一個(gè)github上的優(yōu)秀內(nèi)容,當(dāng)時(shí)很多東西看得云里霧里,不太懂。
現(xiàn)在正好有空了,再來(lái)一次,會(huì)稍作修改再加上代碼實(shí)踐,有問(wèn)題可以留言。
重溫的同時(shí),希望對(duì)你能有所幫助。
以下系列將會(huì)是對(duì)stackoverflow上Java相關(guān)、投票數(shù)TOP100的問(wèn)答(精修版)。
一、Java += 操作符實(shí)質(zhì)
問(wèn)題:我之前以為:
i += j 等同于 i = i + j;
但假設(shè)有:
int i = 5; long j = 8;
這時(shí) i = i + j 不能編譯,但 i += j 卻可以編譯。這說(shuō)明兩者還是有差別的
這是否意味著,i += j,實(shí)際是等同于 i= (type of i) (i + j)呢?
// Java += 操作符實(shí)質(zhì)
public class test01 {public static void main(String[] args) {int i = 5;long j = 8;// i = i + j;// 編譯報(bào)錯(cuò),需要的類(lèi)型int,提供了longi += j; // 這行沒(méi)有問(wèn)題i = i + (int) j; // 這行也沒(méi)問(wèn)題}
}
回答
對(duì)復(fù)合賦值表達(dá)式E1 op= E2
來(lái)說(shuō), (諸如 i += j
i -= j
i*=j
i/=j
等等),其實(shí)是等同于 E1 = (T)((E1) op (E2))
,
其中,E1和E2表示兩個(gè)操作數(shù),T是E1
這個(gè)元素的類(lèi)型。
舉例來(lái)說(shuō),如下的代碼
int i = 5;long j = 8;
i += j;
等同于i = (int)(i + j);
也就是(i + j)
先執(zhí)行,然后(i + j)的結(jié)果
強(qiáng)制類(lèi)型轉(zhuǎn)換為int類(lèi)型
新人注意:表達(dá)式i = (int)(i + j);
里(i + j)
這個(gè)是帶括號(hào)的。
它也等價(jià)于i = i + (int) j;
二、將InputStream轉(zhuǎn)換為String
首先項(xiàng)目名字那按右鍵選Add Framework Support
或者選添加框架支持
,然后選Maven
,在pom.xml
里寫(xiě)入下面這個(gè)
<dependencies><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency></dependencies>
使用IOUtils
最靠譜的方法,用Apache commons IOUtils
文檔test02.txt
ABC a b ABc b
你好
//將InputStream轉(zhuǎn)換為String
public class test02 {public static void main(String[] args) throws Exception {FileInputStream inputStream = new FileInputStream("D:\test02.txt");String encoding = "UTF-8";StringWriter writer = new StringWriter();IOUtils.copy(inputStream, writer, encoding);String theString = writer.toString();// String theString = IOUtils.toString(inputStream, encoding);// 這個(gè)方法其實(shí)封裝了上面的方法,減少了一個(gè)參數(shù)}
}
或者
String theString = IOUtils.toString(inputStream, encoding);
//這個(gè)方法其實(shí)封裝了上面的方法,減少了一個(gè)參數(shù)
自己寫(xiě)輪子
如果不想引入Apache庫(kù),也可以這樣做
//將InputStream轉(zhuǎn)換為String
public class test02 {static String convertStreamToString(InputStream is) {Scanner s = new Scanner(is).useDelimiter("你好");//讀取到你好這個(gè)詞就會(huì)停止輸入return s.hasNext() ? s.next() : "";}public static void main(String[] args) throws FileNotFoundException {FileInputStream fileInputStream = new FileInputStream("test.txt");System.out.println(convertStreamToString(fileInputStream));}
}
三、將數(shù)組轉(zhuǎn)換為L(zhǎng)ist
1、最簡(jiǎn)單的for循環(huán)遍歷挨個(gè)賦值給List。
2、Arrays.asList(array);
// 將數(shù)組轉(zhuǎn)換為L(zhǎng)ist
public class test03 {public static void main(String[] args) {Integer[] array = {1, 2, 3, 4};List<Integer> arrayLists = Arrays.asList(array);// 這里System.out.println(arrayLists);}
}
但這樣做會(huì)有坑:
- 生成的list,是固定長(zhǎng)度的。也就是說(shuō),如果調(diào)用它的
add()
方法或者remove()
方法,都會(huì)拋異常UnsupportedOperationException。 - 如果修改
數(shù)組
的值,list
中的對(duì)應(yīng)值也會(huì)改變!
因?yàn)锳rrays.asList() 返回的是Arrays里的內(nèi)部靜態(tài)類(lèi)
,而不是Java.util.ArrayList這個(gè)類(lèi)。
這個(gè)java.util.Arrays.ArrayList有set(),get(),contains()方法,但是沒(méi)有任何add()
方法,所以它是固定大小的.
建議用這個(gè)
Collections.addAll(arrayLists, array);
// 將數(shù)組轉(zhuǎn)換為L(zhǎng)ist
public class test03 {public static void main(String[] args) {Integer[] array = {1, 2, 3, 4};List<Integer> arrayLists = new ArrayList<>();Collections.addAll(arrayLists, array);// 這里}
}
四、如何遍歷map對(duì)象
在Java中有多種遍歷HashMap的方法。
讓我們回顧一下最常見(jiàn)的方法和它們各自的優(yōu)缺點(diǎn)。
由于所有的Map都實(shí)現(xiàn)了Map接口,所以接下來(lái)方法適用于所有Map(如:HaspMap,TreeMap,LinkedMap,HashTable,ConcurrentHashMAp,……)
使用For-Each迭代entries(方法一)
這是最常見(jiàn)的方法,并在大多數(shù)情況下更可取的。當(dāng)你在循環(huán)中需要使用Map的鍵和值時(shí),就可以使用這個(gè)方法
public class test04 {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();// map = null;map.put("a", 1);testOne(map);}public static void testOne(Map<String, Integer> map) {if (map != null && !map.isEmpty()) {for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());}}else {System.out.println(map);}}
}
注意:遍歷之前你應(yīng)該判斷是否為空引用。如果遍歷的map是null的話(huà),For-Each循環(huán)會(huì)拋出NullPointerException異常。
使用For-Each迭代keys和values(方法二)
如果你只需要用到map的keys或values時(shí),你可以遍歷KeySet或者values代替entrySet
public static void testTwo(Map<String, Integer> map) {if (map != null && !map.isEmpty()) {for (String key : map.keySet()) {System.out.println("Key = " + key);}for (Integer value : map.values()) {System.out.println("Value = " + value);}}}
這個(gè)方法比entrySet迭代具有輕微的性能優(yōu)勢(shì)(大約快10%)并且代碼更簡(jiǎn)潔
使用Iterator迭代(方法三)
使用泛型
public static void testThree(Map<String, Integer> map) {Iterator<Map.Entry<String, Integer>> entries = map.entrySet().iterator();while (entries.hasNext()) {Map.Entry<String, Integer> entry = entries.next();System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());}}
不使用泛型
public static void testFour(Map<String, Integer> map) {if (map != null && !map.isEmpty()) {Iterator entries = map.entrySet().iterator();while (entries.hasNext()) {Map.Entry entry = (Map.Entry) entries.next();String key = (String) entry.getKey();Integer value = (Integer) entry.getValue();System.out.println("Key = " + key + ", Value = " + value);}} else {System.out.println(map);}}
你可以使用同樣的技術(shù)迭代keyset或者values
首先,它是遍歷java 5 以前版本的map的唯一方法。
第二是可以讓你在迭代的時(shí)候從map中刪除entries的(通過(guò)調(diào)用iterator.remover())唯一方法。
如果你試圖在For-Each迭代的時(shí)候刪除entries,你將會(huì)得到unpredictable resultes 異常。
從性能方面看,這個(gè)方法等價(jià)于使用For-Each迭代(方法二)
迭代keys并搜索values(低效的)(方法四)
public static void testFive(Map<String, Integer> map) {if (map != null && !map.isEmpty()) {for (String key : map.keySet()) {Integer value = map.get(key);System.out.println("Key = " + key + ", Value = " + value);}} else {System.out.println(map);}}
比方法一更簡(jiǎn)潔,但是實(shí)際更慢更低效,通過(guò)key得到value值更耗時(shí)
總結(jié)
如果你只需要使用key或者value使用方法二使用For-Each迭代keys和values
,如果你使用java 5 以前的版本或者打算在迭代的時(shí)候移除entries,使用方法三使用Iterator迭代
。其他情況請(qǐng)使用方法一For-Each迭代entries
方法。避免使用迭代keys并搜索values(低效的)
方法。
五、public,protected,private,不加修飾符。有什么區(qū)別呢?
如下表所示,Y表示能訪問(wèn)(可見(jiàn)性),N表示不能訪問(wèn),例如第一行的第3個(gè)Y,表示類(lèi)的變量/方法如果是用public修飾,它的子類(lèi)能訪問(wèn)這個(gè)變量/方法
修飾符 | 類(lèi)內(nèi)部 | 同個(gè)包(package) | 子類(lèi) | 其他范圍 |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
無(wú)修飾符 | Y | Y | N or Y(見(jiàn)說(shuō)明) | N |
private | Y | N | N | N |
說(shuō)明:
需要特別說(shuō)明“無(wú)修飾符”這個(gè)情況,子類(lèi)能否訪問(wèn)父類(lèi)中無(wú)修飾符的變量/方法,取決于子類(lèi)是否在同一個(gè)包中。如果子類(lèi)和父類(lèi)在同一個(gè)包中,那么子類(lèi)可以訪問(wèn)父類(lèi)中的無(wú)修飾符的變量/方法,否則不行。
Java編程問(wèn)題top100—基礎(chǔ)語(yǔ)法系列導(dǎo)航
Java編程問(wèn)題top100—基礎(chǔ)語(yǔ)法系列(一)
Java編程問(wèn)題top100—基礎(chǔ)語(yǔ)法系列(二) 待更新
Java編程問(wèn)題top100—基礎(chǔ)語(yǔ)法系列(三) 待更新
如有錯(cuò)誤,還請(qǐng)多多指教!
轉(zhuǎn)載或者引用本文內(nèi)容請(qǐng)注明來(lái)源及原作者:橘足輕重;