<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          寫不好規(guī)范Java代碼怎么去大廠

          共 11625字,需瀏覽 24分鐘

           ·

          2021-03-15 02:53

          話不多說(shuō)直接上干貨,你我共勉。

          1. 構(gòu)造器參數(shù)太多怎么辦

          解決辦法 :引入Builder模式 場(chǎng)景:當(dāng)構(gòu)造器有5個(gè)或者以上的構(gòu)造參數(shù)時(shí)或者目前參數(shù)不多但是以后會(huì)不斷增多的時(shí)候。demo 如下:

          public class Computer {
              protected String mBoard;
              protected String mDisplay;
              protected String mOs;


              private Computer(Builder builder) {
                  this.mOs = builder.mOs;
                  this.mBoard = builder.mBoard;
                  this.mDisplay = builder.mDisplay;
              }

              @Override
              public String toString() {
                  return "Computer{" +
                          "mBoard='" + mBoard + '\'' +
                          ", mDisplay='" + mDisplay + '\'' +
                          ", mOs='" + mOs + '\'' +
                          '}';
              }


              static class Builder {
                  protected String mBoard;
                  protected String mDisplay;
                  protected String mOs;

                  public Builder setmOs(String mOs) {
                      this.mOs = mOs;
                      return this;
                  }

                  public Builder setmBoard(String mBoard) {
                      this.mBoard = mBoard;
                      return this;
                  }

                  public Builder setmDisplay(String mDisplay) {
                      this.mDisplay = mDisplay;
                      return this;
                  }

                  public Computer build() {
                      return new Computer(this);
                  }
              }
          }

          調(diào)用的時(shí)候如下:

              public static void main(String[] args) {
                  Computer macbook = new Computer.Builder()
                          .setmBoard("board")
                          .setmDisplay("sowhat")
                          .setmOs("Mac")
                          .build();
                  System.out.println(macbook);
              }

          2. 不需要實(shí)例化的類構(gòu)造器要私有化

          經(jīng)常用到的Utils類,比如Java自帶的java.util.Arrays 這樣的類,工具類都盡量不要實(shí)例化。

          public class Arrays {
              private static final int MIN_ARRAY_SORT_GRAN = 8192;
              private static final int INSERTIONSORT_THRESHOLD = 7;
              private Arrays() {
              }
          }

          3. 不要?jiǎng)?chuàng)建不必要對(duì)象

          1. 能用基本類型到時(shí)候盡量要用基本類型。比如我們做數(shù)字運(yùn)算,如果定義稱了個(gè)Long 類型,會(huì)涉及到==自動(dòng)裝箱==。大大耗時(shí)。
          2. 對(duì)于一些程序中共用的參數(shù)盡量設(shè)置為static類型變量。
          3. 對(duì)于一些耗時(shí)性較大的對(duì)象比如數(shù)據(jù)庫(kù)連接,盡量創(chuàng)建數(shù)據(jù)庫(kù)連接池。
          4. 對(duì)于一些占據(jù)內(nèi)存較大的對(duì)象也盡量少創(chuàng)建。因?yàn)樵趀den區(qū)來(lái)回倒騰,它累??!。
          public class Sum {
           public static void main(String[] args) {
            long start = System.currentTimeMillis();
            Long sum = 0L//對(duì)象
            for(long i=0;i<Integer.MAX_VALUE;i++) {
             sum = sum+i;
             //new 20多億的Long的實(shí)例
            }
            System.out.println("spend time:"+(System.currentTimeMillis()-start)+"ms");
           }
          }

          耗時(shí):spend time:7042ms

          public class Sum {
           public static void main(String[] args) {
            long start = System.currentTimeMillis();
            long sum = 0L//基本類型
            for(long i=0;i<Integer.MAX_VALUE;i++) {
             sum = sum+i;
            }
            System.out.println("spend time:"+(System.currentTimeMillis()-start)+"ms");
           }
          }

          耗時(shí):spend time:820ms

          4. 避免使用終結(jié)方法

          1. finalze方法:
          1. finalize()是Object的protected方法,子類可以覆蓋該方法以實(shí)現(xiàn)==資源清理==工作,GC在回收對(duì)象之前調(diào)用該方法。
          2. finalize()與C++中的析構(gòu)函數(shù)不是對(duì)應(yīng)的,但Java中的finalize的調(diào)用具有==不確定性==。
          3. finalize方法在垃圾回收器準(zhǔn)備垃圾回收前被調(diào)用,但是==不一定==會(huì)被調(diào)用 4.finalize()其實(shí)是用來(lái)釋放==不是==通過(guò)java的new關(guān)鍵字分配的內(nèi)存,比如說(shuō)通過(guò)本地方法調(diào)用了c程序,該c程序malloc分配了內(nèi)存,那么垃圾回收器就不能通過(guò)java語(yǔ)言來(lái)釋放內(nèi)存,只能在finalize方法內(nèi)通過(guò)本地方法調(diào)用c程序進(jìn)行釋放內(nèi)存。

          一個(gè)對(duì)象要被回收要經(jīng)過(guò)一次標(biāo)記可達(dá)法已經(jīng)兩次check才算死亡??偨Y(jié)來(lái)說(shuō):finalize()并不是必須要執(zhí)行的,它只能執(zhí)行一次或者0次。如果在finalize中建立對(duì)象關(guān)聯(lián),則當(dāng)前對(duì)象可以復(fù)活一次

          1. System.gc 用System.gc()的時(shí)候,其實(shí)并不會(huì)馬上進(jìn)行垃圾回收,甚至不一定會(huì)執(zhí)行垃圾回收。查看System.gc()的源碼可以看到只有當(dāng)justRanFinalization=true的時(shí)候系統(tǒng)才會(huì)真正GC。如果真要回收查看源碼知道System.gc()要跟System.runFinalization()一起搭配使用才好。

          5. 類跟成員的可訪問(wèn)性最小化

          這個(gè)說(shuō)白了就是設(shè)計(jì)模式中的迪米特法則。定義:要求一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解,所以迪米特法則又叫做最少知識(shí)原則(Least Knowledge Principle, LKP)。

          意義:迪米特法則的意義在于降低類之間的耦合。由于每個(gè)對(duì)象盡量減少對(duì)其他對(duì)象的了解,因此,很容易使得系統(tǒng)的功能模塊功能獨(dú)立,相互之間不存在(或很少有)依賴關(guān)系,日常最常見的比如成員變量私有化。

          6. 使可變性最小化

          盡可能的使用final 來(lái)修飾一些變量,這樣的化線程操作就不需要考慮同步問(wèn)題,同時(shí)也對(duì)于一個(gè)變量不同setX方法也 OK。

          7. 優(yōu)先使用復(fù)合勝過(guò)繼承

          繼承是實(shí)現(xiàn)代碼重用的有力手段,但是使用不當(dāng)會(huì)導(dǎo)致軟件變得脆弱。在包的內(nèi)部使用繼承是非常安全的,子類和超類的實(shí)現(xiàn)都處在同一個(gè)程序員的控制之下。對(duì)于專門為了繼承而設(shè)計(jì)、并且具有很好的文檔說(shuō)明的類來(lái)說(shuō),使用繼承也是非常安全的。然而們對(duì)于進(jìn)行跨越包邊界的繼承,則要非常小心?!袄^承”在這里特指一個(gè)類擴(kuò)展另一個(gè)類。需要我們對(duì)父類十分對(duì)了解才可繼承,只有當(dāng)子類和超類之間==確實(shí)存在==父子關(guān)系時(shí),才可以考慮使用繼承。否則都應(yīng)該用復(fù)合,包裝類不僅比子類更加健壯,而且功能也更加強(qiáng)大。Effective Java

          8.接口優(yōu)于抽象類

          簡(jiǎn)而言之,Java只允許單繼承但是允許實(shí)現(xiàn)多個(gè)接口。通過(guò)接口擴(kuò)充方法很簡(jiǎn)單,這樣也復(fù)合設(shè)計(jì)模式中的開閉原則。接口可以簡(jiǎn)單的理解比抽象類還要抽象的一層,是我們對(duì)外提供的接口。同時(shí)這里提一下==骨架抽象類==。

          骨架類存在的意義是實(shí)現(xiàn)一個(gè)接口中設(shè)計(jì)者認(rèn)為比較公用的方法,然后在具體類實(shí)現(xiàn)的時(shí)候,具體類繼承自骨架類同時(shí)實(shí)現(xiàn)接口類的若干方法。

          HashSet源碼

          public class HashSet<E>
              extends AbstractSet<E>
              implements Set<E>, Cloneablejava.io.Serializable

          看Set源碼

          public interface Set<Eextends Collection<E{
          }

          AbstractSet源碼

          public abstract class AbstractSet<Eextends 
          AbstractCollection<Eimplements Set<E> // 

          AbstractSet抽象類有若干函數(shù)已經(jīng)實(shí)現(xiàn)了。

          HashSet實(shí)現(xiàn)了Set<E>的接口,同時(shí)它還繼承自AbstractSet<E>這個(gè)骨架類(類中有一些公用方法)

          9. 可變參數(shù)謹(jǐn)慎使用

          JDK5增加了可變參數(shù)方法(variable arity method),可變參數(shù)方法接受0個(gè)或多個(gè)指定類型的參數(shù)。可變參數(shù)機(jī)制:先創(chuàng)建一個(gè)數(shù)組,數(shù)組大小為調(diào)用位置所傳遞的參數(shù)數(shù)量,然后將參數(shù)值傳遞到數(shù)組中,最后將數(shù)組傳遞給方法。弊端如下:

          1.如果所傳參數(shù)為null,方法里有對(duì)參數(shù)的引用(比如 args[0])時(shí),那么就會(huì)在運(yùn)行時(shí)失?。ň幾g時(shí)卻檢測(cè)不出錯(cuò)誤);2.在對(duì)性能有要求時(shí),我們要慎重考慮是否使用可變參數(shù)。因?yàn)?,可變參?shù)方法的調(diào)用都會(huì)引起array的內(nèi)存分配和初始化,這會(huì)給性能帶來(lái)?yè)p耗。3. 當(dāng)可變參數(shù)的使用發(fā)生變動(dòng)時(shí)(比如:以前用可變參數(shù)方法,現(xiàn)在用普通方法),所有引用參數(shù)列表的類的.class都要重新生成,因?yàn)榭勺儏?shù)的array的分配和初始化是在編譯期間完成的。

          Effective Java給我們的建議是:假設(shè)調(diào)用可變參數(shù)的方法中,有95%只是調(diào)用參數(shù)個(gè)數(shù)小于4,那么就可以將個(gè)數(shù)小于4的方法,用普通方法定義;剩余的5%,調(diào)用可變參數(shù)方法。

          public void foo() {}
          public void foo(int a1) {}
          public void foo(int a1, int a2) {}
          public void foo(int a1, int a2, int a3) {}
          public void foo(int a1, int a2, int a3, int... rest) {}

          10. 盡量不要返回NULL,盡量返回零數(shù)組或集合

          函數(shù)中如果返回NULL,那么代碼還要去重新的判斷返回值。JDK都主動(dòng)給我們提供好了Collections.EMPTY_LIST。當(dāng)然如果是對(duì)象就只能是NULL了。阿里巴巴開發(fā)手冊(cè)也是這樣建議的哦。

          1.返回值為null并不會(huì)有什么問(wèn)題,但是在“解引用”(dereference)時(shí),調(diào)用者沒(méi)有對(duì)null進(jìn)行判斷就會(huì)出現(xiàn)NullPointerException。2. 在返回值為數(shù)組或者集合時(shí),盡量返回長(zhǎng)度為零的數(shù)組或者集合,而不是null,這樣在調(diào)用時(shí)就能簡(jiǎn)化代碼,減少不必要的麻煩,并且不必?fù)?dān)心NullPointer異常(除非這對(duì)性能會(huì)造成很大的影響)。

          11.優(yōu)先使用標(biāo)準(zhǔn)異常

          總結(jié)來(lái)說(shuō)好處就是:追求代碼的重用考慮,在裝載類的性能上面考慮。具體細(xì)節(jié)如下:

          1. 它使你對(duì)官方API更加易于學(xué)習(xí)和使用,因?yàn)樗c程序員已經(jīng)熟悉的習(xí)慣用法是一致的。
          2. 對(duì)于用到這些API的程序而言,他們的可讀性會(huì)更好,因?yàn)樗麄儾粫?huì)出現(xiàn)很多程序員不熟悉的異常。
          3. 異常類越少,意味著內(nèi)存印跡就越小,裝載這些類的時(shí)間開銷也越少。

          12.盡量使用枚舉替換int

          枚舉的本質(zhì)就是一個(gè)類的具體實(shí)例。枚舉比普通業(yè)務(wù)類型int類型的區(qū)別跟好處,以及策略枚舉的使用,這些以前寫給直接看==>花樣玩枚舉

          13. 局部變量作用域最小化

          1. 從系統(tǒng)GC的角度考慮(一個(gè)變量的周期越短整個(gè)gc過(guò)程越快)。2.從棧楨中的局部變量表的可重用性來(lái)看,作用域越小系統(tǒng)的棧楨空間利用了越大。
          2. 可以增強(qiáng)代碼的可讀性和可維護(hù)性,并降低出錯(cuò)的可能性。

          應(yīng)該:

          1. 在第一次使用某個(gè)局部變量的地方進(jìn)行聲明。
          2. 如果你還沒(méi)有足夠的前置信息來(lái)對(duì)一個(gè)變量進(jìn)行有意義的初始化,就應(yīng)該推遲這個(gè)聲明,直到可以初始化為止。
          3. 盡量將方法小而集中。方法的功能盡量單一。

          14. 對(duì)于精度技術(shù)不用float或double

          Java在允許float或者double類之間計(jì)算的時(shí)候會(huì)有誤差。

          double a = 0.2;
          double b = 0.1;
          double c = a+ b;
          System.out.println(c);
          -----
          0.30000000000000004

          要用:BigDecimal 或者FloatDecimal。具體類用法自行百度。

          15.字符串操作少用String

          這點(diǎn)操作是大家都知道的,String定義為private final byte[] value;是不可變的。StringBuilder 和 StringBuffer都繼承于:AbstractStringBuilder他們的底層使用的是沒(méi)有用final修飾的字符數(shù)組:char[]

          在這里插入圖片描述

          1.如果要操作少量的數(shù)據(jù)用 String;
          2. 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuffer;
          3. 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) StringBuilder。

          16.對(duì)資源的close建議分開操作

          比如說(shuō)我們有這樣的一個(gè)close方法,

          try{
           a.close()
           b.close()
          }catch(Exception e){
           ...
          }

          上面這樣寫一旦a關(guān)閉的時(shí)候出錯(cuò)了,b的關(guān)閉也會(huì)出錯(cuò)。盡量分開來(lái)關(guān)閉。

          try{
           a.close()
          }catch(Exception e){
           ...
          }

          try{
           b.close()
          }catch(Exception e){
           ...
          }

          17. 數(shù)據(jù)類型轉(zhuǎn)換

          基本數(shù)據(jù)類型轉(zhuǎn)換為String的時(shí)候注意性能優(yōu)化,比如Integer類型數(shù)據(jù)轉(zhuǎn)換為String一般有三種方法

          1. Integer.toString方法,首先推薦。速度最好
          2. String.valueOf() ,該方法底層調(diào)用的是Integer.toString方法,速度中等。
          3. i + "" 這種方法,底層是用StringBuilder實(shí)現(xiàn),先用append方法拼接,再用toString方法獲取字符串。速度最慢。

          18. 不用的對(duì)象記得置NULL

          我們不用一個(gè)空間對(duì)象后而沒(méi)有將其置NULL,JDK底層代碼對(duì)用不到的對(duì)象都會(huì)立馬置空,如果不這樣容易造成內(nèi)存泄露,比如我自己實(shí)現(xiàn)了一個(gè)棧

          public class Stack {
           
           public  Object[] elements;
           private int size = 0//指示器,用來(lái)指示當(dāng)前棧頂?shù)奈恢?/span>

              private static final int Cap = 16;

              public Stack() {
               elements = new Object[Cap];
              }
              //入棧
              public void push(Object e){
               elements[size] = e;
               size++;
              }
              //出棧
              public Object pop(){
               size = size-1;
               Object object = elements[size];
               elements[size] = null//  這里很重要 JDK底層都是這樣實(shí)現(xiàn)的,不用了,即使置NULL
                  return object;
              }
          }

          19. if判斷常量在前

          if(i==1)if(1==i)看起來(lái)沒(méi)有差別,但是從容錯(cuò)性上面來(lái)考慮,如果手誤寫成了if(i=1)就是賦值語(yǔ)句了,而if(1=i)則不會(huì)出現(xiàn)這樣的錯(cuò)誤。因此if判斷建議常量在前,變量在后。

          20. 字符串變量比較的時(shí)候

          str.equal("sowhat")“sowhat”.equal(str)功能上看是一樣的,但是從代碼的健壯性來(lái)看推薦后者,因?yàn)槟銦o(wú)法確實(shí)str 一定是非空,可以避免空指針異常。

          21. 同步方法跟同步方法塊

          盡量使用同步方法塊而不是同步方法,這點(diǎn)在多線程模塊中的synchronized鎖 方法塊文章中已經(jīng)講得很清楚了,除非我們能確定一整個(gè)方法都是需要進(jìn)行同步的,否則盡量使用同步代碼塊,避免對(duì)那些不需要進(jìn)行同步的代碼也進(jìn)行了同步,影響了代碼執(zhí)行效率。

          22.方法要盡可能小

          一個(gè)方法要盡量實(shí)現(xiàn)單一指責(zé),方法編譯后字節(jié)碼越小越可能會(huì)引發(fā)JIT的方法內(nèi)聯(lián),

          public void SetAge(int age){
             this.age = age
          }
          -------JIT 優(yōu)化后直接就是 如下,避免類方法調(diào)用。
          this.age = age 

          23.一定記得寫注釋

          代碼寫的再好也要記得寫類跟方法的大概注釋,不然接收你工作的人絕對(duì)分分鐘化身祖安玩家!

          參考

          阿里Java編碼規(guī)范

          Builder模式

          finalize跟gc

          深入理解String

          推薦閱讀:

          Nginx的這個(gè)默認(rèn)配置,差點(diǎn)讓我的職場(chǎng)生涯折戟沉沙

          一個(gè)空格引發(fā)的“慘案“

          “坑爹”排行榜:Java語(yǔ)言最違反常識(shí)的功能點(diǎn)TOP 10

          Redis 高可用篇:你管這叫主從架構(gòu)數(shù)據(jù)同步原理?

          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色逼资源站 | 亚洲操逼在线 | 在线亚洲免费视频二 | 久久亚洲AV成人影视 | 亚洲免费欧洲 |