JAVA|后端編碼規范

目錄

零、引言

一、基礎

二、集合

三、并發

四、日志

五、安全


零、引言

規范等級:

  • 【強制】:強制遵守,來源于線上歷史故障,將通過工具進行檢查。
  • 【推薦】:推薦遵守,來源于日常代碼審查、開發人員反饋和行業經驗。

一、基礎

序號

等級

規范

示例??

說明

1

強制

在POJO類中定義布爾類型成員變量時,禁止用is作變量名前綴。

反例:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

private?boolean?isDeleted;

// Getter方法:IDEA生成,與變量同名。

public?boolean?isDeleted() {

????return?isDeleted;

}

// Setter方法:IDEA生成

public?void?setDeleted(boolean?deleted) {

????isDeleted = deleted;

}

is作變量名前綴的布爾型成員變量,在一些IDE(如:IDEA)中,默認生成的getter方法與變量名相同,導致部分框架(如:Jackson、Fastjson)在反向解析時會引發“找不到指定成員變量名”的錯誤。
2

強制

在對象之間做相等比較時,應當使用Objects工具類(java.util.Objects)的equals方法。

正例:

String versionNo =?"6.6.1";

// 如param為null,不會出現異常。

Objects.equals(param, versionNo);

反例:

String versionNo =?"6.6.1";

// 如param為null,會出現異常。

param.equals(versionNo);

當對象為null時,直接調用equals會出現空指針異常。

注意:Objects的equals方法內部會利用參數對象的equals方法進行比較,對數組、集合之類的對象并不會做內部元素的一一比較。

3

強制

在BigDecimal之間做等值比較時,禁止使用equals方法。

正例:

// 商品原價格

BigDecimal skuPrice =?new?BigDecimal("120.00");

// 商品優惠后價格

BigDecimal skuPromoPrice =?new?BigDecimal("120.0");

// 使用compareTo做比較,不會比較精度。

if?(skuPrice.compareTo(skuPromoPrice) ==?0) {?// true

????// ...

}

反例:

// 商品原價格

BigDecimal skuPrice =?new?BigDecimal("120.00");

// 商品優惠后價格

BigDecimal skuPromoPrice =?new?BigDecimal("120.0");

// 使用equals做比較,會比較精度。

if?(skuPrice.equals(skuPromoPrice)) {?// false

????// ...

}

BigDecimal的equals方法會比較精度,如1.0與1.00比較的結果為false,推薦使用其

compareTo方法做比較。

4強制在浮點數之間做等值比較時,基本類型禁止使用==,包裝類型禁止使用equals。

正例:

// 下方減法運算是為了故意引起浮點誤差

// 時段一的單價:充電站單價 - 優惠價

float?timePrice1 =?1.0F -?0.9F;

// 時段二的單價:充電站單價 - 優惠價

float?timePrice2 =?0.9F -?0.8F;

// 工具類推薦:org.apache.commons.lang3.math.NumberUtils

// 將浮點數轉為BigDecimal并指定保留位數和取舍方式

BigDecimal decimalTimePrice1 = NumberUtils.toScaledBigDecimal(timePrice1,?2, RoundingMode.HALF_UP);

BigDecimal decimalTimePrice2 = NumberUtils.toScaledBigDecimal(timePrice2,?2, RoundingMode.HALF_UP);

if?(decimalTimePrice1.compareTo(decimalTimePrice2) ==?0) {?// true

????// ...

}

反例:

// 下方減法運算是為了故意引起浮點誤差

// 時段一的單價:充電站單價 - 優惠價

float?timePrice1 =?1.0F -?0.9F;

// 時段二的單價:充電站單價 - 優惠價

float?timePrice2 =?0.9F -?0.8F;

//? 可能存在浮點誤差,等式不成立。

if?(timePrice1 == timePrice2) {?// false

????// ...

}

反例:

// 下方減法運算是為了故意引起浮點誤差

// 時段一的單價:充電站單價 - 優惠價

Float timePrice1 =?1.0F -?0.9F;

// 時段二的單價:充電站單價 - 優惠價

Float timePrice2 =?0.9F -?0.8F;

// 可能存在浮點誤差,等式不成立。

if?(timePrice1.equals(timePrice2)) {?// false

????// ...

}

浮點數先轉成BigDecimal,再用compareTo方法做比較,以避免精度問題影響結果。

浮點數采用“尾數+階碼”的編碼方式,類似于科學計數法的“有效數字+指數”的表示方式。二進制無法精確表示大部分的十進制小數。

5

強制

將浮點數轉換為BigDecimal 時,禁止直接使用構造方法。

正例:

// 商品SKU單價

double?skuPrice =?0.1D;

// 工具類推薦:org.apache.commons.lang3.math.NumberUtils

// 精度不影響,仍然是0.1。

BigDecimal decimalSkuPrice = NumberUtils.createBigDecimal(Double.toString(skuPrice));

反例:

// 商品SKU單價

double?skuPrice =?0.1D;

// 精度受影響,可能是0.1000000000000000055511151231257827021181583404541015625。

BigDecimal decimalSkuPrice =?new?BigDecimal(skuPrice);

BigDecimal的浮點數構造方法存在精度損失風險,在精確計算或值比較的場景中會導致業務邏輯異常。

注意:和上一條的正例不同的是,前者在經過浮點計算后已經形成了誤差,在轉換時用toScaledBigDecimal方法限定了精度。在此處,是為了避免因直接利用浮點數構造而導致的誤差。

6強制在空指針異常易發的場景中,應當對對象做null判斷。

正例:

@Resource

private?UserService userService;

public?String queryCityName(String userId) {

????User userObj = userService.queryUserInfo(userId);

????Optional<User> userData = Optional.ofNullable(userObj);

????Optional<UserAddress> userAddress = userData.map(User::getUserAddress);

????// 如用戶地址為null,不會空指針異常。

????Optional<String> optionalCityName = userAddress.map(UserAddress::getCiyName);

????// null時返回默認值

????String cityName = optionalCityName.orElse(DEFAULT_CITY);

????return?cityName;

}??

反例:

@Resource

private?UserService userService;

public?String queryCityName(String userId) {

????User userObj = userService.queryUserInfo(userId);

????// 如用戶地址為null,會空指針異常。

????String cityName = userObj.getUserAddress().getCiyName();

????return?cityName;

}

在對象未判斷null的情況下直接引用,容易發生空指針異常,推薦用Optional類更優雅的處理null對象。

一些空指針異常(NPE)易發的場景:

  1. 返回類型為基本數據類型,return包裝數據類型的對象時,自動拆箱有可能產生NPE。
  2. 數據庫的查詢結果可能為null
  3. 集合里的元素即使isNotEmpty,取出的數據元素也可能為null。
  4. 遠程調用返回對象時,一律要求進行空指針判斷,防止NPE。
  5. 對于Session中獲取的數據,建議進行NPE檢查,避免空指針。
  6. 級聯調用obj.getA().getB().getC(),一連串調用,易產生NPE。

7

強制

在日期格式化時,應當使用DateUtils工具類

正例

Calendar calendar = Calendar.getInstance();

// 日期是2023-12-31

calendar.set(2023,?11,?31);

// strDateTime:2023-12-31

String strDateTime = DateUtils.datesToString(calendar.getTime());

反例

Calendar calendar = Calendar.getInstance();

// 日期是2023-12-31

calendar.set(2023,?11,?31);

// 誤用了大寫Y格式化年份

SimpleDateFormat simpleDateFormat =?new?SimpleDateFormat("YYYY-MM-dd");

// strDateTime:2024-12-31

String strDateTime = simpleDateFormat.format(calendar.getTime());

DateUtils包裝了常用的日期格式,避免了手動格式化時的誤用風險,如:年份格式化誤書寫成YYYY,如本周存在跨年的情況,返回的就是下一年。

8強制POJO類屬性,禁止使用基本數據類型。

正例

@Resource

private?UserRepository userRepository;

public?Integer queryUserId(String phone) {

????// getUserIdByPhone返回的是Integer類型,當返回null時,不會出現空指針異常。

????Integer userId = userRepository.getUserIdByPhone(phone);

????// 可以做防御性校驗,以避免直接空指針

????if(userId !=?null){

????????// …

????}

????// …

}

反例:

@Resource

private?UserRepository userRepository;

public?int?queryUserId(String phone) {

????//? getUserIdByPhone返回的是Integer類型,當返回null時,會出現空指針異常。

????int?userId = userRepository.getUserIdByPhone(phone);

????// …

}

POJO類屬性使用包裝數據類型有如下優點:

  1. 若值為null時,能顯式的提醒使用者做相應的處理,而不是使用基本數據類型的默認值。
  2. 避免對象之間的自動拆裝箱時出現NPE。

二、集合

序號

等級

規范

示例

說明

1

強制

在需要對List的subList方法返回結果進行遍歷、增加、刪除元素時,禁止直接變更原List中的元素。

反例:

List<String> cityList =?new?ArrayList<>();

cityList.add("北京");

cityList.add("上海");

cityList.add("廣州");

List<String> citySubList = cityList.subList(0,?1);

// subList之后變更原List

cityList.add("深圳");

// 出現ConcurrentModificationException異常

for?(int?i =?0; i < citySubList.size(); i++) {

????// ...

}

List的subList方法返回的是一個List的內部類對象,它是List的一個視圖,對原List所有的操作都會反映到這個對象上。

同時,對原List進行元素的增加或刪除,會被計數(modCount,結構變更次數),此數值和原subList時記錄的數值(expectedModCount)不一致,會引發ConcurrentModification

Exception異常。

2強制

對集合進行for循環時,禁止在循環體內用remove/add方法。

正例:

List<String> cityList =?new?ArrayList<>();

cityList.add("北京");

cityList.add("上海");

cityList.add("廣州");

Iterator<String> iterator = cityList.iterator();

while?(iterator.hasNext()) {

????String city = iterator.next();

????// 工具類推薦:org.apache.commons.lang3.StringUtils

????if?(StringUtils.equals("廣州", city)) {

????????iterator.remove();

????}

}

反例:

List<String> cityList =?new?ArrayList<>();

cityList.add("北京");

cityList.add("上海");

cityList.add("廣州");

// 出現ConcurrentModificationException異常

for?(String city : cityList) {

????// 工具類推薦:org.apache.commons.lang3.StringUtils

????if?(StringUtils.equals("廣州", city)) {

????????cityList.remove(city);

????}

}

若在for循環體內對集合元素進行remove/add操作,可能導致異常,建議使用iterator方式處理。

三、并發

序號

等級

規范

示例

說明

1

強制

動態線程池只允許使用通義管理平臺定義的(比如Poseidon),禁止自行創建。

正例:

// poseidonThreadPool在Poseidon管理平臺已創建

@Resource(name =?"poseidonThreadPool")

private?ThreadPoolExecutor poseidonThreadPool;

CompletableFuture.supplyAsync(() -> {

????// ...

}, poseidonThreadPool);

反例:

// 自建線程池,未接入Poseidon。

ThreadPoolExecutor customThreadPool =?new?ThreadPoolExecutor(corePoolSize,

????????????????????maximumPoolSize,

????????????????????keepAliveTime,

????????????????????unit,

????????????????????workQueue,

????????????????????new?ThreadPoolExecutor.AbortPolicy());

CompletableFuture.supplyAsync(() -> {

????// ...

}, customThreadPool);

通過Poseidon創建的線程池將能較好的進行管理和監控:

  1. 支持通過Poseidon動態修改線上線程池參數(線程數量、隊列長度、拒絕策略),無需重啟服務即可生效。
  2. CAT平臺能對線程池狀態進行監控和告警。
2強制

在使用線程池時,禁止將拒絕策略設置為DiscardPolicy。

反例:

// poseidonThreadPool在Poseidon管理平臺已創建,且配置了DiscardPolicy拒絕策略。

@Resource(name =?"poseidonThreadPool")

private?ThreadPoolExecutor poseidonThreadPool;

public?void?process(){

????// ...

????// 隊列滿且已達到最大線程數后,任務會被自動拋棄。

????Future<String> resultFuture = poseidonThreadPool.submit(task);

????// ...

}

若配置了DiscardPolicy,當線程池隊列排滿且已達到了最大線程數后,新增任務會被直接丟棄,無任何提示,并且在結合future.get()運行時,存在阻塞的風險。

3強制

父子任務禁止使用同一個線程池。

反例:

class?OrderManager {

????// Poseidon配置的線程池

????@Resource(name =?"poseidonThreadPool")?

????private?ThreadPoolExecutor poseidonThreadPool;

????@Autowired

????private?ProductManager productManager;

????public?List<Order> queryOrders()?throws?Exception {

????????// ...

????????// 如果子任務出現阻塞,父任務一直等待。

????????Future<Order> orderFuture = poseidonThreadPool.submit(() -> {

????????????// ...

????????????ProductInfo product = productManager.queryProducts(orderId);

????????????// ...

????????});

????????orderFuture.get();

????????// ...

????}

}

class?ProductManager {

????// Poseidon配置的線程池

????@Resource(name =?"poseidonThreadPool")

????private?ThreadPoolExecutor poseidonThreadPool;

????public?List<ProductInfo> queryProducts(String orderId)?throws?Exception {

????????// ...

????????// 子任務存在多線程處理,且使用了同一個線程池。

????????Future<ProductInfo> productFuture = poseidonThreadPool.submit(() -> {

????????????// ...

????????});

????????productFuture.get();

????????// ...

????}

}

父子任務使用同一個線程池容易相互影響,線程數達上限時,子任務等待線程資源,而同時,父任務因子任務未完成,其資源得不到釋放,最終可能導致相互等待或死鎖。

4強制在多線程環境下,禁止直接使用HashMap。

正例:

// poseidonThreadPool在Poseidon管理平臺已創建

@Resource(name =?"poseidonThreadPool")

private?ThreadPoolExecutor poseidonThreadPool;

public?void?process() {

?????// ConcurrentHashMap是線程安全的

????Map<String, String> map =?new?ConcurrentHashMap<>();

????CompletableFuture.supplyAsync(() -> {

????????// ...

????????map.put("key1",?"value1");

????????// ...

????}, poseidonThreadPool);

????CompletableFuture.supplyAsync(() -> {

????????// ...

????????map.put("key2",?"value2");

????????// ...

????}, poseidonThreadPool);

}

反例:

// poseidonThreadPool在Poseidon管理平臺已創建

@Resource(name =?"poseidonThreadPool")

private?ThreadPoolExecutor poseidonThreadPool;

public?void?process() {

????// HashMap是線程不安全的

????Map<String, String> map =?new?HashMap<>();

????CompletableFuture.supplyAsync(() -> {

????????// ...

????????map.put("key1",?"value1");

????????// ...

????}, poseidonThreadPool);

????CompletableFuture.supplyAsync(() -> {

????????// ...

???????map.put("key2",?"value2");

????????// ...

????}, poseidonThreadPool);

}

HashMap是線程不安全的,在容量不夠進行resize時,可能因并發出現死鏈,導致CPU飆升。

四、日志

序號

等級

規范

示例

說明

1

強制

日志級別只允許使用ERROR、WARN、INFO、DEBUG。

正例:

// ...

// info打印業務關鍵信息

log.info("操作人id:{}", operatorUserId);

// ...

List<UserData> userDataList = userListService.selectUsers();

// debug打印開發調試信息

log.debug("開始執行時間:{}", System.currentTimeMillis());

userDataList.stream().forEach(userData -> {

????// ...

});

log.debug("結束執行時間:{}", System.currentTimeMillis());

  • ERROR:業務功能受損或無法完成預期操作,可能會造成線上故障需要預警并及時解決,否則該功能將無法正常運行。
  • WARN:異常符合預期的情況且業務不受損,不會出現線上故障,可根據實際情況選擇性預警,解決時效要求不高,但需要關注。
  • INFO:用于記錄系統運行過程或重要信息點,主要為故障定位、過程追溯、數據分析等提供輔助。
  • DEBUG:用于在測試或本地的非生產環境中使用,可以記錄詳細的信息,主要為了方便開發調試程序,在生產環境中禁止使用。
2

強制

業務受損或預期外的異常場景,應當打印ERROR日志。

正例:

try?{

????// ...

????// 發送短信驗證碼

????loginService.sendVerificationCode(cellphone);

????// ...

}?catch?(Exception ex) {

????// 預期外的系統錯誤,業務受損。

????log.error("異常場景:{}, 異常數據:{}",?"用戶H5登錄", userId, ex);

????// 異常處理

}

反例:

try?{

????// ...

????// 發送短信驗證碼

????loginService.sendVerificationCode(cellphone);

????// ...

}?catch?(Exception ex) {

????log.info("異常場景:{}, 異常數據:{}",?"用戶H5登錄", userId, ex);

????// 異常處理

}

ERROR日志用于描述異常不可控的場景,當該類異常發生的時候會給業務和系統帶來傷害,需要第一時間告警并介入排查修復。

3強制業務不受損且預期內的異常場景,應當打印WARN日志。

正例:

public?List<User> selectUserByHeight(Integer height) {

????// ...

????// 該校驗偶發于用戶錄入出錯的情況下,需觀測是否頻繁以指導進一步處理。

????// 如:可能上游系統BUG導致度量單位搞錯

????if?(height >?270) {

????????log.warn("異常場景:{},身高:{} 不能大于270cm",?"用戶H5注冊",? height);

????????// ...

????}

????// ...

}

WARN日志用于描述異常可控的場景,當該類異常發生的時候不會給業務和系統帶來傷害,用于記錄和觀測,指導進一步處理。
4

推薦

打印日志時,建議使用占位符的方式拼裝內容。

正例:

// 用{}填充

log.info("用戶注冊ID:{}", userId);

反例:

// 用+拼接

log.info("用戶注冊ID:"?+ userId);

”+“ 拼接會多次調用StringBuilder的append()方式,每一次append的時候會計算字符串的長度以及重新分配一次內存,對性能有一定的損耗。

此外,“+”拼接方式無論本條日志是否打印都會計算長度和分配內存,而占位符的方式僅在打印的時候才進行內存分配。

5

推薦

打印日志時,不建議使用JSON工具將對象轉換成String。

正例

public?class?UserInfo {

????private?String id;

????public?String getUserName()?throws?Exception {

????????throw?new?Exception();

????}

????@Override

????public?String toString() {

????????return?"id:"?+ id;

????}

}

public?void?doSth (UserInfo user) {

????// ...

???if(user !=?null){

????????// ...

????????log.info("user = {}", user.toString());

????}

????// ...

}

反例:

public?class?UserInfo {

????// ...

????public?String getUserName()?throws?Exception {

????????throw?new?Exception();

????}

}

public?void?doSth(UserInfo user) {

????// 會拋出異常。

????log.info("user = {}", JSON.toJSONString(user));

????// ...

}

如果對象里某些get方法被覆寫,存在拋出異常的風險,進而影響正常業務流程。

6

推薦

異常日志內容中應當包含三要素:異常場景、異常數據、異常堆棧。

正例:

try?{

????// ...

}?catch?(Exception ex) {

????// 日志內容里記錄異常場景、異常數據、異常堆棧信息。

????log.error("異常場景:{}, 異常數據:{}",?"用戶H5登錄", userId, ex);

????// 異常處理

}

反例:

try?{???????

????// ...

}?catch?(Exception ex) {

????// 打印日志不完整,沒有打印異常堆棧信息、異常數據。

????log.error("系統異常");

????// 異常處理

}

異常日志內容應記錄關鍵的信息(異常場景、異常數據、異常堆棧),為問題排查提供有效幫助,能更高效的處理線上故障。

三要素包含:

異常場景:出現異常的業務場景說明。

異常數據:出現異常的數據(比如下單場景,需要記錄商品ID、用戶ID等信息)。

異常堆棧:異常堆棧信息。

五、安全

序號

等級

規范

示例

說明

1強制

用戶敏感數據禁止直接展示、禁止用Get方式提交。

反例:

@Resource

private?UserService userService;

public?BizResponse<List<UserDTO>> getAllUsers() {

????List<User> users = userService.selectAllUsers();

????List<UserDTO> userDTOs =?new?ArrayList<>();

????users.forEach(user -> {

????????UserDTO userDTO =?new?UserDTO();

????????// 手機號碼此處沒有脫敏,直接返回到前端。

????????userDTO.setPhone(user.getPhone());

????????// ...

????????userDTOs.add(userDTO);

????});

????return?BizResponse.success(userDTOs);

}

手機號、銀行卡卡號、身份證、車牌、車架號等都屬于用戶敏感信息,不能直接展示。

脫敏方式:

  • 手機號保留前3位和后4位;
  • 身份證號保留前6位和后3位;
  • 銀行卡前6位和后4位;
  • 車牌將視情況按照保留地區和流水號后2位;
  • 車架號將視情況按照保留后6位;

禁止用Get方式提交,這種方式在URL上帶有敏感數據,將會在wan/lan日志中出現這些元數據。

2強制

用戶輸入的參數,禁止直接拼接到SQL訪問數據庫。

反例:

<!-- Mapper XML -->

<select?id="findUser"?resultType="com.tuhu.mysql.User">

????select * from userInfo where username = ${userName}

</select>

// Mapper接口

public?UserInfo findUser(String userName)

用戶輸入的參數可能帶有SQL片段,存在SQL注入的風險,需要使用參數綁定的技術來防范。

3強制未經許可,禁止外發公司任何程序代碼。

反例:

為了交流學習,將公司代碼上傳至GitHub,以方便各方來閱讀和討論,導致APPID、API等信息泄漏。

程序代碼屬于公司資產,在未經許可的情況下不得以任何方式(郵件、IM軟件、紙質打印等)向外傳輸或公開,包括但不僅限于:

  • 第三方代碼托管平臺(Github、Gitee等)
  • 第三方網盤(百度網盤、阿里網盤等)
  • 第三方網站(CSDN、博客園等)

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

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

相關文章

2025-05-21 Python深度學習5——數據讀取

文章目錄 1 數據準備2 Dataset2.1 自定義 Dataset2.2 使用示例 3 TensorBoard3.1 安裝3.2 標量可視化&#xff08;Scalars&#xff09;3.3 圖像可視化&#xff08;Images&#xff09;3.4 其他常用功能 4 transform4.1 ToTensor()4.2 Normalize()4.3 Resize()4.4 Compose()4.5 C…

5月21日學習筆記

MYSQL三層結構 表1 數據庫DB1 表2 數據庫管理系統 客戶端命令終端&#xff08;Dos&#xff09; DBMS 數據庫DB2 表1 表2 數據庫………. Mysql數據庫-表的本質仍然是文件 表的一行稱之為一條記錄->在java程序中一行記錄往往使用對象表示 SQL語…

二十、面向對象底層邏輯-ServiceRegistry接口設計集成注冊中心

一、服務治理的基石接口 在微服務架構中&#xff0c;服務實例的動態注冊與發現是保證系統彈性的關鍵機制。Spring Cloud Commons模塊通過ServiceRegistry與Registration接口定義了服務注冊的標準化模型&#xff0c;為不同服務發現組件&#xff08;Eureka、Consul、Nacos等&…

DeepSeek:以開源之力,引領AI技術新風潮

在年春節&#xff0c;大語言模型DeepSeek如同一枚震撼彈&#xff0c;在全球范圍內引發了轟動&#xff0c;成功“破圈”&#xff0c;將中國的人工智能&#xff08;AI&#xff09;技術成果推向了世界舞臺。 開源策略&#xff1a;打破技術壁壘 在AI行業&#xff0c;OpenAI等巨頭…

完整改進RIME算法,基于修正多項式微分學習算子Rime-ice增長優化器,完整MATLAB代碼獲取

1 簡介 為了有效地利用霧狀冰生長的物理現象&#xff0c;最近開發了一種優化算法——霧狀優化算法&#xff08;RIME&#xff09;。它模擬硬霧狀和軟霧狀過程&#xff0c;構建硬霧狀穿刺和軟霧狀搜索機制。在本研究中&#xff0c;引入了一種增強版本&#xff0c;稱為修改的RIME…

PyTorch可視化工具——使用Visdom進行深度學習可視化

文章目錄 前置環境Visdom安裝并啟動VisdomVisdom圖形APIVisdom靜態更新API詳解通用參數說明使用示例Visdom動態更新API詳解1. 使用updateappend參數2. ~~使用vis.updateTrace方法~~3. 完整訓練監控示例 Visdom可視化操作散點圖plot.scatter()散點圖案例線性圖vis.line()vis.lin…

Java使用Collections集合工具類

1、Collections 集合工具類 Java 中的 Collections 是一個非常有用的工具類&#xff0c;它提供了許多靜態方法來操作或返回集合。這個類位于 java.util 包中&#xff0c;主要包含對集合進行操作的方法&#xff0c;比如排序、搜索、線程安全化等。 Java集合工具類的使用&#x…

Unity基礎學習(五)Mono中的重要內容(1)延時函數

目錄 一、Mono中的延時函數Invoke 1. Invoke作用&#xff1a;延遲指定時間后執行一次函數。API&#xff1a; 2. InvokeRepeating作用&#xff1a;延遲后開始重復執行函數。API&#xff1a; 3. CancelInvoke作用&#xff1a;停止所有延時函數&#xff0c;或停止指定函數的延時…

180KHz 60V 5A開關電流升壓/升降壓型DC-DC轉換器XL4019升降壓芯片

介紹 XL6019是一款專為升壓、升降壓設計的 單片集成電路&#xff08;升壓和降壓是由外圍電路拓撲確定的&#xff09;&#xff0c;可工作在DC5V到40V輸入電 壓范圍&#xff0c;低紋波&#xff0c;內置功率MOS。XL6019內 置固定頻率振蕩器與頻率補償電路&#xff0c;簡化了電 路…

如何暢通需求收集渠道,獲取用戶反饋?

要暢通需求收集渠道、有效獲取用戶反饋&#xff0c;核心在于多樣化反饋入口、閉環反饋機制、用戶分層管理、反饋數據結構化分析等四個方面。其中&#xff0c;多樣化反饋入口至關重要&#xff0c;不同用戶有不同的溝通偏好&#xff0c;只有覆蓋多個反饋路徑&#xff0c;才能捕捉…

Python結合ollama和stramlit開發聊天機器人

Python結合ollama和stramlit開發聊天機器人 一、環境準備1、streamlit安裝2、langchain安裝3、ollama的安裝 二、Ollama平臺聊天機器人實現1、需求2、模型調用3、前端實現頁面呈現代碼實現 三、詳細代碼地址四、參考資源 一、環境準備 1、streamlit安裝 # 通過 pip 安裝 pip …

java jdbc執行Oracle sql文件

執行代碼 import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.DriverManager;import org.apache.ibatis.jdbc.ScriptRunner;public class ExecSqlFileController {pu…

[Java實戰]Spring Boot整合MinIO:分布式文件存儲與管理實戰(三十)

[Java實戰]Spring Boot整合MinIO&#xff1a;分布式文件存儲與管理實戰&#xff08;三十&#xff09; 一、MinIO簡介與核心原理 MinIO 是一款高性能、開源的分布式對象存儲系統&#xff0c;兼容 Amazon S3 API&#xff0c;適用于存儲圖片、視頻、日志等非結構化數據。其核心特…

開發指南115-CSS中選擇器關系

1、選擇后代 可以用選擇器1 選擇器2&#xff08;中間用空格分隔&#xff09;來表達&#xff0c;也可以在大括號里通過包含關系來表達 舉例 .a .b 舉例.a { .b{} } 注意css本身并不支持嵌套的寫法&#xff0c;是scss等提供的擴展能力。 2、選擇直系后代 選擇器1 > 選擇器2&a…

創建型:抽象工廠模式

目錄 1、核心思想 2、實現方式 2.1 模式結構 2.2 實現案例 3、優缺點分析 4、適用場景 1、核心思想 目的&#xff1a;統一管理相關對象的創建&#xff0c;確保產品兼容性。優先用于需要強約束產品兼容性的場景&#xff08;如UI主題、跨平臺適配&#xff09; 概念&#…

乘最多水的容器 | 算法 | 給定一個整數數組。有n條垂線。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。

在我們日常生活中&#xff0c;蓄水似乎是一個極為樸素的物理行為&#xff1a;兩堵墻之間&#xff0c;注入水&#xff0c;看誰能裝得更多。可如果換個角度&#xff0c;從算法的視角去看這個問題&#xff0c;它會變得怎樣&#xff1f;你是否意識到&#xff0c;這樣一個簡單的問題…

無人機避障——深藍學院浙大Ego-Planner規劃部分

ESDF-free&#xff1a; 被這種類型的障礙物死死卡住的情況&#xff1a; 在一定范圍內建立ESDF&#xff1a; Ego-Planner框架&#xff1a; 找到{p,v} pair&#xff1a; 【注意】&#xff1a;首先根據在障礙物內航跡上的點Q&#xff0c;以及與它相鄰但不在障礙物內的兩個點&#…

零基礎設計模式——大綱匯總

零基礎學設計模式 - 大綱 前言 本教程旨在幫助零基礎的同學快速入門設計模式&#xff0c;理解其核心思想和應用場景。我們將通過清晰的講解和簡單的示例&#xff0c;逐步引導你掌握常用的設計模式。 第一部分&#xff1a;設計模式入門 什么是設計模式&#xff1f; 設計模式…

leetcode 92. Reverse Linked List II

題目描述 92. Reverse Linked List II 是第206題的進階版206. Reverse Linked List 思路很簡單&#xff0c;但一次性通過還是有點難度的。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(n…

CUDA的設備,流處理器(Streams),核,線程塊(threadblock),線程,網格(?gridDim),塊(block)和多gpu設備同步數據概念

CUDA的設備,流處理器&#xff0c;核&#xff0c;線程塊&#xff08;threadblock&#xff09;&#xff0c;線程&#xff0c;網格&#xff08;?gridDim&#xff09;&#xff0c;塊&#xff08;block&#xff09;和多gpu設備同步數據概念 CUDA的設備,流處理器&#xff0c;核&…