Java基礎(chǔ)

  • 數(shù)據(jù)類(lèi)型:
類(lèi)型 大小 取值范圍
byte 1字節(jié) -128~127 (10000000~01111111) [-2^7 ~ 2^7-1]
short 2字節(jié) -3276832767(100...011...) [-215~215-1]
int 4字節(jié) 根據(jù)以上規(guī)律可推出(正好超過(guò)20億族阅,無(wú)法表示全球人數(shù))
float 4字節(jié) 根據(jù)以上規(guī)律可推出
long 8字節(jié) 根據(jù)以上規(guī)律可推出(足夠表示全球人數(shù))
double 8字節(jié) 根據(jù)以上規(guī)律可推出
char 2字節(jié) java采用Unicode,2個(gè)字節(jié)(16位)來(lái)表示一個(gè)字符
boolean 未知 true 、false
  • 二進(jìn)制
    原碼:普通二進(jìn)制數(shù),第一位(8位)表示符號(hào)(1為負(fù)旅东,0為正), 其余位表示值,eg:110十艾。
    正數(shù)情況:原碼 = 反碼 = 補(bǔ)碼
    負(fù)數(shù)情況:
    反碼:將原碼按位取反得到的值成為原碼的反碼抵代,eg:001。
    補(bǔ)碼:將反碼+1忘嫉,eg:010荤牍。
    1.二進(jìn)制轉(zhuǎn)十進(jìn)制的通用方法eg:
    11101->12^4+123+1*22+02^1+12^0
    2.正數(shù)二進(jìn)制轉(zhuǎn)十進(jìn)制(位1比較多情況)eg:
    01110 ---取反得到反碼--->10001
    ---加1得到補(bǔ)碼---->10010
    ---0比較多直接用通用方法-->-1*2^4 + 2 = -14
    ----取絕對(duì)值--------->14
    3.負(fù)數(shù)二進(jìn)制轉(zhuǎn)十進(jìn)制(位1比較多情況,負(fù)數(shù)二進(jìn)制是補(bǔ)碼形式)eg:
    11110(補(bǔ)碼)---減1得到反碼---->11101(反碼)
    ---取反得到原碼---->00010(原碼)
    ---0比較多直接用通用方法-->2
    ---取相反值------>-2

  • 浮點(diǎn)數(shù)值不適用于出現(xiàn)舍入誤差的金融計(jì)算中庆冕。eg:
    命令System.out.println(2.0-1.1) 得到的結(jié)果并不是想象中的0.9而是0.8999999999999.
    原因是浮點(diǎn)數(shù)采用二進(jìn)制表示康吵,無(wú)法精確表示分?jǐn)?shù)1/10就像十進(jìn)制無(wú)法精確表示分?jǐn)?shù)1/3一樣.
    如果需要在數(shù)值計(jì)算中保證精確的話,應(yīng)使用BigDecimal類(lèi).
    4.&访递、~的特殊用法:

    與.png

    亦或.png

    亦或.png

  • Unicode編碼表示為十六進(jìn)制其范圍從\u0000 到 \uffff晦嵌。eg: \u03c0表示希臘字母π。

  • 短路與拷姿、短路或 &&惭载、|| 都是在第一個(gè)表達(dá)式如果能夠確定值后就沒(méi)必要執(zhí)行第二個(gè)表達(dá)式了。

  • StringBuilder 適用單線程响巢、StringBuffer允許多線程

  • 數(shù)組拷貝 Arrays.copyOf()

  • 兩個(gè)相等的對(duì)象hashCode值一定相等
    Equals與hashCode方法的定義必須一致:如果x.equals(y)返回true描滔,那么x的hashCode()就必須與y的hashCode()相等。
    eg:如果用定義的Employee.equals比較員工的ID抵乓,那么hashCode()就需要散列ID伴挚,而不是員工的姓名或存儲(chǔ)地址靶衍。

  • 對(duì)象克隆
    默認(rèn)情況下是淺拷貝灾炭,也就是只拷貝普通成員變量和不可變的子對(duì)象(如String),它并不會(huì)拷貝其他可變對(duì)象颅眶。要想拷貝其他可變對(duì)象蜈出,
    則需要實(shí)現(xiàn)深拷貝,即重寫(xiě)clone()方法涛酗。具體實(shí)現(xiàn)如下:
    對(duì)于員工類(lèi):public class Employee implements Cloneable{//必須實(shí)現(xiàn)Cloneable接口
    private String name;
    private double salary;
    private Date hireDay;

                     public void Employee(String name,double salary,Date hireDay){
                          this.name = name;
                          this.salary = salary;
                          this.hireDay = hireDay;
                     }
    
                     public Employee clone() throws CloneNotSupportedException{
                          Employee cloned = (Employee)super.clone();//克隆了成員變量(salary)和String(name)
                          cloned.hireDay = (Date)this.hireDay.clone();//克隆對(duì)象
                          return cloned;
                     }
                  }
          調(diào)用方法如下:
                          Employee employee = new Employee("neo",10000.0,new Date());
                          Employee cloned = employee.clone();
                          這樣employee 和 cloned 對(duì)象就互不相干了铡原。
    
  • 反射 -- 一切都是對(duì)象,類(lèi)也是對(duì)象商叹,而類(lèi)是Class類(lèi)的實(shí)例對(duì)象(類(lèi)類(lèi)型)
    ArrayList list = new ArrayList();

      ArrayList<String> list1 = new ArrayList<String>();
      list1.add("hello");
      //list1.add(20);錯(cuò)誤的
      Class c1 = list.getClass();
      Class c2 = list1.getClass();
      System.out.println(c1 == c2);
      //反射的操作都是編譯之后的操作
      
      /*
       * c1==c2結(jié)果返回true說(shuō)明編譯之后集合的泛型是去泛型化的
       * Java中集合的泛型燕刻,是防止錯(cuò)誤輸入的,只在編譯階段有效剖笙,
       * 繞過(guò)編譯就無(wú)效了
       * 驗(yàn)證:我們可以通過(guò)方法的反射來(lái)操作卵洗,繞過(guò)編譯
       */
      try {
          Method m = c2.getMethod("add", Object.class);
          m.invoke(list1, 20);//繞過(guò)編譯操作就繞過(guò)了泛型
          System.out.println(list1.size());//輸出2
          System.out.println(list1);//輸出[hello,2]
          /*for (String string : list1) {
              System.out.println(string);
          }*///現(xiàn)在不能這樣遍歷
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    
  • 代理

        --為某個(gè)對(duì)象提供一個(gè)代理,以控制對(duì)這個(gè)對(duì)象的訪問(wèn)(代理類(lèi)負(fù)責(zé)請(qǐng)求的預(yù)處理弥咪、過(guò)濾过蹂、將請(qǐng)求分派給委托類(lèi)處理十绑、以及委托類(lèi)執(zhí)行完請(qǐng)求后的后續(xù)處理)。分為以下兩類(lèi):
    
          靜態(tài)代理:在程序運(yùn)行前就已經(jīng)存在代理類(lèi)的字節(jié)碼文件酷勺,代理類(lèi)和委托類(lèi)的關(guān)系在運(yùn)行前就確定了本橙。
          實(shí)現(xiàn)靜態(tài)代理的步驟:
            1.創(chuàng)建業(yè)務(wù)邏輯方法的接口
            2.代理類(lèi)和委托類(lèi)都實(shí)現(xiàn)該接口
            3.代理類(lèi)擁有委托類(lèi)的對(duì)象并通過(guò)構(gòu)造方法傳進(jìn)來(lái)引用
            4.代理類(lèi)調(diào)用業(yè)務(wù)方法,可在方法前進(jìn)行過(guò)濾脆诉,方法結(jié)束后進(jìn)行處理
          動(dòng)態(tài)代理:代理類(lèi)的源碼是在運(yùn)行期間通過(guò)反射生成的甚亭,代理類(lèi)和委托類(lèi)的關(guān)系是在程序運(yùn)行時(shí)確定。
          實(shí)現(xiàn)動(dòng)態(tài)代理的步驟:
            1.創(chuàng)建一個(gè)實(shí)現(xiàn)InvocationHandler接口的類(lèi)库说,并實(shí)現(xiàn)invoke方法:
               public class TimeHandler implements InvocationHandler {
                  private Object target;
                  public TimeHandler(Object target) {
                           super();
                           this.target = target;
                       }             
                  /*
                   * proxy  被代理對(duì)象
                   * method  被代理對(duì)象的方法
                   * args 方法的參數(shù)
                   * 返回值:Object  方法的返回值
                   * */
                    @Override
                   public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
                          long starttime = System.currentTimeMillis();
                          System.out.println("汽車(chē)開(kāi)始行駛....");
                          Object methodReturnType = method.invoke(target,args);
                          long endtime = System.currentTimeMillis();
                          System.out.println("汽車(chē)結(jié)束行駛....  汽車(chē)行駛時(shí)間:" + (endtime - starttime) + "毫秒狂鞋!");
                          return methodReturnType;
                       }
                    }
    
            2.創(chuàng)建被代理的類(lèi)及接口:
              public interface Moveable {
                     void move();
              }
              public class Car implements Moveable {
                      @Override
                      public void move() {
                            //實(shí)現(xiàn)開(kāi)車(chē)
                          try {
                                Thread.sleep(new Random().nextInt(1000));
                                System.out.println("汽車(chē)行駛中....");
                            } catch (InterruptedException e) {
                              e.printStackTrace();
                           }
                    }
               }
            3.創(chuàng)建代理類(lèi):Proxy.newProxyInstance(ClassLoader classLoader,Class[] interfaces, InvocationHandler h);//classLoader為null,表示使用默認(rèn)的類(lèi)加載器潜的。   
                    Car car = new Car();//代理對(duì)象骚揍,委托類(lèi)
                    InvocationHandler h = new TimeHandler(car);
                    Class<?> cls = car.getClass();
                    /**
                     * loader  類(lèi)加載器
                     * interfaces  實(shí)現(xiàn)接口
                     * h InvocationHandler
                     */
                    Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h);
            4.通過(guò)代理調(diào)用方法:
                    m.move();
    
              Object sysIActivityManager = mInstanceField.get(gDefaultFieldObj);//系統(tǒng)的IActivityManager
              Class<?> iActivityManagerProxy = Class.forName("android.app.IActivityManager");//代理對(duì)象
              Object proxy = Proxy.newProxyInstance(sysIActivityManager.getClass().getClassLoader(),new Class[]{iActivityManagerProxy}, new MyHandler(sysIActivityManager));
    
  • 異常
    異常分為RuntimeException(由程序錯(cuò)誤導(dǎo)致的異常) 和 IOException(程序本身沒(méi)問(wèn)題,IO錯(cuò)誤)啰挪。

  • Hashmap
    1.默認(rèn)大小capacity=16 默認(rèn)加載因子loadFactory=0.75信不,默認(rèn)情況下,當(dāng)buckets桶的數(shù)量
    大于 capacity * loadFactory=12(即桶的數(shù)量為13時(shí))亡呵,進(jìn)行resize抽活,將capacity擴(kuò)大到原來(lái)的2倍。
    2.當(dāng)我們?cè)跇?gòu)造方法中傳一個(gè)大小后锰什,Hashmap會(huì)取大于參數(shù)大小的最小的2的次冪作為capacity下硕。
    比如我傳一個(gè)15,則capacity=16.
    原因:如果我們不以2的次冪作為capacity的話汁胆,比如capacity=15梭姓,當(dāng)我們進(jìn)行put操作時(shí),源碼如下:


    put操作部分源碼.png

    上面的tab.length 其實(shí)就是capacity嫩码,index 就是得到table的索引誉尖,hash是經(jīng)過(guò)hash()函數(shù)處理的hash值
    當(dāng)hash=8時(shí):
    index = 0100&1110(15-1的二進(jìn)制)=0100
    當(dāng)hash=9時(shí):
    index = 0101&1110(15-1的二進(jìn)制)=0100
    我們發(fā)現(xiàn),出現(xiàn)了hash碰撞铸题,并且索引為9的數(shù)組(table[9])是無(wú)法存數(shù)據(jù)的(因?yàn)槿?時(shí)被映射到了8)铡恕,
    而且不僅僅是索引為9無(wú)數(shù)據(jù),而且只要是第四位為1(0001,0101,0111,1001,1101,1111等等)都無(wú)法存數(shù)據(jù)丢间,造成了一半的空間浪費(fèi)探熔。
    當(dāng)capacity是2的次冪如16:
    當(dāng)hash=8時(shí):
    index = 0100&1111(16-1的二進(jìn)制)=0100
    當(dāng)hash=9時(shí):
    index = 0101&1111(16-1的二進(jìn)制)=0101
    這樣就避免了空間的浪費(fèi)以及減少hash碰撞。

  • ArrayList
    ArrayList 默認(rèn)大小為10烘挫,每次擴(kuò)容為原來(lái)大小的1.5倍
    HashSet底層就是HashMap(數(shù)組加鏈表)诀艰、TreeSet底層就是TreeMap(紅黑樹(shù))

  • Math
    Math.ceil()用作向上取整。 Math.floor()用作向下取整。 Math.round() 我們數(shù)學(xué)中常用到的四舍五入取整
    Math.round(11.5)的返回值是12涡驮,Math.round(-11.5)的返回值是-11暗甥。四舍五入的原理是在參數(shù)上加0.5然后進(jìn)行下取整

Paste_Image.png
  • String
    1 String str = "hello";
    str = str + "world";
    這兩句話會(huì)造成內(nèi)存泄漏;因?yàn)镾tring是不可變對(duì)象捉捅,所以在內(nèi)存中同時(shí)存在hello對(duì)象 和 helloworld對(duì)象撤防,
    但str引用指向的是helloworld對(duì)象,導(dǎo)致hello對(duì)象沒(méi)有被引用棒口,而且一直存在常量池中寄月,從而導(dǎo)致內(nèi)存泄漏
    解決方案:StringBuilder
    2 String str = "hello "+"world "+"are you ok?";
    這句話會(huì)創(chuàng)建一個(gè)對(duì)象,因?yàn)镴VM在編譯階段就確定了str的值為helloworldare you ok?
    編譯階段還會(huì)進(jìn)行宏替換eg:
    final int len = 10;
    String str = "java 的長(zhǎng)度為 "+len;
    以上也只會(huì)創(chuàng)建一個(gè)對(duì)象

  • 表達(dá)式

       short s = 5; s = s - 2;上述代碼會(huì)編譯出錯(cuò)无牵,因?yàn)?是int 漾肮,s-2也是int,不能直接賦給s茎毁。
      但是 short s = 5; s-=2;上述代碼不會(huì)出錯(cuò)克懊,因?yàn)閟-=2 等價(jià)于s = (short)(s-2)
      String str = "java.com.neo.lala";
      String[] split = str.split(".");//這樣得不到想要的結(jié)果(改為str.split("\\."))
      因?yàn)閟plit方法的參數(shù)是正則表達(dá)式,而"."是匹配任何字符七蜘,所以需要轉(zhuǎn)義
    
  • 樹(shù)

       每個(gè)內(nèi)部節(jié)點(diǎn)均為 m 度的有序樹(shù),稱(chēng)作 m 叉樹(shù)
      由 n 個(gè)節(jié)點(diǎn)構(gòu)成的二叉樹(shù),高度至少為?log2n?
      不含 1 度節(jié)點(diǎn)的二叉樹(shù),稱(chēng)作真二叉樹(shù)(Proper bina ry tree ),否則稱(chēng)作非真二叉樹(shù) (Improper binary tree)谭溉。
    
  • 簡(jiǎn)單工廠模式(最少知識(shí)原則)

    提供創(chuàng)建對(duì)象的功能,不需要關(guān)心具體的實(shí)現(xiàn)
    使用場(chǎng)景:創(chuàng)建對(duì)象
    好處:降低模塊之間的耦合度
      public class Factory {
          public static Api create(int type){
              switch (type) {
              case 1:
                  return new ImplA();
              case 2:
                  return new ImplB();
              case 3:
                  return new ImplC(); 
              default:
                  return new ImplC();
              }
          }
          public <T extends Api> T creatProduct(Class<T> clz)
          {
              Api  api=null;
              try {
                  api=(Api) Class.forName(clz.getName()).newInstance();
              } catch (InstantiationException | IllegalAccessException
                      | ClassNotFoundException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
              return (T)api;
          }   
      }
    
  • 工廠方法模式(抽象工廠模式)

    需求:導(dǎo)出數(shù)據(jù)(數(shù)據(jù)庫(kù)文件橡卤、文本文件)
    把對(duì)象的實(shí)現(xiàn)延遲到子類(lèi)完成
    Android使用場(chǎng)景:Activity生命周期(在子類(lèi)加載具體的布局)扮念、MediaPlayer的創(chuàng)建、ArrayList的迭代器
    public interface IFactory {//抽象工廠
        IApi createApi();
    }
      public class AndroidFactory implements IFactory{//具體工廠
          @Override
          public IApi createApi() {
              return new AndroidApi();
          }
      }
      public class IOSFactory implements IFactory{//具體工廠
          @Override
          public IApi createApi() {
              return new IOSApi();
          }
      }
    使用:IFactory factory=new IOSFactory();
         factory.createApi();
    
  • 單例模式

    枚舉(天生支持反序列化):
      1 枚舉中的屬性必須放在最前面 
      2. 枚舉中可以和java類(lèi)一樣定義方法
      3. 枚舉中的構(gòu)造方法必須是私有的
      public  enum EnumManager {
          SDCardManager(10){
              @Override
              public EnumManager getSingle() {
                  return SDCardManager;
              }   
          },
          HttpManager(1) {
              @Override
              public EnumManager getSingle() {
                  return null;
              }
          };
          public SdCardImpl getSingleton()
          {
              return new SdCardImpl();
          }
          public abstract EnumManager getSingle();
          private  EnumManager(int type){
      
          }
      }
      EnumManager.SDCardManager.getSingleton();  
     DCL(Double Check Lock)存在的問(wèn)題:
           public class DoubleCheckedLock {  
          private static DoubleCheckedLock instance;         
          public static DoubleCheckedLock getInstance() {    
              if (instance == null) {  //step1  
                  synchronized (DoubleCheckedLock.class) { //step2  
                      if(instance==null){ //step3  
                          instance=new DoubleCheckedLock(); //step4  
                      }  
                  }  
              }    
              return instance;    
          }    
      }  
         Jdk5 以后支持處理器亂序執(zhí)行 匯編指令(為了優(yōu)化)
        導(dǎo)致 指向地址和實(shí)例化堆區(qū) 順序不同碧库,eg:
        step4這一步分為兩步(正常是先a后b柜与、某些平臺(tái)編譯器會(huì)優(yōu)化導(dǎo)致先b后a):
              a實(shí)例化DoubleCheckedLock堆區(qū)順序不一樣
              b.instance 指向堆區(qū)地址 
       (優(yōu)化情況先b后a) 比如線程A執(zhí)行到step4的b處時(shí)(此時(shí)instance不為空),cpu讓線程B執(zhí)行嵌灰,當(dāng)?shù)絪tep1的時(shí)候發(fā)現(xiàn)instance不為空弄匕,就直接返回。
        但事實(shí)上線程B得到的instance是沒(méi)有實(shí)例化完成的導(dǎo)致錯(cuò)誤
    
  • 建造者模式

    核心思想:構(gòu)造方法私有伞鲫,在Builder的構(gòu)造方法里面初始化該類(lèi)使用內(nèi)部類(lèi)(保持和房子(目標(biāo)對(duì)象)一樣的參數(shù))來(lái)建造
      public class Room {
          private String window;  
          private String floor;
          private String doorl;
          private String  chat;
          public void apply(WorkBuilder.RoomParmas parmas)
          {
              window=parmas.window;
              floor=parmas.floor;
              doorl=parmas.door;
              chat=parmas.chat;
          }
      }
      public class WorkBuilder{
          private RoomParmas parmas;
          public WorkBuilder( ) {
              this.parmas = new RoomParmas();
          }
          public  WorkBuilder makeWindow(String window ) {
              parmas.window=window;
              return this;
          }
          public WorkBuilder makeFloor(String floorCorlor) {
              parmas.floor=floorCorlor;
              return this;
          }
          public WorkBuilder makeDoor(String door) {
              parmas.door=door;
              return this;
          }
          public Room makeChat(String  chat) {
              parmas.chat=chat;
              return this;
          }
          public Room build() {
              Room room=new Room();
              room.apply(parmas);
              return room;
          }
          class RoomParmas{
              public  String window;  
              public String floor;
              public String door;
              public String  chat;
              
          }
      }
    
  • 原型模式

    原型模式就是拷貝原型創(chuàng)建新對(duì)象(深拷貝)
    目的:保護(hù)最原始的那一份存檔粘茄。隱藏復(fù)制過(guò)程
      使用場(chǎng)景:類(lèi)初始化需要消耗很多資源签舞、new 一個(gè)對(duì)象需要很多數(shù)據(jù)準(zhǔn)備或訪問(wèn)權(quán)限秕脓、
      一個(gè)對(duì)象需要提供給其他對(duì)象使用,但是可能會(huì)改變?cè)偷闹?  項(xiàng)目中登錄后保存session保存用戶(hù)的登錄信息儒搭、這些用戶(hù)信息在其他地方用來(lái)做
      登錄校驗(yàn)吠架,信息顯示等。但是這些信息在其他地方是不允許修改的
      public User getLoginUser(){
        return loginUser.clone();/返回深拷貝
      }
    
      優(yōu)點(diǎn):原型模式是在內(nèi)存中二進(jìn)制流的拷貝搂鲫,要比直接new一個(gè)對(duì)象性能好很多傍药,特別是在循環(huán)體內(nèi)產(chǎn)生大量對(duì)象時(shí),原型模式可以更好的體現(xiàn)優(yōu)點(diǎn)
      缺點(diǎn):直接在內(nèi)存中拷貝,是不會(huì)調(diào)用其構(gòu)造函數(shù)的拐辽。(注意<鹋病!)
    
  • 策略模式

      設(shè)置某一個(gè)策略就會(huì)擁有相應(yīng)的功能(有一個(gè)上下文對(duì)象來(lái)設(shè)置某一個(gè)策略)
      eg:Android 中的插值器
      代碼中有大量if else 就可以考慮策略模式
      public class Context {  
           private IStrategy strategy;  
           //構(gòu)造函數(shù)俱诸,要你使用哪個(gè)策略 
           public Context(IStrategy strategy){  
                this.strategy = strategy;  
           }  
           public void setStrategy(IStrategy strategy){  
                this.strategy = strategy;  
           }  
           public void operate(){  
                this.strategy.operate();  
           }  
      } 
      public class FirstStrategy implements IStrategy {  
           @Override  
           public void operate() {  
                System.out.println("first");  
           }  
      }  
      public class SecondStrategy implements IStrategy {  
           @Override  
           public void operate() {  
                System.out.println("second");  
           }  
      }  
    
  • 狀態(tài)模式

   和策略模式結(jié)構(gòu)一樣菠劝,但是行為跟狀態(tài)有關(guān)(有一個(gè)上下文對(duì)象來(lái)控制具體的狀態(tài))
    eg:電視遙控器在開(kāi)機(jī)狀態(tài) 的各種操作(調(diào)音量、換頻道)才有效睁搭,在關(guān)機(jī)狀態(tài)無(wú)效
    實(shí)用場(chǎng)景:用戶(hù)登錄狀態(tài)和未登錄狀態(tài)會(huì)有不一樣的響應(yīng)8险铩!T奥妗L蚧尽(非常實(shí)用)
    public class PowerOn  implements TVState{
        @Override
        public void nextChannel() {
            System.out.println("下一頻道");
        }
        @Override
        public void preChannel() {
            System.out.println("上一頻道");
        }
        @Override
        public void turnOn() {
            System.out.println("正在開(kāi)機(jī)");
        }
        @Override
        public void turnOff() {
            System.out.println("關(guān)機(jī)");
        }
    }
    public class PowerOff implements TVState{
        @Override
        public void nextChannel() {}
        @Override
        public void preChannel() {}
        @Override
        public void turnOn() {
            System.out.println("開(kāi)機(jī)");
        }
        @Override
        public void turnOff() {}
    }
    public class TvContext {
        private TVState tvState=new PowerOff();
        public void setTate(TVState tvState){
            this.tvState=tvState;
        }
        public void turnOn(){
            setTate(new PowerOn());
            tvState.turnOn();
        }
        public void turnOff(){
            setTate(new PowerOff());
            tvState.turnOff();
        }
        public void nextChannel(){
            tvState.nextChannel();
        }
        public void preChannel() {
            tvState.preChannel();
        }
    }
  • 責(zé)任鏈模式

      當(dāng)前處理者必須持有下一個(gè)處理者的引用
      使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接受者之前的耦合關(guān)系锌唾。將這些對(duì)象連成一條鏈锄码,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理它為止
      在安卓中的應(yīng)用:事件傳遞機(jī)制晌涕、有序廣播
      
      優(yōu)點(diǎn):請(qǐng)求者和處理者關(guān)系解耦      缺點(diǎn):需要遍歷處理者巍耗,太多影響性能
    
  • 命令模式

    底層業(yè)務(wù)邏輯代碼用接口進(jìn)行隔離eg:登錄時(shí)只關(guān)心登錄成功和失敗、登錄具體邏輯應(yīng)該使用接口隔離
    客戶(hù)端只是想要發(fā)出命令或者請(qǐng)求渐排,不關(guān)心請(qǐng)求的真正接收者是誰(shuí)炬太,也不關(guān)心具體如何實(shí)現(xiàn)
    
  • 模板方法模式

    定義一個(gè)操作中的算法框架,而將一些步驟延遲到子類(lèi)中驯耻,使得子類(lèi)不改變算法的結(jié)構(gòu)即可重復(fù)定義算法的某些特點(diǎn)步驟
    
  • 觀察者模式

    被觀察者一般會(huì)有一個(gè)列表來(lái)保存觀察者的引用亲族,并且提供增加和刪除的方法,通知的時(shí)候會(huì)遍歷這個(gè)列表可缚,回調(diào)所有的觀察者的方法
    
  • 內(nèi)存分配

       了解內(nèi)存分配的幾種策略:
        1.靜態(tài)的
          靜態(tài)的存儲(chǔ)區(qū):內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好霎迫,這塊的內(nèi)存在程序整個(gè)運(yùn)行期間都一直存在。
          它主要存放靜態(tài)數(shù)據(jù)帘靡、全局的static數(shù)據(jù)和一些常量知给。
      
      2.棧式的
          在執(zhí)行函數(shù)(方法)時(shí),函數(shù)一些內(nèi)部變量的存儲(chǔ)都可以放在棧上面創(chuàng)建描姚,函數(shù)執(zhí)行結(jié)束的時(shí)候這些存儲(chǔ)單元就會(huì)自動(dòng)被釋放掉涩赢。
          棧內(nèi)存包括分配的運(yùn)算速度很快,因?yàn)閮?nèi)置在處理器的里面的轩勘。當(dāng)然容量有限筒扒。
      3.堆式的
          也叫做動(dòng)態(tài)內(nèi)存分配。有時(shí)候可以用malloc或者new來(lái)申請(qǐng)分配一個(gè)內(nèi)存绊寻。在C/C++可能需要自己負(fù)責(zé)釋放(java里面直接依賴(lài)GC機(jī)制)花墩。
          在C/C++這里是可以自己掌控內(nèi)存的悬秉,需要有很高的素養(yǎng)來(lái)解決內(nèi)存的問(wèn)題。java在這一塊貌似程序員沒(méi)有很好的方法自己去解決垃圾內(nèi)存冰蘑,需要的是編程的時(shí)候就要注意自己良好的編程習(xí)慣和泌。
          
      區(qū)別:堆是不連續(xù)的內(nèi)存區(qū)域,堆空間比較靈活也特別大祠肥。
          棧式一塊連續(xù)的內(nèi)存區(qū)域允跑,大小是有操作系統(tǒng)覺(jué)決定的。
      
      堆管理很麻煩搪柑,頻繁地new/remove會(huì)造成大量的內(nèi)存碎片聋丝,這樣就會(huì)慢慢導(dǎo)致效率低下。
      對(duì)于棧的話工碾,他先進(jìn)后出弱睦,進(jìn)出完全不會(huì)產(chǎn)生碎片入录,運(yùn)行效率高且穩(wěn)定温赔。
      public class Main{
          int a = 1;//堆內(nèi)存
          Student s = new Student();//堆內(nèi)存
          public void XXX(){
              int b = 1;//棧里面
              Student s2 = new Student();//s2一開(kāi)始是在常量池里面,后面才壓棧
          }
      
      }
      
      1.成員變量全部存儲(chǔ)在堆中(包括基本數(shù)據(jù)類(lèi)型健无,引用及引用的對(duì)象實(shí)體)---因?yàn)樗麄儗儆陬?lèi)旬迹,類(lèi)對(duì)象最終還是要被new出來(lái)的火惊。
      2.局部變量的基本數(shù)據(jù)類(lèi)型和引用存儲(chǔ)于棧當(dāng)中,引用的對(duì)象實(shí)體存儲(chǔ)在堆中奔垦。-----因?yàn)樗麄儗儆诜椒ó?dāng)中的變量屹耐,生命周期會(huì)隨著方法一起結(jié)束。
      
      我們所討論內(nèi)存泄露椿猎,主要討論堆內(nèi)存惶岭,他存放的就是引用指向的對(duì)象實(shí)體。
    
  • 線程

    Java語(yǔ)言自己可以創(chuàng)建兩種進(jìn)程“用戶(hù)線程”和“守護(hù)線程(Daemon)”
      用戶(hù)線程:就是我們平時(shí)創(chuàng)建的普通線程
      守護(hù)線程:主要是用來(lái)服務(wù)用戶(hù)線程.
      7该摺0丛睢!當(dāng)線程只剩下守護(hù)線程的時(shí)候筐咧,JVM就會(huì)退出.但是如果還有其他的任意一個(gè)用戶(hù)線程還在鸯旁,JVM就不會(huì)退出
    將線程轉(zhuǎn)換為守護(hù)線程可以通過(guò)調(diào)用Thread對(duì)象的setDaemon(true)方法來(lái)實(shí)現(xiàn)。在使用守護(hù)線程時(shí)需要注意一下幾點(diǎn):
    (1) thread.setDaemon(true)必須在thread.start()之前設(shè)置量蕊,否則會(huì)跑出一個(gè)IllegalThreadStateException異常铺罢。你不能把正在運(yùn)行的常規(guī)線程設(shè)置為守護(hù)線程。 
    (2) 在Daemon線程中產(chǎn)生的新線程也是Daemon的危融。
    (3) 守護(hù)線程應(yīng)該永遠(yuǎn)不去訪問(wèn)固有資源畏铆,如文件雷袋、數(shù)據(jù)庫(kù)吉殃,因?yàn)樗鼤?huì)在任何時(shí)候甚至在一個(gè)操作的中間發(fā)生中斷
    
    synchronized鎖代碼塊鎖的對(duì)象是同一個(gè)才會(huì)鎖住eg:
     void method(String str){
      synchronized(str){
          ...
      }
      }
      method("xxx");
      method(new String("xxx"));
      上面兩個(gè)方法同時(shí)執(zhí)行時(shí)代碼塊是不會(huì)被鎖住的辞居,因?yàn)閮蓚€(gè)str雖然內(nèi)容相同但是不是同一個(gè)對(duì)象。解決方法(字符串入池):
       synchronized(str.intern()){}
    
  • do{...}while(false)

    do{
      ...
      if (somethingIsWrong) break;
      //more code
      ...  
      }while(false);
  • volatile

    在線程中訪問(wèn)變量的時(shí)候蛋勺,為了提高效率瓦灶,會(huì)在線程中的私有空間中緩存這個(gè)變量。所以多個(gè)線程訪問(wèn)同一個(gè)變量的時(shí)候抱完,會(huì)在各自線程的私有空間中緩存贼陶,對(duì)變量的修改是對(duì)這個(gè)緩存進(jìn)行操作的。
    但是從緩存更新到主存是需要時(shí)間的巧娱,所以多個(gè)線程對(duì)同一個(gè)變量進(jìn)行操作這個(gè)變量的值就是不可靠的碉怔,使用volatile關(guān)鍵字,就會(huì)使得緩存的值會(huì)立即更新到主存禁添,使得變量可見(jiàn)撮胧!
    
  • 生產(chǎn)者消費(fèi)者

public class ThreadTest1 {

//產(chǎn)品
static class ProductObject{
    //線程操作變量可見(jiàn)
    public volatile static String value;
}

//生產(chǎn)者線程
static class Producer extends Thread{
    Object lock;
    
    public Producer(Object lock) {
        this.lock = lock;
    }
    
    @Override
    public void run() {
        //不斷生產(chǎn)產(chǎn)品
        while(true){
            synchronized (lock) { //互斥鎖
                //產(chǎn)品還沒(méi)有被消費(fèi),等待
                if(ProductObject.value != null){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //產(chǎn)品已經(jīng)消費(fèi)完成老翘,生產(chǎn)新的產(chǎn)品
                ProductObject.value = "NO:"+System.currentTimeMillis();
                System.out.println("生產(chǎn)產(chǎn)品:"+ProductObject.value);
                lock.notify(); //生產(chǎn)完成芹啥,通知消費(fèi)者消費(fèi)
            }
        }
        
    }
}

//消費(fèi)者線程
static class Consumer extends Thread{
    Object lock;
    public Consumer(Object lock) {
        this.lock = lock;
    }
    
    @Override
    public void run() {
        while(true){
            synchronized (lock) {
                //沒(méi)有產(chǎn)品可以消費(fèi)
                if(ProductObject.value == null){
                    //等待,阻塞
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("消費(fèi)產(chǎn)品:"+ProductObject.value);
                ProductObject.value = null;
                lock.notify(); //消費(fèi)完成铺峭,通知生產(chǎn)者墓怀,繼續(xù)生產(chǎn)
            }
        }
    }
}


public static void main(String[] args) {
    Object lock = new Object();
    
    new Producer(lock).start();
    
    new Consumer(lock).start();
}
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市卫键,隨后出現(xiàn)的幾起案子傀履,更是在濱河造成了極大的恐慌,老刑警劉巖莉炉,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啤呼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡呢袱,警方通過(guò)查閱死者的電腦和手機(jī)官扣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)羞福,“玉大人惕蹄,你說(shuō)我怎么就攤上這事≈巫ǎ” “怎么了卖陵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)张峰。 經(jīng)常有香客問(wèn)我泪蔫,道長(zhǎng),這世上最難降的妖魔是什么喘批? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任撩荣,我火速辦了婚禮铣揉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘餐曹。我一直安慰自己逛拱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布台猴。 她就那樣靜靜地躺著朽合,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饱狂。 梳的紋絲不亂的頭發(fā)上曹步,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音休讳,去河邊找鬼箭窜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛衍腥,可吹牛的內(nèi)容都是我干的磺樱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼婆咸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼竹捉!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起尚骄,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤块差,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后倔丈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體憨闰,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年需五,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹉动。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宏邮,死狀恐怖泽示,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜜氨,我是刑警寧澤械筛,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站飒炎,受9級(jí)特大地震影響埋哟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜郎汪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一赤赊、第九天 我趴在偏房一處隱蔽的房頂上張望闯狱。 院中可真熱鬧,春花似錦砍鸠、人聲如沸扩氢。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朦肘,卻和暖如春饭弓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背媒抠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工弟断, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人趴生。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓阀趴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親苍匆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子刘急,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Win7下如何打開(kāi)DOS控制臺(tái)? a:開(kāi)始--所有程序--附件--命令提示符 b:開(kāi)始--搜索程序和文件--cmd...
    逍遙嘆6閱讀 1,587評(píng)論 4 12
  • 常量的概述和使用 A:什么是常量在程序執(zhí)行的過(guò)程中其值不可以發(fā)生改變 B:Java中常量的分類(lèi)字面值常量自定義常量...
    野望君閱讀 610評(píng)論 0 0
  • 在經(jīng)過(guò)一次沒(méi)有準(zhǔn)備的面試后浸踩,發(fā)現(xiàn)自己雖然寫(xiě)了兩年的android代碼叔汁,基礎(chǔ)知識(shí)卻忘的差不多了。這是程序員的大忌检碗,沒(méi)...
    猿來(lái)如癡閱讀 2,829評(píng)論 3 10
  • [TOC] StringBuffer類(lèi) StringBuffer類(lèi)概述及其構(gòu)造方法 StringBuffer類(lèi)概述...
    lutianfei閱讀 461評(píng)論 0 1
  • 1据块、一個(gè)".java"源文件中是否可以包括多個(gè)類(lèi)(不是內(nèi)部類(lèi))?有什么限制折剃?答:可以有多個(gè)類(lèi)另假,但只能有一個(gè)publ...
    岳小川閱讀 908評(píng)論 0 2