日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

后端技术:Java编程中忽略这些细节,Bug肯定少不了

發(fā)布時間:2023/12/10 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后端技术:Java编程中忽略这些细节,Bug肯定少不了 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在Java語言的日常編程中,也存在著容易被忽略的細(xì)節(jié),這些細(xì)節(jié)可能會導(dǎo)致程序出現(xiàn)各種Bug。

Java語言構(gòu)建的各類應(yīng)用程序,在人類的日常生活中占用非常重要的地位,各大IT廠商幾乎都會使用它來構(gòu)建自己的產(chǎn)品,為客戶提供服務(wù)。作為一個企業(yè)級應(yīng)用開發(fā)語言,穩(wěn)定和高效的運行,至關(guān)重要。在Java語言的日常編程中,也存在著容易被忽略的細(xì)節(jié),這些細(xì)節(jié)可能會導(dǎo)致程序出現(xiàn)各種Bug,下面就對這些細(xì)節(jié)進(jìn)行一些總結(jié):

1 相等判斷中的==和equals

在很多場景中,我們都需要判斷兩個對象是否相等,一般來說,判定兩個對象的是否相等,都是依據(jù)其值是否相等,如兩個字符串a(chǎn)和b的值都為"java",則我們認(rèn)為二者相等。在Java中,有兩個操作可以判斷是否相當(dāng),即==和equals,但二者是有區(qū)別的,不可混用。下面給出示例:

String a = "java"; String b = new String("java"); System.out.println(a == b);//false System.out.println(a.equals(b));//true

字符串a(chǎn)和b的字面值都為"java",用a == b判斷則輸出false,即不相等,而a.equals(b)則輸出true,即相等。這是為什么呢?在Java中,String是一個不可變的類型,一般來說,如果兩個String的值相等,默認(rèn)情況下,會指定同一個內(nèi)存地址,但這里字符串String b用new String方法強(qiáng)制生成一個新的String對象,因此,二者內(nèi)存地址不一致。由于 == 需要判斷對象的內(nèi)存地址是否一致,因此返回false,而equals默認(rèn)(override后可能不一定)是根據(jù)字面值來判斷,即相等。

下面再給出一個示例:

//integer -128 to 127 Integer i1 = 100; Integer i2 = 100; System.out.println(i1 == i2);//true i1 = 300; i2 = 300; System.out.println(i1 == i2);//false System.out.println(i1.equals(i2));//true

這是由于Java中的Integer數(shù)值的范圍為-128到127,因此在這范圍內(nèi)的對象的內(nèi)存地址是一致的,而超過這個范圍的數(shù)值對象的內(nèi)存地址是不一致的,因此300這個數(shù)值在 == 比較下,返回false,但在equals比較下返回true。

2 switch語句中丟失了break

在很多場景中,我們需要根據(jù)輸入?yún)?shù)的范圍來分別進(jìn)行處理,這里除了可以使用if ... else ...語句外,還可以使用switch語句。在switch語句中,會羅列出多個分支條件,并進(jìn)行分別處理,但如果稍有不注意,就可能丟失關(guān)鍵字break語句,從而出現(xiàn)預(yù)期外的值。下面給出示例:

//缺少break關(guān)鍵字public static void switchBugs(int v ) {switch (v) {case 0:System.out.println("0");//breakcase 1:System.out.println("1");break;case 2:System.out.println("2");break;default:System.out.println("other");} }

如果我們使用如下語句進(jìn)行調(diào)用:

switchBugs(0);

則我們預(yù)期返回"0",但是卻返回"0" "1"。這是由于case 0 分支下缺少break關(guān)鍵字,則雖然程序匹配了此分支,但是卻能穿透到下一個分支,即case 1分支,然后遇到break后返回值。

3 大量的垃圾回收,效率低下

字符串的拼接操作,是非常高頻的操作,但是如果涉及的拼接量很大,則如果直接用 + 符號進(jìn)行字符串拼接,則效率非常低下,程序運行的速度很慢。下面給出示例:

private static void stringWhile(){//獲取開始時間long start = System.currentTimeMillis();String strV = "";for (int i = 0; i < 100000; i++) {strV = strV + "$";}//strings are immutable. So, on each iteration a new string is created.// To address this we should use a mutable StringBuilder:System.out.println(strV.length());long end = System.currentTimeMillis(); //獲取結(jié)束時間System.out.println("程序運行時間:"+(end-start)+"ms");start = System.currentTimeMillis();StringBuilder sb = new StringBuilder();for (int i = 0; i < 100000; i++) {sb.append("$");}System.out.println(strV.length());end = System.currentTimeMillis();System.out.println("程序運行時間:"+(end-start)+"ms"); }

上述示例分別在循環(huán)體中用 + 和 StringBuilder進(jìn)行字符串拼接,并統(tǒng)計了運行的時間(毫秒),下面給出模擬電腦上的運行結(jié)果:

//+ 操作 100000 程序運行時間: 6078ms StringBuilder操作 100000 程序運行時間: 2ms

由此可見,使用StringBuilder構(gòu)建字符串速度相比于 + 拼接,效率上高出太多。究其原因,就是因為Java語言中的字符串類型是不可變的,因此 + 操作后會創(chuàng)建一個新的字符串,這樣會涉及到大量的對象創(chuàng)建工作,也涉及到垃圾回收機(jī)制的介入,因此非常耗時。

4 循環(huán)時刪除元素

有些情況下,我們需要從一個集合對象中刪除掉特定的元素,如從一個編程語言列表中刪除java語言,則就會涉及到此種場景,但是如果處理不當(dāng),則會拋出
ConcurrentModificationException異常。下面給出示例:

private static void removeList() {List<String> lists = new ArrayList<>();lists.add("java");lists.add("csharp");lists.add("fsharp");for (String item : lists) {if (item.contains("java")) {lists.remove(item);}} }

運行上述方法,會拋出錯誤,此時可以用如下方法進(jìn)行解決,即用迭代器iterator,具體如下所示:

private static void removeListOk() {List<String> lists = new ArrayList<>();lists.add("java");lists.add("csharp");lists.add("fsharp");Iterator<String> hatIterator = lists.iterator();while (hatIterator.hasNext()) {String item = hatIterator.next();if (item.contains("java")) {hatIterator.remove();}}System.out.println(lists);//[csharp, fsharp] }

5 null引用

在方法中,首先應(yīng)該對參數(shù)的合法性進(jìn)行驗證,第一需要驗證參數(shù)是否為null,然后再判斷參數(shù)是否是預(yù)期范圍的值。如果不首先進(jìn)行null判斷,直接進(jìn)行參數(shù)的比較或者方法的調(diào)用,則可能出現(xiàn)null引用的異常。下面給出示例:

private static void nullref(String words) {//NullPointerExceptionif (words.equals("java")){System.out.println("java");}else{System.out.println("not java");} }

如果此時我們用如下方法進(jìn)行調(diào)用,則拋出異常:

nullref(null)

這是由于假設(shè)了words不為null,則可以調(diào)用String對象的equals方法。下面可以稍微進(jìn)行一些修改,如下所示:

private static void nullref2(String words) {if ("java".equals(words)){System.out.println("java");}else{System.out.println("not java");} }

則此時執(zhí)行則可以正確運行:

nullref2(null)

6 hashCode對equals的影響

前面提到,equals方法可以從字面值上來判斷兩個對象是否相等。一般來說,如果兩個對象相等,則其hash code相等,但是如果hash code相等,則兩個對象可能相等,也可能不相等。這是由于Object的equals方法和hashCode方法可以被Override。下面給出示例:

package com.jyd; import java.util.Objects; public class MySchool {private String name;MySchool(String name) {this.name = name;}@Overridepublic boolean equals(Object o) {if (this == o) {return true;}if (o == null || getClass() != o.getClass()) {return false;}MySchool _obj = (MySchool) o;return Objects.equals(name, _obj.name);}@Overridepublic int hashCode() {int code = this.name.hashCode();System.out.println(code);//return code; //true//隨機(jī)數(shù)return (int) (Math.random() * 1000);//false} } Set<MySchool> mysets = new HashSet<>(); mysets.add(new MySchool("CUMT")); MySchool obj = new MySchool("CUMT"); System.out.println(mysets.contains(obj));

執(zhí)行上述代碼,由于hashCode方法被Override,每次返回隨機(jī)的hash Code值,則意味著兩個對象的hash code不一致,那么equals判斷則返回false,雖然二者的字面值都為"CUMT"。

7 內(nèi)存泄漏

我們知道,計算機(jī)的內(nèi)存是有限的,如果Java創(chuàng)建的對象一直不能進(jìn)行釋放,則新創(chuàng)建的對象會不斷占用剩余的內(nèi)存空間,最終導(dǎo)致內(nèi)存空間不足,拋出內(nèi)存溢出的異常。內(nèi)存異?;镜膯卧獪y試不容易發(fā)現(xiàn),往往都是上線運行一定時間后才發(fā)現(xiàn)的。下面給出示例:

package com.jyd;import java.util.Properties; //內(nèi)存泄漏模擬 public class MemoryLeakDemo {public final String key;public MemoryLeakDemo(String key) {this.key =key;}public static void main(String args[]) {try {Properties properties = System.getProperties();for(;;) {properties.put(new MemoryLeakDemo("key"), "value");}} catch(Exception e) {e.printStackTrace();}}/*@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;MemoryLeakDemo that = (MemoryLeakDemo) o;return Objects.equals(key, that.key);}@Overridepublic int hashCode() {return Objects.hash(key);}*/}

此示例中,有一個for無限循環(huán),它會一直創(chuàng)建一個對象,并添加到properties容器中,如果MemoryLeakDemo類未給出自己的equals方法和hashCode方法,那么這個對象會被一直添加到properties容器中,最終內(nèi)存泄漏。但是如果定義了自己的equals方法和hashCode方法(被注釋的部分),那么新創(chuàng)建的MemoryLeakDemo實例,由于key值一致,則判定為已存在,則不會重復(fù)添加,此時則不會出現(xiàn)內(nèi)存溢出。

IT技術(shù)分享社區(qū)

個人博客網(wǎng)站:https://programmerblog.xyz

文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠(yuǎn)程辦公:常用的遠(yuǎn)程協(xié)助軟件,你都知道嗎?51單片機(jī)程序下載、ISP及串口基礎(chǔ)知識硬件:斷路器、接觸器、繼電器基礎(chǔ)知識

總結(jié)

以上是生活随笔為你收集整理的后端技术:Java编程中忽略这些细节,Bug肯定少不了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲精品 日韩无码 | 高清在线一区二区三区 | 国产精品免费一区二区 | 激情综合网激情 | 欧美妞干网 | 久免费一级suv好看的国产 | 欧美日韩午夜爽爽 | 美丽的小蜜桃2:美丽人生 | 中文字幕99 | 亚洲国产片 | 亚洲视频精选 | 99久久久国产精品免费蜜臀 | 97久久久久久 | 成人在线免费网站 | 欧美视频www | 18p在线观看 | 久久久久久久久久久综合 | 欧美日韩加勒比 | 性三级视频 | 少妇太爽了在线观看 | 一级黄色片看看 | 天天看天天操 | 亚洲国产精品999 | 另类欧美亚洲 | 欧美黄色免费视频 | 国产在线不卡视频 | 一级片手机在线观看 | 久久偷看各类wc女厕嘘嘘偷窃 | 欧美精品aaa | 97看片吧| 成人性视频sm. | 疯狂少妇 | 三上悠亚三级 | 国产视频第一区 | 91免费看大片 | 中文有码av| 久久久中文网 | 国产18在线观看 | 日韩人妻无码精品久久久不卡 | 九七电影院97理论片 | 国产精品国产三级国产普通话蜜臀 | 国产天天操 | 久久综合av | 伦伦影院午夜理伦片 | 欧美在线一二三 | 后入内射欧美99二区视频 | 妖精视频一区二区 | 精品人伦一区二区三区蜜桃网站 | 亚洲视频在线观看免费视频 | 91国产一区二区 | 免费网站91| 国产成人毛毛毛片 | 奇米四色在线视频 | 草草久久久 | 理论片中文字幕 | 欧美高清日韩 | 日本黄色大片网站 | 精品影视一区二区 | 亚洲www.| 国产黄色一区 | 91av在线看| 综合爱爱网 | 国产制服91一区二区三区制服 | 欧美大片免费观看 | 亚洲欧洲成人精品久久一码二码 | 国产精品变态另类虐交 | 亚洲中文无码av在线 | аⅴ资源天堂资源库在线 | 日本三级韩国三级三级a级中文 | 女人的洗澡毛片毛多 | 成人动漫在线免费观看 | 97国产视频| 美女黄色小视频 | 成人h片| 亚洲av永久纯肉无码精品动漫 | 欧美视频自拍偷拍 | 麻豆久久久午夜一区二区 | 狠狠操综合网 | 日韩免费淫片 | 中文字幕日本一区二区 | 狠狠干视频网 | 国产一二三四在线 | 超碰在线一区 | 天堂社区av| 亚洲精品乱码久久久久久写真 | 国产精品人八做人人女人a级刘 | 欧美成人精品二区三区99精品 | 富二代成人短视频 | 成人免费公开视频 | 国产精品极品白嫩在线 | 美女扒开腿让男人捅 | 国产尤物视频在线 | 黄色免费网站在线观看 | 久久桃色| 性欧美长视频 | 亚洲无吗一区二区三区 | 欧美无砖区 | 免费黄色欧美 | 狠狠干狠狠操视频 |