面試總結(jié)-Java基礎(chǔ)(一)

我的博客
我的博客:面試總結(jié)-Java基礎(chǔ)(一)

  • 之前學習Java基礎(chǔ)的時候做的一些筆記,稍微整理了一下,也方便以后看。不過這里都是一些較為基礎(chǔ)的Java知識,后期有時間,會針對里面的泛型,多線程,算法,nio 等模塊進行更深入的解析。

  • 如果有寫錯的地方,還望指出,一定及時更正。

基礎(chǔ)

  • 1 switch支持的類型:byte, short, int, char, enum,

    注意:不支持long,double,JDK7之后,開始支持String。

      //簡單示例
      public class MyDemo {
          public static void main(String... args) {
              Demo demo = Demo.A;
              switch (demo) {
                  case A:
                      break;
                  case B:
                      break;
              }
          }
          enum Demo {
              A,
              B,
              C
          }
      }
    
  • 2 if和switch的區(qū)別:

    if :1.對具體的值進行判斷 2.對區(qū)間判斷 3.對運算結(jié)果是boolean類型的表達式進行判斷

    switch :1.對具體的值進行判斷;2.值的個數(shù)通常是固定的。

    對于幾個固定值的判斷,建議使用switch語句,因為switch語句會將具體的答案加載進內(nèi)存,相對高效一點。

  • 重載和重寫的區(qū)別

    • 重載:允許存在一個以上的同名函數(shù),只要它們的參數(shù)類型不同即可。
    • 重寫:當子類繼承父類,沿襲了父類的功能到子類中,子類雖具備該功能,但功能內(nèi)容不一致,這是使用覆蓋特性,保留父類的功能定義,并重寫功能內(nèi)容。
  • 單例模式

    • 餓漢式

        private static Single s = new Single ( ) ;
                private Single ( ) { }  
                public static Single getInstance () 
                {
                return s ;
                }
      
    • 懶漢式

        class Single {
            public static Single getInstance (){
                if ( s== null ){
                    synchronized (Single.class){//鎖不讀可以提高效率
                    if ( s== null ){
                        s = new Single () ;
                     }
                 }
                return s ;
            }
        }
      
  • 特殊關(guān)鍵字:final

      1.    可以修飾類、函數(shù)、變量;
      2.    被final修飾的類不可以被繼承。為了避免被繼承,被子類復寫。final class Demo { }
      3.    被final修飾的方法不可以被復寫。final void show () { }
      4.    被final 修飾的變量是一個常量,只能賦值一次。
      5.    內(nèi)部類定義在類中的局部位置上時,只能訪問該局部被final修飾的局部變量。
    
  • 異常:(關(guān)于問題1,謝謝ylt提醒)

      try{}catch(){}finally{}
      1.在catch中return(),finally{}會不會執(zhí)行?
      答:會,會在return之后執(zhí)行。
      2.finally()在什么情況下不會執(zhí)行
      答:只有一種情況不會執(zhí)行,當執(zhí)行到System.exit(0)時,finally不會執(zhí)行。
    

public class Test {
public static void main(String[] args) {
System.out.println("haha:" + haha(true));
}
private static boolean haha(boolean isTrue) {
try {
int i = 1 / 0;
return isTrue ? System.out.printf("return try !null ", "test") != null : System.out.printf("return try null ", "test") == null;
} catch (Exception e) {
System.out.println("catch");
return isTrue ? System.out.printf("return catch !null ", "test") != null : System.out.printf("return catch null ", "test") == null;
} finally {
System.out.println("");
System.out.println("finally");
}
}
}

```java
//打印結(jié)果:
catch
return catch !null 
finally
haha:true
  • 常見Runtime異常:

      ArithmeticException, ClassCastException, IllegalArgumentException, 
      IndexOutOfBoundsException, NullPointerException, 
    
  • 訪問權(quán)限

權(quán)限.png

Java靜態(tài)代碼塊、構(gòu)造函數(shù)、構(gòu)造代碼塊

  • 先看下面一段代碼,運行Test,會打印什么?

      package test;
      public class Test {
          public static void main(String... args) {
              TestA a;
              a = new TestA();
              a = new TestA();
              TestA aa = new TestA();
          }
      }
      class TestA {
          {
              System.out.println("TestA code create");
          }
          
          private TestB b = new TestB();
          private static TestC c = new TestC();
          
          public TestA() {
              System.out.println("TestA create");
          }
      
          static {
              System.out.println("TestA static create");
          }
      }
      class TestB {
          public TestB() {
              System.out.println("TestB create");
          }
      }
      class TestC {
          public TestC() {
              System.out.println("TestC create");
          }
      }
    

打印結(jié)果:

TestC create
TestA static create
TestA code create
TestB create
TestA create
TestA code create
TestB create
TestA create
TestA code create
TestB create
TestA create
  • static特點:

      1.  隨著類的加載而加載(隨著類的消失而消失,生命周期最長)
      2.  優(yōu)先于對象存在
      3.  被所有對象所共享
      4.  可以直接被類所調(diào)用
      5.  static是一個修飾符,用于修飾成員
    
  • 構(gòu)造代碼塊

      作用:給對象進行初始化,對象一建立就運行,而且優(yōu)先于構(gòu)造函數(shù)執(zhí)行。
      
      和構(gòu)造函數(shù)的區(qū)別:
      構(gòu)造代碼塊是給所有對象進行統(tǒng)一初始化;而構(gòu)造函數(shù)是給對應(yīng)的對象初始化
      構(gòu)造代碼塊中定義的是不同對象共性的初始化內(nèi)容
    
  • 靜態(tài)代碼塊

      static
      {
          靜態(tài)代碼塊中的執(zhí)行語句;
      }
      特點:隨著類的加載而執(zhí)行,只執(zhí)行一次(再new一個對象也不會執(zhí)行,類只加載一次),
      如果定義在有主函數(shù)的類中,則優(yōu)先于主函數(shù)執(zhí)行。用于給類進行初始化。
      有些類不用創(chuàng)建對象,無法用構(gòu)造函數(shù)初始化,就通過靜態(tài)代碼塊初始化。
      
      執(zhí)行順序:靜態(tài)代碼塊先執(zhí)行,如果有對象,構(gòu)造代碼塊先執(zhí)行,然后是構(gòu)造函數(shù)。
      如果沒有對象,則構(gòu)造代碼塊和構(gòu)造函數(shù)都不會執(zhí)行。
    

Java-封裝、繼承、多態(tài)

  • 抽象類的特點:

      1.    抽象方法一定在抽象類中。
      2.    抽象方法和抽象類都必須被abstract關(guān)鍵字修飾。
      3.    抽象類不可以用new創(chuàng)建對象,因為調(diào)用抽象方法沒有意義。
      4.    抽象類中的抽象方法要被使用,必須由子類復寫所有的抽象方法后,建立子類對象調(diào)用。如果子類只覆蓋了部分抽象方法,那么該子類還是一個抽象類。強迫子類復寫,強迫子類做一些事。
      5.    抽象類中可以不定義抽象方法,如果不定義抽象方法,那么抽象類的功能就是為了不讓該類建立對象。
    
  • 抽象關(guān)鍵字不可以和哪些關(guān)鍵字共存?

      答:(1)private不能:抽象方法就是給子類覆蓋的,私有了就不能覆蓋了。
          (2)static不能:static可以直接用類名調(diào)用,而調(diào)用抽象方法沒有意義。
          (3)final 不能:final修飾的方法不可以被復寫,修飾的類不可以被繼承。與abstract沖突。
    
  • 接口的特點

      ●    接口是對外暴露的規(guī)則。
      ●    接口是程序的功能擴展。
      ●    接口可以多實現(xiàn)。
      ●    類與接口直接是實現(xiàn)關(guān)系,而且類可以繼承一個類的同時實現(xiàn)多個接口。
      ●    接口與接口之間可以有繼承關(guān)系,可以多繼承。
           因為接口沒有方法體,不會存在兩個父類出現(xiàn)同一個方法但是方法體不同的情況,
           不會引起沖突,如下:
    
      public class Test implements d{
          public static void main(String... args) {
          }
          
          @Override
          public void as() {
          }
      }
      
      interface d extends e,f {
      }
      interface f{
          void as();
      }
      interface e{
          void as();
      }
    
  • 接口和抽象類的異同點:

      相同點:都是不斷向上抽取而來的。不可以被實例化
      
     不同點:
      1.  抽象類需要被繼承,而且只能單繼承;接口需要被實現(xiàn),而且可以多實現(xiàn)
      2.  抽象類中可以定義抽象方法和非抽象方法,子類繼承后,可以直接使用非抽象方法;
            接口只能定義抽象方法,必須有子類實現(xiàn)。
      3.  抽象類的繼承,是is a關(guān)系,在定義該體系的基本共性內(nèi)容;
            接口的實現(xiàn)是like a 關(guān)系,在定義體系額外功能。
    
  • 繼承

      子類的實例化過程:
      結(jié)論:子類的所有的構(gòu)造函數(shù),默認都會訪問父類中空參數(shù)構(gòu)造函數(shù),因為子類中每一個構(gòu)造函數(shù)內(nèi)的第一行都有一句隱式的super() ;
      當父類中沒有空參數(shù)的構(gòu)造函數(shù)時,子類必須手動通過super或者this語句形式來指定要訪問的構(gòu)造函數(shù)。
      當然:子類的構(gòu)造函數(shù)第一行也可以手動指定this語句來訪問本類中的構(gòu)造函數(shù),
      子類中至少會有一個構(gòu)造函數(shù)會訪問到父類中的構(gòu)造函數(shù)。
    
  • 對象的初始化過程,見下圖:

對象初始化過程.png

打印結(jié)果:

打印結(jié)果.png

線程

  • 關(guān)于線程這塊,后期有時間會寫一個完整的深入的文章,這里寫的都是比較簡單基礎(chǔ)的線程的一些知識。

  • 創(chuàng)建線程的兩種方式:

1 繼承Thread類。
    ①.定義類繼承Thread;
    ②.復寫父類中的方法;目的:將自定義代碼存儲在run方法中,讓線程運行。
    ③.調(diào)用線程的start方法,該方法有兩個作用:啟動線程,調(diào)用run方法
2 實現(xiàn)Runnable接口
    1.  定義類實現(xiàn)Runnable接口。
    2.  覆蓋Runnable接口中的run方法。
    3.  通過Thread類建立線程對象。
    4.  將Runnable接口的子類對象作為實際參數(shù)傳遞給Thread類的構(gòu)造函數(shù)。
    5.  調(diào)用Thread類的start方法開啟線程并調(diào)用Runnable接口子類的run方法。
  • 實現(xiàn)方式和繼承方式有什么區(qū)別?

      1.  實現(xiàn)方式相比繼承方式的好處:
      避免了單繼承的局限性(單繼承只能繼承一個父類)。在定義線程時,建議使用實現(xiàn)方式。
      2.存放代碼的位置不一樣:
      繼承Thread:線程代碼存放Thread子類的run方法中
      實現(xiàn)Runnable,線程代碼存在接口的子類的run方法。
    
  • 實現(xiàn)Runnable接口的好處:

      1,將線程的任務(wù)從線程的子類中分離出來,進行了單獨的封裝。
      按照面向?qū)ο蟮乃枷雽⑷蝿?wù)的封裝成對象。
      
      2,避免了java單繼承的局限性。
    
  • 同步的兩種表現(xiàn)形式:

    • 1 同步代碼塊

      synchronized(對象){
      需要被同步的代碼;
      }

    • 2 同步函數(shù)。

      將synchronized關(guān)鍵字作為修飾符放在函數(shù)上。

      public synchronized void add()

* 同步函數(shù)用的是哪一個鎖:函數(shù)需要被對象調(diào)用,那么該函數(shù)都有一個所屬對象引用,就是this,所以同步函數(shù)使用的鎖是this(對象)

* JDK1.5中提供了多線程升級解決方案,將同步synchronized替換成實現(xiàn)Lock操作,將Object中的wait,notify,notifyAll,替換成了Condition對象的await(),signal(),signalAll(),該對象可以通過Lock鎖進行獲取。
  • 停止線程

      原理:run方法結(jié)束
      1.  使用intrrupt()方法。該方法是結(jié)束線程的凍結(jié)狀態(tài),使線程回到運行狀態(tài)中來。
      當線程處于凍結(jié)狀態(tài),就不會結(jié)束讀取到標記,那么線程就不會結(jié)束。
      當沒有指定的方式讓凍結(jié)的線程恢復到運行狀態(tài)時,這時需要對凍結(jié)進行清除。
      強制讓線程恢復到運行狀態(tài)中來,這樣就可以操作標記讓線程結(jié)束。
    
      2.  定義循環(huán)結(jié)束標記。線程運行代碼一般都是循環(huán),只要控制了循環(huán)即可。
    
  • 線程常見方法

      1 setDeamon() 守護線程:setDaemon(ture) ;
        也稱后臺線程,當前臺線程執(zhí)行時后臺線程也在執(zhí)行,但是當前臺線程全部執(zhí)行完關(guān)閉時,
        后臺線程也會跟著自動關(guān)閉,jvm退出。
        ??!該方法必須在啟動線程前調(diào)用。
      2 join()等待該線程終止:一般用于臨時加入線程。
        當A線程執(zhí)行到了B線程的.join()方法時,A就會等待,等B線程都執(zhí)行完,A才會執(zhí)行
      3 yield()方法:釋放執(zhí)行權(quán),讓其他線程運行。
        暫停當前正在執(zhí)行的線程對象,并執(zhí)行其他線程。
    
  • 一個死鎖的demo

      class Test implements Runnable {
          private boolean flag;
          Test(boolean flag) {
              this.flag = flag;
          }
          public void run() {
      
              if (flag) {
                  while (true)
                      synchronized (MyLock.locka) {
                          System.out.println(Thread.currentThread().getName()
                                  + "..if   locka....");
                          synchronized (MyLock.lockb) {
                              System.out.println(Thread.currentThread().getName()
                                      + "..if   lockb....");
                          }
                      }
              } else {
                  while (true)
                      synchronized (MyLock.lockb) {
                          System.out.println(Thread.currentThread().getName()
                                  + "..else  lockb....");
                          synchronized (MyLock.locka) {
                              System.out.println(Thread.currentThread().getName()
                                      + "..else   locka....");
                          }
                      }
              }
          }
      }
      
      class MyLock {
          public static final Object locka = new Object();
          public static final Object lockb = new Object();
      }
      class DeadLockTest {
          public static void main(String[] args) {
              Test a = new Test(true);
              Test b = new Test(false);
              Thread t1 = new Thread(a);
              Thread t2 = new Thread(b);
              t1.start();
              t2.start();
          }
      }
    
  • wait和sleep的區(qū)別

      1. wait 可以指定時間也可以不指定。sleep必須指定時間。
      2. 在同步中,對CPU的執(zhí)行權(quán)和鎖的處理不同:
          wait:釋放執(zhí)行權(quán),釋放鎖
          sleep:釋放執(zhí)行權(quán),不釋放鎖
    
  • StringBuffer和StringBuilder的區(qū)別

    StringBuffer是線程同步(安全)。如果是單線程,效率就比較低
    StringBuilder是線程不同步。

集合

Java集合關(guān)系圖.png

Collection:單列集合

  • List 和 set

      List:元素是有序的,元素可以重復,因為該集合體系有索引
      Set:元素是無序的,元素不可以重復(存入和取出的順序不一定一致)。
      List特有方法:凡是可以操作角標的方法都是該體系特有的方法
    
  • List中常見的三個子類

      1. ArrayList :底層的數(shù)據(jù)使用的是數(shù)組結(jié)構(gòu)。
      特點:查詢速度很快,但是增刪稍慢。線程不同步,效率高 。
      可變長度數(shù)組,默認容量為10的空列表,如果超過了,則50%的增加
      2. LinkedList :底層的數(shù)據(jù)使用的是鏈表數(shù)據(jù)結(jié)構(gòu)。
      特點:增刪數(shù)度很快,但是查詢稍慢。
      3. Vector:底層使用的是數(shù)組結(jié)構(gòu)。枚舉是Vector特有的取出方式
      是同步的,效率較低,被ArrayList替代。最早出現(xiàn)的。
      默認容量為10的空列表,如果超過了,則100%的增加.
    
  • LinkedList

      JDK1.6版本出現(xiàn)的:pollFirst(),pollLast(),peekFirst() ,peekLast(),offerFirst(),offerLast()
      (如果鏈表為空,返回null )。
      分別替代了remove 和 get 和add (如果鏈表為空,則拋出異常)。
    
  • set常見子類

      1. HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表。
      HashSet是如何保證元素的唯一性的:
      是通過元素的兩個方法,hashCode和equals來完成,如果元素的hashCode值相同,
      才會判斷equals是否為true,如果元素的hashCode值不同,不會調(diào)用equals 。
      開發(fā)時描述事物,需要往集合里面存時,一般都要復寫hashCode和equals。
    
  • TreeSet底層的數(shù)據(jù)結(jié)構(gòu):二叉樹

      保證數(shù)據(jù)元素唯一性的依據(jù)compareTo方法return 0,為0則表示是相同元素 ;
      
      排序的兩種方式:
      TreeSet排序的第一種方式:
      讓元素自身具備比較性。元素需要實現(xiàn)Comparable接口,覆蓋compareTo方法。這種方式也稱為元素的自然順序,或者叫做默認順序。
      
      TreeSet的第二種排序方式:
      當元素自身不具備比較性時,或具備的比較性不是所需要的,這是就需要讓集合自身具備比較性。
      定義一個比較器,將比較器對象作為參數(shù)傳遞給TreeSet集合的構(gòu)造函數(shù)。
      定義一個類,實現(xiàn)Comparator接口,覆蓋compare方法
    
      當兩種排序都存在時,以比較器為主。
    
  • 泛型

      泛型技術(shù)是給編譯器使用的技術(shù),用于編譯時期。確保了類型的安全。
      
      運行時,會將泛型去掉,生成的class文件中是不帶泛型的,這個稱為泛型的擦除。
      為什么擦除呢?因為為了兼容運行的類加載器。
      泛型的補償:在類加載器原有基礎(chǔ)上,編寫一個補償程序。在運行時,通過反射,
      獲取元素的類型進行轉(zhuǎn)換動作。不用使用者在強制轉(zhuǎn)換了。
    

Map:雙列集合

  • 常見子類

      Hashtable:底層是哈希表數(shù)據(jù)結(jié)構(gòu),不可以存入null鍵null值,該集合是線程同步的。jdk1.0 ,效率低 。
      HashMap:底層是哈希表數(shù)據(jù)結(jié)構(gòu),并允許使用null鍵null值,該集合不是同步的,jdk1.2 ,效率高。
      TreeMap :底層是二叉樹數(shù)據(jù)結(jié)構(gòu),線程不同步,可以給map集合中的鍵進行排序 。
      Map 和 Set很像 :其實,Set底層使用了Map集合 。
    
  • map集合的兩種取出方式:

      1.Set<K> KeySet:
      將Map中所有的Key存到了Set集合中,因為Set集合具備迭代器。
      所有可以迭代方式取出所有的鍵,再根據(jù)get方法,獲取每一個鍵對應(yīng)的值
      Map集合的取出原理:將Map集合轉(zhuǎn)成Set集合,再通過迭代器取出
      
      2.Set<Map.Entry<K,V>> 
      entrySet:將Map集合中的映射關(guān)系存入到了Set集合中,而這個關(guān)系的數(shù)據(jù)類型就是:Map.Entry。
      Map.Entry :其實Entry也是一個接口,它是Map接口中的一個內(nèi)部接口。
      先有Map,才有映射關(guān)系,所有Entry類定義在Map內(nèi)部
    
  • Math類:

      double d = Math.ceil(12.56);// 13.0 。ceil返回大于指定整數(shù)的最小整數(shù)
      double d1 =Math.floor(12.34);//12.0 。floor返回小于指定數(shù)據(jù)的最大整數(shù)
      long l = Math.round(12.64);//四舍五入
      double d2 = Math.pow(2,3);//冪運算 :2^3 = 8
    

io

  • 字節(jié)流:InputStream(讀) OutputStream(寫)

  • RandomAccessFile(斷點下載會用到的類):

    隨機訪問文件,自身具備讀寫的方法。
    通過skipBytes(int x),seek(int x)來達到隨機訪問。

    seek(int x):調(diào)整對象中指針,指針跳轉(zhuǎn),可以實現(xiàn)對數(shù)據(jù)指定位置的讀取和寫入。

  • IO流體系:

      字符流:
      Reader
          |--BufferedReader:
              |--LineNumberReader
          |--CharArrayReader
          |--StringReader
          |--InputStreamReaer
              |--FileReader
      
      Writer
          |--BufferedWriter
          |--CharArrayWriter
          |--StringWriter
          |--OutputStreamWriter
              |--FileWriter
          |--PrintWriter
      
      字節(jié)流:
      InputStream
          |--FileInputStream:
          |--FilterInputStream
              |--BufferedInputStream
              |--DataInputStream
          |--ByteArrayInputStream
          |--ObjectInputStream
          |--SequenceInputStream
          |--PipedInputStream
      
      OutputStream
          |--FileOutputStream
          |--FilterOutputStream
              |--BufferedOutputStream
              |--DataOutputStream
          |--ByteArrayOutputStream
          |--ObjectOutputStream
          |--PipedOutputStream
          |--PrintStream
    
  • 示例:讀出C盤下txt文件

      public static void listDemo_2() {
              File dir = new File("c:\\");
              String[] names = dir.list(new SuffixFilter(".txt"));
              for(String name : names){
                  System.out.println(name);
              }
          }
      
      public class SuffixFilter implements FilenameFilter {
          private String suffix ;
          public SuffixFilter(String suffix) {
              super();
              this.suffix = suffix;
          }
          @Override
          public boolean accept(File dir, String name) {
              return name.endsWith(suffix);
          }
      }
    
  • 示例:深度遞歸,讀出制定目錄下的所有文件和文件夾,包括子目錄。

      public class FileTest {
          public static void main(String[] args) {
              File dir = new File("D:\\me\\mime\\RuntimePermissions");
              listAll(dir,0);
          }
          /**
           * 
           * @param dir
           * @param spaceLevel 這個是為了打印結(jié)果好看,與空格有關(guān)的參數(shù)
           */
          public static void listAll(File dir,int spaceLevel) {
              System.out.println(getSpace(spaceLevel)+dir.getName());
              //獲取指定目錄下當前的所有文件夾或者文件對象
              spaceLevel++;
              File[] files = dir.listFiles();
              
              for(int x=0; x<files.length; x++){
                  
                  if(files[x].isDirectory()){
                      listAll(files[x],spaceLevel);
                  }
                  else
                      System.out.println(getSpace(spaceLevel)+files[x].getName());
              }   
          }
          private static String getSpace(int spaceLevel) {
              StringBuilder builder = new StringBuilder();
              builder.append("|--");
              for(int x=0; x<spaceLevel; x++){
                  builder.insert(0,"|  ");
              }
              return builder.toString();
          }
      }
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容