溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java開發(fā)常用規(guī)范技巧有哪些

發(fā)布時間:2021-12-22 14:22:28 來源:億速云 閱讀:113 作者:iii 欄目:編程語言

本篇內(nèi)容主要講解“Java開發(fā)常用規(guī)范技巧有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java開發(fā)常用規(guī)范技巧有哪些”吧!

1、Object 的 equals 方法容易拋空指針異常。

從源碼來進(jìn)行分析equals方法是屬于Object類的,如果調(diào)用方為null,那么自然在運行的時候會拋出空指針異常的情況。

object類中的源碼:

從源碼來進(jìn)行分析equals方法是屬于Object類的,如果調(diào)用方為null,那么自然在運行的時候會拋出空指針異常的情況。

object類中的源碼:

    public boolean equals(Object obj) {

        return (this == obj);

    }

為了避免這種現(xiàn)況出現(xiàn),在比對的時候盡量將常量或者有確定值的對象置前。

例如說:

正確:“test”.equals(object);

錯誤:object.equals(“test”);

 2、類的命名使用駝峰式命名的規(guī)范。

例如:UserService,但是以下情景例外:DO / BO / PO / DTO / VO。

例如說:UserPO,StudentPO(PO,VO,DTO,等這類名詞需要全大寫)

@Data

@Builder

public class CustomBodyDTO {

    private String name;

    private String idCode;

    private String status;

}

  1. 如果在模塊或者接口,類,方法中使用了設(shè)計模式,那么請在命名的時候體現(xiàn)出來。例如說:TokenFactory,LoginProxy等。

public class TokenFactory {

    public TokenDTO buildToken(LoginInfo loginInfo) {

        String token = UUID.randomUUID().toString();

        TokenDTO tokenDTO = TokenDTO.builder()

                .token(token)

                .createTime(LocalDateTime.now())

                .build();

        String redisKey = RedisKeyBuilder.buildTokenKey(token);

        redisService.setObject(redisKey, loginInfo, Timeout.ONE_DAY * 30 * 2);

        log.info("創(chuàng)建token成功|loginInfo={}", loginInfo.toString());

        return tokenDTO;

    }

}

4、對于所有相同類型的包裝類進(jìn)行比較的時候,都是用equal來進(jìn)行操作。

對于Integer類來說,當(dāng)相應(yīng)的變量數(shù)值范圍在-128到127之間的時候,該對象會被存儲在IntegerCache.cache里面,因此會有對象復(fù)用的情況發(fā)生。

所以對于包裝類進(jìn)行比較的時候,最好統(tǒng)一使用equal方法。

private static class IntegerCache {

        static final int low = -128;

        static final int high;

        static final Integer cache[];

        static {

            // high value may be configured by property

            int h = 127;

            String integerCacheHighPropValue =

                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

            if (integerCacheHighPropValue != null) {

                try {

                    int i = parseInt(integerCacheHighPropValue);

                    i = Math.max(i, 127);

                    // Maximum array size is Integer.MAX_VALUE

                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);

                } catch( NumberFormatException nfe) {

                    // If the property cannot be parsed into an int, ignore it.

                }

            }

            high = h;

            cache = new Integer[(high - low) + 1];

            int j = low;

            for(int k = 0; k < cache.length; k++)

                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)

            assert IntegerCache.high >= 127;

        }

        private IntegerCache() {}

    }

  public static Integer valueOf(int i) {

        if (i >= IntegerCache.low && i <= IntegerCache.high)

            return IntegerCache.cache[i + (-IntegerCache.low)];

        return new Integer(i);

}

5、所有的pojo類中的屬性最好統(tǒng)一使用包裝類屬性類型數(shù)據(jù)。RPC方法的返回值和參數(shù)都統(tǒng)一使用包裝類數(shù)據(jù)。局部變量中使用基本的數(shù)據(jù)類型。

對于實際的應(yīng)用場景來說,例如說一個學(xué)生類,當(dāng)我們設(shè)置里面的成績字段為int類型的時候,如果學(xué)生沒有考試,那么這個成績字段應(yīng)該為空,但是int默認(rèn)會賦值為0,那么這個時候使用基本數(shù)據(jù)類型就容易產(chǎn)生誤區(qū),到底是考了0分,還是說沒有參加考試。

如果換成使用包裝類Integer類型的話,就可以通過null值來進(jìn)行區(qū)分了。

6、當(dāng)pojo類在進(jìn)行編寫的時候要重寫相應(yīng)的toString方法,如果該pojo中繼承了另外的一個pojo類,那么請在相應(yīng)的tostring函數(shù)中加入super.toString()方法。

通過重寫toString方法有利于在日志輸出的時候查看相應(yīng)對象的屬性內(nèi)容進(jìn)行逐一分析,對于一些有繼承關(guān)系的對象而言,加入了super.toString方法更加有助于對該對象的理解和分析。

7、在pojo的getter和setter方法里面,不要增加業(yè)務(wù)邏輯的代碼編寫,這樣會增加問題排查的難度。

正確做法:

public class User {

    private Integer id;

    private String username;

    public Integer getId() {

        return id;

    }

    public User setId(Integer id) {

        this.id = id;

        return this;

    }

    public String getUsername() {

        return username;

    }

    public User setUsername(String username) {

        this.username = username;

        return this;

    }

}

8、final 可以聲明類、成員變量、方法、以及本地變量。

下列情況使用 final 關(guān)鍵字:

不允許被繼承的類,如:String 類。

不允許修改引用的域?qū)ο?,如:POJO 類的域變量。

不允許被重寫的方法,如:POJO 類的 setter 方法。

不允許運行過程中重新賦值的局部變量。

避免上下文重復(fù)使用一個變量,使用 final 描述可以強(qiáng)制重新定義一個變量,方便更好地進(jìn)行重構(gòu)。

9、對于任何類而言,只要重寫了equals就必須重寫hashcode。

舉例說明:

1)HashSet在存儲數(shù)據(jù)的時候是存儲不重復(fù)對象的,這些對象在進(jìn)行判斷的時候需要依賴hashcode和equals方法,因此需要重寫。

2)在自定義對象作為key鍵時,需要重寫hashcode和equals方法,例如說String類就比較適合用于做key來使用。

10、不要在 foreach 循環(huán)里進(jìn)行元素的 remove/add 操作。

remove 元素請使用 Iterator方式,如果并發(fā)操作,需要對 Iterator 對象加鎖。

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

while (iterator.hasNext()) {

String item = iterator.next();

if (刪除元素的條件) {

iterator.remove();

}

}

11、使用HashMap的時候,可以指定集合的初始化大小。

例如說,HashMap里面需要存放10000個元素,但是由于沒有進(jìn)行初始化大小操作,所以在添加元素的時候,hashmap的內(nèi)部會一直在進(jìn)行擴(kuò)容操作,影響性能。

那么為了減少擴(kuò)容操作,可以在初始化的時候?qū)ashmap的大小設(shè)置為:已知需要存儲的大小/負(fù)載因子(0.75)+1

HashMap hashMap=new HashMap<>(13334);

12、Map類集合中,K/V對于null類型存儲的情況:

集合名稱

key

value

說明

HashMap

允許為null

允許為null

線程不安全

TreeMap

不允許為null

允許為null

線程不安全

HashTable

不允許為null

不允許為null

線程安全

ConcurrentHashMap

不允許為null

不允許為null

線程安全

13、可以利用 Set 元素唯一的特性,可以快速對一個集合進(jìn)行去重操作,避免使用 List 的contains 方法進(jìn)行遍歷、對比、去重操作。

通關(guān)觀察可以發(fā)現(xiàn),HashSet底層通過將傳入的值再傳入到一個HashMap里面去進(jìn)行操作,進(jìn)入到HashMap里面之后,會先通過調(diào)用該對象的hashcode來判斷是否有重復(fù)的值,如果有再進(jìn)行equals判斷,如果沒有相同元素則插入處理。

   public boolean add(E e) {

        return map.put(e, PRESENT)==null;

    }

14、線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運行規(guī)則,規(guī)避資源耗盡的風(fēng)險。

錯誤做法:

ExecutorService executors = Executors.newSingleThreadExecutor();

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

對于線程池的參數(shù)需要有深入的理解后,結(jié)合實際的機(jī)器參數(shù)來進(jìn)行參數(shù)設(shè)置,從而防止在使用中出現(xiàn)異常。

ExecutorService fixedExecutorService = new ThreadPoolExecutor(

                1,

                2,

                60,

                TimeUnit.SECONDS,

                 linkedBlockingQueue,

                new MyThreadFactory(),

                new ThreadPoolExecutor.AbortPolicy()

        );

ps:使用Executors.new方式創(chuàng)建線程池的缺點:

對于FixedThreadPool 和 SingleThreadPool而言

允許的請求隊列長度為 Integer.MAX_VALUE,可能會堆積大量的請求,從而導(dǎo)致 OOM。

對于CachedThreadPool 和 ScheduledThreadPool而言

允許的創(chuàng)建線程數(shù)量為 Integer.MAX_VALUE,可能會創(chuàng)建大量的線程,從而導(dǎo)致 OOM。

到此,相信大家對“Java開發(fā)常用規(guī)范技巧有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI