Java中不太常見的語法-總結

簡介

讀源碼時,或者看同事寫的代碼,經常看到一些不太常見的語法,這里做一個總結

不太常見的語法

成員變量的默認值

案例:

public class Person2 {private String name = "張三";private Integer age;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "Person2{" +"name='" + name + '\'' +", age=" + age +'}';}
}

實例化Person2,會發現,name已經被賦默認值了:

Person2 person2 = new Person2();
System.out.println("person2 = " + person2);   // person2 = Person2{name='張三', age=null}

普通的業務代碼中不推薦這么寫,建議把賦值語句寫在構造方法中,語義更明確。

原始類型數據不能和null進行運算

案例:

int i = null;

這一行代碼會報錯,基礎數據類型不是一個對象,不支持賦null值。

我在開發中遇到的一個實際案例,當時沒有注意到這一點,這里我使用一段簡單的代碼來模擬一下:

public class Test3 {@Testpublic void test1() {Integer i = null;if (Color.RED.getId() == i) {  // 這行代碼會報空指針異常,可以使用Objects.equals來避免System.out.println("aaa");} else {System.out.println("bbb");}}enum Color {RED(1, "紅色"),BLACO(2, "黑色"),YELLOE(3, "黃色");private final int id;private final String name;Color(int id, String name) {this.id = id;this.name = name;}public int getId() {return id;}public String getName() {return name;}}
}

分析一下原因,因為基礎數據類型不支持和null進行運算,而案例中Integer類型的變量實際上是一個null值,所以會報空指針異常,我當時遇到這個問題,怎么都想不到原因,結果發現,同事定義的枚舉值中,居然使用了int類型,所以最好使用包裝類來作為成員變量的類型,這個案例中,如果id的類型是Integer,這么比較不會有問題。

do while語句

do while循環,第一次時一定會進入循環,在某些情況下使用它更合適,例如,有一種場景,需要循環讀取外部數據并處理,直到讀完,第一次的時候肯定要讀取外部數據,所以這種情況下使用do while會比較合適。

案例:

數據準備: 模擬讀取外部數據,分頁讀取

private static final List<User> list = Lists.newArrayList(new User(1L, "aaa", "aaa@qq.com", 20),new User(2L, "bbb", "bbb@qq.com", 20),new User(3L, "ccc", "ccc@qq.com", 20));private PageBO<User> readList(int pageNo, int pageSize) {PageBO<User> bo = new PageBO<>();bo.setPageNo((long) pageNo);bo.setPageSize(pageSize);bo.setTotalCount((long) list.size());int offset = (pageNo - 1) * pageSize;int limit = Math.min(offset + pageSize, list.size());if (offset < list.size()) {List<User> resultList = new ArrayList<>(list.subList(offset, limit));bo.setRecordList(deepCopyByIO(resultList));}return bo;
}// 使用IO流實現深拷貝
@SuppressWarnings("unchecked")
public static <T> T deepCopyByIO(T object) {if (object == null) {return null;}// ByteArrayOutputStream、ByteArrayInputStream,是內存流,即使不關閉也不會造成資源泄露,例如文件句柄未// 釋放等問題,即使如此,隨時關閉流依然是一個好習慣,而且關閉輸出流會保證緩沖區的數據被正確的寫出try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {objectOutputStream.writeObject(object);try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {return (T) objectInputStream.readObject();}} catch (Exception e) {e.printStackTrace(); // 打印異常信息return null;}
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBO<T> {/*** 總條數*/private Long totalCount;/*** 當前頁碼*/private Long pageNo;/*** 頁面大小*/private Integer pageSize;/*** 本頁數據*/private List<T> recordList;
}@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {private static final long serialVersionUID = 8683452581122892181L;private Long id;private String name;private String email;private Integer age;
}

案例1: 使用while語句來實現循環讀取外部數據

@Test
public void test1() {int pageNo = 1;final int PAGE_SIZE = 1;PageBO<User> pageBO = readList(pageNo, PAGE_SIZE);while (CollectionUtils.isNotEmpty(pageBO.getRecordList())) {// 處理數據System.out.println("處理數據 = " + pageBO.getRecordList());// 循環讀取pageNo++;pageBO = readList(pageNo, PAGE_SIZE);}
}

案例2: 將上面的while循環變成do while循環

@Test
public void doWhileTest() {int pageNo = 1;final int PAGE_SIZE = 1;PageBO<User> pageBO; // while 條件表達式中的變量,必須在do while之外才可以被看到do {pageBO = readList(pageNo, PAGE_SIZE);System.out.println("處理數據 = " + pageBO.getRecordList());pageNo++; // 循環讀取} while (CollectionUtils.isNotEmpty(pageBO.getRecordList()));
}

案例3:案例2中有一個問題,最后一次一定會讀到空數據,所以while不可以直接轉換為do while,代碼要做一點改變

@Test
public void doWhileTest2() {int pageNo = 1;final int PAGE_SIZE = 1;PageBO<User> pageBO;do {pageBO = readList(pageNo, PAGE_SIZE);if (CollectionUtils.isEmpty(pageBO.getRecordList())) {break;}System.out.println("處理數據 = " + pageBO.getRecordList());pageNo++; // 循環讀取} while (true);
}

案例4:一個簡單的案例

public static void main(String[] args) {java.util.Scanner scanner = new java.util.Scanner(System.in);int userInput;do {System.out.print("請輸入一個1到10之間的數字: ");userInput = scanner.nextInt();} while (userInput < 1 || userInput > 10);System.out.println("你輸入了: " + userInput);
}

總結:do while語句適合處理第一次一定會進入循環的情況,但是使用普通的while也可以,只是do wihle在語義上更加合適,不過要注意的是,判斷是否需要繼續循環的條件,和while的不太一樣,它們不可以共用。

平時do while使用的不是很多,更多的使用的是while,遇到類似的情況,可以使用更合適的do while。

問題:a = b的返回值是什么?

答案:返回b

案例:

int a = 10;
int b = 11;
int c = a = b;
System.out.println("c = " + c); // 11

這是在閱讀源碼時看到的一段代碼:

queued = UNSAFE.compareAndSwapObject(this, waitersOffset,q.next = waiters, q);

注意看方法中的參數3,q.next = waiters,最終是把什么值傳遞給了方法?答案是waiters,但同時,q.next的值也被更新為waiters了

雙括號初始化

一種快捷的初始化集合或其他對象的方式

案例:

List<String> list = new ArrayList<String>() {{add("AA");add("BB");}
};

list被初始化為一個 ArrayList 的匿名子類。大括號中的代碼塊是一個實例初始化塊,它在匿名子類創建時執行。

需要注意的是,雖然雙括號初始化語法在某些情況下很方便,但它也創建了一個匿名的子類,會產生一些額外的內存開銷,因為每個實例都是一個單獨的類。此外,這種語法在某些上下文中可能會導致問題,比如在序列化時。

這種初始化方式會創建一個匿名內部類,相較于普通的初始化方式性能較低,不建議使用,而且序列化等方面,可能會有意想不到的坑

迭代器的使用

關于迭代器的幾個問題:

  • 自己編寫的類,怎樣可以被for關鍵字遍歷? 實現Iterable接口,這個接口要求返回Iterator實例,通常需要為自己編寫的類實現一個獨有的Iterator。
  • 迭代器的初始狀態:迭代器被創建后,指針指向列表的第一個元素,hasNext的第一次判斷,是判斷列表的第一個元素存不存在,next方法,返回當前指向的元素并且指針后移。這里不是絕對的,取決于迭代器的實現邏輯,但是通常是這么實現的。

案例:模擬ArrayList,寫一個基于數組的集合

public class ArrList<E> implements List<E>, Iterable<E>, Serializable, Cloneable {private static final long serialVersionUID = 1234L;private static final int DEFAULT_CAPACITY = 8;private Object[] arr;private int size;private int capacity;public ArrList() {capacity = DEFAULT_CAPACITY;size = 0;arr = new Object[capacity];}// 省略代碼,這里只關系迭代器的實現@Overridepublic Iterator<E> iterator() {return new Itr();}private void checkIdx(int i) {if (i < 0 || i >= size) {throw new RuntimeException("下標越界:" + i);}}private class Itr implements Iterator<E> {private int idx;private int lastRet = -1;  // 上次訪問@Overridepublic boolean hasNext() {return idx < size;}@Overridepublic E next() {checkIdx(idx);lastRet = idx;return get(idx++);}// remove方法,只有在調用next方法之后才可以調用remove方法,它用于移除當前元素,// 因為此時指針已經后移,所以特定使用一個變量來記錄指針的上一個位置。@Overridepublic void remove() {checkIdx(idx);ArrList.this.remove(lastRet);  idx = lastRet;lastRet = -1;}}
}

重點查看迭代器的實現邏輯,迭代器初始化時,指向列表中的第一個元素,調用next方法,返回當前元素并且指針后移。

之前只是學習過迭代器的正確使用姿勢,自己嘗試寫一個迭代器時,才注意到它內部的邏輯,所以這里做個簡單總結

總結

這里記錄了一些不太常見的語法,跟個人經驗有關,比如我就不怎么使用do while循環來解決問題,但是有些情況下它確實更合適,還有迭代器的使用,不太清楚它的內部邏輯,剩下的就是某些不太常見的語法,或者容易被忽視的問題點。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97441.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97441.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97441.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Easytier異地組網與移動光貓GS220-s

Easytier異地組網與Nginx反向代理_--relay-network-whitelis easytier-CSDN博客 上一篇文章介紹了Easytier實現異地組網&#xff0c;基于Windows應用&#xff0c;本篇將探討如何將Easytier寫入光貓GS220-s中&#xff0c;實現更方便的家庭組網。 一、Telnet移動光貓GS220-s 1…

衛星信號和無線信號的設備廠商

以下是一些與衛星信號相關的公司&#xff1a;中國衛通集團股份有限公司&#xff1a;中國航天科技集團有限公司從事衛星運營服務業的核心專業子公司&#xff0c;是中國唯一擁有通信衛星資源且自主可控的衛星通信運營企業。運營管理著多顆在軌民商用通信廣播衛星&#xff0c;覆蓋…

HyperPlonk 的硬件友好性

1. 引言 在工業界廣泛使用的 Plonk SNARK 協議高度依賴 NTT 來完成計算。HyperPlonk 是 Plonk 的一個變種&#xff0c;它試圖通過用 Sumcheck 替代 NTT&#xff08;以及其它改進&#xff09;來提升并行性。Ingonyama團隊認為&#xff1a; Sumcheck 在 HyperPlonk 中所謂的并行…

Visual Studio內置環境變量有哪些

在 Visual Studio 中&#xff0c;內置變量&#xff08;也稱為宏&#xff09;可以用于在項目配置中指定特定的路徑、環境變量或其他值。這些變量可以在項目的屬性頁面中使用&#xff0c;也可以在代碼中使用。以下是一些常用的內置變量及其用途&#xff1a; 常用內置變量 $(Solut…

大模型入門學習微調實戰:基于PyTorch和Hugging Face電影評價情感分析模型微調全流程(附完整代碼)手把手教你做

深入淺出&#xff1a;如何訓練一個屬于你的大模型&#xff1f; “一個強大的大模型&#xff0c;究竟是如何訓練出來的&#xff1f;” 本文將基于行業共識&#xff0c;為您詳細拆解大模型的完整訓練流程&#xff0c;并提供一個基于開源模型和數據集的實戰代碼示例&#xff0c;…

零、2025 年軟件設計師考試大綱

一、考試說明 1.考試目標 通過本考試的合格人員能根據軟件開發項目管理和軟件工程的要求&#xff0c;按照系統總體設計規格說明書進行軟件設計&#xff0c;編寫程序設計規格說明書等相應的文檔&#xff0c;組織和指導程序員編寫、調試程序&#xff0c;并對軟件進行優化和集成…

uniapp npm安裝形式 全局分享和按鈕分享設置

全局分享方法新建一個shareUtil.ts方法import { storageConfig } from /config/storageConfig; export default {data() {return {miniShareOptions: {title: 標題,path: /pages/tabbar/index?inviteCode,summary: 描述,imageUrl: /userPages/static/img/invitation_h_bg.png,…

【數據結構】樹和二叉樹——樹和森林

目錄樹和二叉樹樹和森林樹的存儲結構雙親表示法孩子表示法孩子兄弟表示法森林與二叉樹的轉換樹和森林的遍歷樹的先根遍歷樹的后根遍歷樹的層次遍歷森林的先序遍歷森林的中序遍歷樹的應用求樹的深度輸出樹中所有從根到葉子的路徑的算法建樹的存儲結構的算法哈夫曼樹與哈夫曼編碼…

【小寧學習日記5 PCB】電路定理

目錄 一、先搞懂&#xff1a;原理圖的 “構成密碼” &#xff08;1&#xff09;連接線&#xff1a;別被 “直線” 騙了&#xff01; &#xff08;2&#xff09;結點&#xff1a;紅色小圓點才是 “真?連接” &#xff08;3&#xff09;網絡標簽&#xff1a;“無形的連線” …

ans1語法的一個例子nt5inf.cat

第二部分&#xff1a;語法第一部分&#xff1a;頭部語法第一部分A&#xff1a;0x30 類型位0x10SEQUENCE and SEQUENCE OF10語法第一部分B&#xff1a;83 長度3個字節&#xff0c;如果為1個字節&#xff0c;第一部分B則沒有。語法第一部分C&#xff1a;長度 0x09 …

三電平逆變器SVPWM控制(無解耦功能)與諧波分析

三電平逆變器的空間矢量脈寬調制(SVPWM)控制方法&#xff0c;重點分析在不使用解耦控制的情況下實現5%諧波含量的技術方案。我們將使用MATLAB/Simulink進行建模和仿真分析。 一、三電平逆變器基本原理 三電平逆變器相比傳統兩電平逆變器具有以下優勢&#xff1a; 輸出電壓波形質…

模擬實現C++中的string類型:從底層理解字符串操作

string前言核心成員變量設計構造函數與析構函數默認構造函數從C風格字符串構造填充構造拷貝構造函數迭代器范圍構造析構函數基本操作實現迭代器支持容量管理元素訪問字符串修改操作拼接操作插入與刪除字符串查找操作運算符重載總結每文推薦前言 在C中&#xff0c;std::string是…

pdf轉ofd之移花接木

文章目錄1.pdf轉ofd的方法1.1 spire.pdf.free1.2 ofdrw2.移花接木3.總結1.pdf轉ofd的方法 1.1 spire.pdf.free 這個是一個半開源的類庫&#xff0c;免費版本的在轉換的時候會有一個10的限制&#xff0c;所以不推薦使用&#xff0c;具體教程網上都有&#xff0c;這里只是分享有…

用【Coze】實現文案提取+創作

在AI技術飛速發展的當下&#xff0c;打造專屬智能應用成為不少人的向往。今天&#xff0c;就帶大家走進字節跳動的扣子Coze平臺&#xff0c;看看如何借助它搭建智能體&#xff0c;還會介紹AI工作流&#xff0c;以及詳細的Coze搭建步驟&#xff0c;開啟你的AI創作之旅&#xff5…

buuctf——web刷題第5頁

第五頁 目錄 [EIS 2019]EzPOP [WMCTF2020]Make PHP Great Again 2.0 [BSidesCF 2020]Hurdles [安洵杯 2019]iamthinking [GWCTF 2019]mypassword [HFCTF2020]BabyUpload [NewStarCTF 2023 公開賽道]include 0。0 [SWPU2019]Web4 [PASECA2019]honey_shop [Black Watc…

果蔬采摘機器人:自動駕駛融合視覺識別,精準定位,高效作業

在智慧農業的快速發展中&#xff0c;果蔬采摘機器人以其自動駕駛技術與視覺識別技術的完美融合&#xff0c;正逐步成為農業生產中的重要力量。這些機器人不僅實現了對果蔬的精準定位&#xff0c;還顯著提高了采摘效率&#xff0c;展現了強大的技術優勢。一、自動駕駛技術的引領…

2025年職業發展關鍵證書分析:提升專業能力的路徑選擇

在當今職場環境中&#xff0c;專業能力的提升已成為職業發展的重要方面。各類專業證書作為系統學習與能力驗證的方式&#xff0c;受到越來越多職場人士的關注。本文基于當前行業發展趨勢&#xff0c;分析8個在不同領域具有代表性的專業資格認證&#xff0c;為職場人士提供參考信…

【Qt】QCryptographicHash 設置密鑰(Key)

QCryptographicHash 本身不能設置密鑰&#xff08;Key&#xff09;。 它是一個用于計算非密鑰型加密哈希的函數&#xff0c;其設計目的和 HMAC 或加密算法完全不同。 下面我詳細解釋為什么&#xff0c;以及如何正確地實現你可能想要的功能。 1. QCryptographicHash 的核心功能&…

2025板材十大品牌客觀評估報告—客觀分析(三方驗證權威數據)

隨著消費者環保意識提升&#xff0c;板材作為家裝基礎材料的性能指標受到廣泛關注。中國林產工業協會數據顯示&#xff0c;2025年國內環保板材市場規模約860億元&#xff0c;但行業標準執行不一&#xff0c;消費者面臨信息不對稱問題。本報告嚴格依據可驗證的第三方數據&#x…

診斷通信管理(Diagnostic Communication Management)詳解

—— 基于《Specification of Diagnostics AUTOSAR AP R24-11》(SWS_Diagnostics.pdf) 診斷通信管理(Diagnostic Communication Management)是 AUTOSAR 自適應平臺診斷管理(Diagnostic Management,DM)的核心功能模塊之一,位于應用層,承擔 “診斷客戶端與診斷服務器實…