# Java 面試考題 > 2018.1.10 AndyLee <style> .align-right { text-align: right; } .align-center { text-align: center; color: blue; } </style> ## Arrays跟ArrayList的差異? * Arrays可包含原始(primitive)及物件(object),ArrayList只允許物件 * Arrays大小固定,ArrayList可以動態調整 * ArrayList提供較多方法,如removeAll、iterator ## a == b 以及 a.equals(b)有何差異?(重要) * a == b只有在兩者**指向記憶體中同一個stack對象**時才會為真 * a.equals(b)則是==邏輯比較==,例如String.equals()可用來比較兩個不同物件所含的相同字串內容 ## sleep()跟wait()的差異? * ==sleep()是使線程停止一段時間的方法==。在sleep 時間間隔期滿後,線程不一定立即恢復執行。這是因為在那個時刻,其他線程可能正在運行而且沒有被設定為放棄執行,除非(a)“醒來”的線程具有更高的優先順序 (b)正在運行的線程因為其他原因而阻塞。 * wait()是線程交互時,如果線程對一個同步物件x 發出一個wait()調用,該線程會暫停執行,被調物件進入等待狀態,直到被喚醒或等待時間到。 * Sleep()無法由其他thread喚起,wait()可以。 ![](https://i1.wp.com/www.lightblue.asia/wp-content/uploads/2016/11/JavaThreadLifeCycle.png?w=855&ssl=1) ## 說明stack跟heap? * stack: 可被預測生命週期的**變數**或函數資訊都放在stack,例如**區域變數(local variable)**、**函式參數(function/method parameter)**、**函數的返回位址**(function/method return address)等資訊 * heap: 動態配置的記憶體空間,放置被new出來的物件以及內含的成員變數及方法 >一般來說stack爆掉是因為有太多區域變數或recursive function跑太深,heap爆掉則是GC沒有做好物件無法被回收 ## String & StringBuilder & StringBuffer 區別與性能比較? * **String:** 字符串常量,字符串長度不可變。 * 如果你要改變string對象的字符或者是拼接字符的話,系統就會新建一個string,然後把原來string的對象指向新的string。舊的string就等著被回收,==所以你每次操作string的時候就會出現很多垃圾對象,效率不高== * **StringBuffer:** StringBuffer的長度是可變的 * 每次操作的時候都是對同一個stringBuffer進行操作的,如果要拼接字符的話,同它提供的append方法就行了。 * ==這是一個線程安全對象。它的長度會根據你要存放的字符串來動態改變,涉及到先申請一個大小== * 如果想轉成String類型,可以調用StringBuffer的toString()方法。 * **StringBuilder:** 是java5.0的新對象,長度也是可變的,和stringBuffer類似。==特殊之處是它不是線程安全的,好處是效率比stringBuffer要高==,兩者的方法基本相同 #### 使用策略: 1. 基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。 2. 不要使用String類的”+“來進行頻繁的拼接,因為那樣的性能極差的,應該使用StringBuffer或StringBuilder類,這在Java的優化上是一條比較重要的原則。 3. 相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。 原文網址:https://read01.com/x85KyJ.html ## 陣列有沒有length()這個方法? String有沒有length()這個方法? 陣列僅有length的屬性,String有length()方法。 ## 談談final, finally, finalize的區別? * final是修飾的關鍵字,可修飾類別、方法 和變數。 * final class該類別無法被繼承,final method 該方法不能被override,final variable 該變數一經設定後就無法修改。 * finally 在例外處理中(try…catch….finally)最後一定會被執行的區塊。 * finalize當garbage collector發現某物件已經不被任何物件所參考(reference) 會呼叫該物件的finalize(),finalize()內沒有什特別的動作一般會被OVERRIDE拿來作為資源的釋放。 ## HashMap和HashTable的區別? * Hashtable 是thread safe class,HashMap不是。 * HashMap 接受 null, 而 Hashtable 不接受。 ## String s = new String("xyz");創建了幾個String Object? 兩個 : 一個是“xyx”,一個是指向“xyx”的引用物件s。 ## 以下程式碼有什麼錯? ```javascript= short s1 = 1; s1 = s1 + 1; short s1 = 1; s1 += 1; ``` S1 +1會回傳int,int不能指定給short; S1 += 1 沒錯。 ## List, Set, Map是否繼承自Collection介面? List和Set是 ,Map不是 ![](https://i.imgur.com/Uu9Fa0Z.png) ## Abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized? 不可,abstract method不可包含private, final, static, native, synchronized等關鍵字 ## try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被執行,什麼時候被執行,在return前還是後? 會在return前執行。 ## 用最有效率的方法算出2乘以8等於幾? 2<<3 ## Swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? Switch(exp),exp為整數運算式,故僅有int、 short、 char 或者 byte可以作用。 ## Collection 和 Collections的區別? * Collections是個java.util下的**class**,它包含有各種有關集合操作的靜態方法。 * Collection是個java.util下的**interface**,它是各種集合結構的父介面。 ![](http://incdn1.b0.upaiyun.com/2014/06/647d134fddb1872cf1f5a8facbb41557.jpeg) ## 說明一下public static void main(String args[])里每個關鍵字的作用? * **public:** main方法是Java程序運行時調用的第一個方法,因此它必須對Java環境可見。所以可見性設置為pulic. * **static:** Java平台調用這個方法時不會創建這個類的一個實例,因此這個方法必須聲明為static。 * **void:** main方法沒有返回值。 * **String** 是命令行傳進參數的類型,**args**是指命令行傳進的字符串數組。 原文網址:https://kknews.cc/zh-tw/other/6e3vjl.html ## 在System.out.println()裡面,System, out, println分別是什麼? System是系統提供的預定義的final類,out是一個PrintStream對象,println是out對象裡面一個重載的方法。 ## What is difference between Thread vs Process in Java ? 1. Both process and Thread are independent path of execution but one process can have multiple Threads. 2. Every process has its own memory space, executable code and a unique **process identifier (PID)** while every thread has its own stack in Java but it uses process main memory and share it with other threads. 3. Threads are also refereed as **task** or **light weight process (LWP)** in operating system 4. Threads from same process can communicate with each other by using Programming language construct like [wait and notify in Java](http://javarevisited.blogspot.sg/2011/05/wait-notify-and-notifyall-in-java.html) and much simpler than inter process communication (IPC). 5. It's easy to create Thread as compared to Process which requires duplication of parent process. 6. ==All Threads which is part of same process share system resource== like file descriptors , [Heap Memory](http://javarevisited.blogspot.de/2011/05/java-heap-space-memory-size-jvm.html) and other resource but each Thread has its own Exception handler and own stack in Java. ## Thread 類中的start() 和run() 方法有什麼區別? start()方法被用來啟動新創建的線程,而且start()內部調用了run()方法,這和直接調用run()方法的效果不一樣。 當你調用run()方法的時候,只會是在原來的線程中調用,沒有新的線程啟動,start()方法才會啟動新線程。更多討論請[點擊這裡](http://javarevisited.blogspot.sg/2012/03/difference-between-start-and-run-method.html) ## Java 變數與記憶體 ## ![](https://1.bp.blogspot.com/-Ct8x3H1i0O8/UzF3zlQpjFI/AAAAAAAABYM/lGNrHBsgZ-g/s1600/java-memory.jpg) Java 的變數依照其存活時間長短分成下列四種 : ### **1\. 類別變數 (Class Variables):** 又稱為靜態變數, 因為它必須在類別成員區宣告為 static (也只能在類別成員區有 static), 例如 : > static int count=0; 其特性如下 : static variables 一開始就被載入記憶體,並且放在靜態區,給了它不一樣的特性: - 存活時間最長, 編譯時即配置記憶體存放於 **global 區 (即靜態區, 靜態方法也在此區)**, 程式執行期間均可存取. - 靜態變數在任何該類別的物件被建立(常用 new)之前就已經被初始化 - **有預設值,** 如果沒有給訂初值, 編譯器也會給予預設值如下: ![](https://1.bp.blogspot.com/-QyOZIJ2SqZI/Uy609pL2nTI/AAAAAAAABXg/w_FKjiG6yi8/s1600/java_tpyes_defaults.jpg) #### 來個範例 ```javascript= class VariableDemo{ static int count=0; public void increment(){ count++; } public static void main(String args[]){ VariableDemo obj1=new VariableDemo(); VariableDemo obj2=new VariableDemo(); obj1.increment(); obj2.increment(); System.out.println("Obj1: count is="+obj1.count); System.out.println("Obj2: count is="+obj2.count); } } ``` **輸出:** > Obj1: count is=2 Obj2: count is=2 從上面的範例中我們可以發現,雖然是透過不同的物件中的 increment() 操作,但**實際上操作的卻是同一區塊,證明 static 變數不是跟其他同 class 的元素一起放在heap區,而是獨立放在靜態區**,因此 obj1 和 obj2 的 count 都是指向記憶體的同一區塊。 ### **2. 實體變數(Instant Variables) :** 又稱為物件變數, 或物件的屬性, 係類別成員中沒有 static宣告之變數. 其特性如下 : - 於物件建立時產生, **存放於 heap 區**, 只要物件未消滅皆可存取. - 必須以物件實體名稱存取, 即 : [物件名稱].[變數名稱], 同類別之不同實體有各自屬性 (不共用). - 可以加存取修飾子 : public, protected, private. - 有預設值, 如果沒有初始化, 編譯器也會給予預設值, 與類別變數相同. ### **3. 方法變數 (Method Variables) :** 此為method中的variable以及內容中所用到的變數,是其特性如下 : - 存活期間最短, 僅在該方法被呼叫時存在, **配置於 stack 區 (LIFO)**, 方法執行完畢即消滅, 還給作業系統.  - 只能在方法內部直接存取, 故不可以加任何存取修飾子 (即外部無法存取). - 無預設值, 存取前必須先初始化 (賦值), 否則會編譯失敗 ### **4\. 區塊變數 (Local Variables):** 即 if, switch, for, while, do-while 等流程控制語法大括弧內所定義之變數, 是兩種區域變數之一, 其特性如下 : - 存活期間最短, 僅在進入該區塊執行時才存在, **配置於 statck 區 (FILO)**, 離開該區塊時即消滅, 還給作業系統. - 只能在區塊內部存取, 故不可以加任何存取修飾子 (區塊外部無法存取). - 無預設值, 存取前必須先初始化 (賦值), 否則會編譯失敗.  ### 總結: - 區域變數 (方法變數, 區塊變數) 是放在 stack 區, 執行時期動態生滅; - 靜態變數放在 global 區, 編譯成功時即存在, 程式結束時消滅; - 實體變數放在 heap 區, 隨實體(new)存亡而生滅. ## Private/ Public / Protected 修飾子 - **Private**:同一個class內才可存取 - **Protected**:同一個package的class才可存取,不同的package得要有**繼承關係**才可存取 - **Public**:皆可存取 - **Default (無修飾元)** : 同一個package的class才可存取 ## 說明Interface、Abstract Class、Anonymous Class差異? * **Interface:** * 完全不需要定義實作, 只需要定義函式原型 * **Interfaces cannot be instantiated** —they can only be _implemented_ by classes or _extended_ by other interfaces. * interface中所有資料成員都必須**初始化**, 且均為常數 * 宣告變數必須是final, static和public * interface中的method必須為abstract或public (\[public\] \[abstract\]是預設, 所以可省略, 因為interface本身就是抽象的) * **Abstract Class:** * 使用 abstract 定義抽象類別 (不得宣告為 `final class`) * 使用 abstract 宣告的class 並**不能夠被實體化 (instantiated)**, * 繼承abstract class的子類別必須實作父類別的abstract method, 否則這子類別還是個abstract class * **Anonymous Class:** 匿名類別實際上也擁有一個.class檔案,在概念上,它其實就是將一個類別或是介面在編譯new statement時由編譯器重新產生出另一個類別 :::info Abstract Class提供一種多個class一起合作工作的方式, 將多個class中相同的元素pull up method到public class中, 再以==繼承==的方式來使用它, 目的是為了實現==多型==精神 ::: Ex: 數學計算包括求各種形狀的面積、體積 、數字的立方 、平方等, 就可以把類似的方法集中到同一個public class中 ```clike= abstract class Shape { String name; double length, width, heigh; double radius; abstract double area(); // 求面積 abstract double perimeter(); // 求周長 // abstract class中也可以有建構方法, 但必須在子類別中被呼叫 // 四邊形的建構方法 public Shape(double length, double width, String name){ this.length = length; this.width = width; this.name = name; } // 三角形的建構方法 public Shape(String name, double width, double height){ this.height = height; this.width = width; this.name = name; } } ``` ```clike= // 三角形 class EqualTriangle extends Shape { public EqualTrangle(String name, double width, double height){ super(name, width, height); } double area(){ return (width * height) / 2 ; } double perimeter(){ return 3 * width; } } ``` ```clike= // 長方形 class Rectangular extends Shape { public Rectangular(double length, double width, String name){ //在子類別中呼叫父類別的建構方法用super() super(length, width, name); } // 因為繼承Shape類別, 因此要實作area和perimeter的abstract class double area(){ return length * width; } double perimeter(){ return (length + width) * 2; } } ``` Ref :+1: https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html [Interview: Can we instantiate abstract class?](https://stackoverflow.com/questions/13670991/interview-can-we-instantiate-abstract-class) ## Abstract Classes Compared to Interfaces > ([From Oracle Java Doc](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)) > Abstract classes are similar to interfaces. **You cannot instantiate them**, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods. With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces. ### Which should you use, abstract classes or interfaces? - Consider using **abstract classes** if any of these statements apply to your situation: - You want to share code among several closely related classes. - You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private). - You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong. - Consider using **interfaces** if any of these statements apply to your situation: - You expect that unrelated classes would implement your interface. For example, the interfaces [`Comparable`](https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html)and [`Cloneable`](https://docs.oracle.com/javase/8/docs/api/java/lang/Cloneable.html) are implemented by many unrelated classes. - You want to specify the behavior of a particular data type, but not concerned about who implements its behavior. - You want to take advantage of multiple inheritance of type. ### Abstract Class in JDK - AbstractMap An example of an abstract class in the JDK is [`AbstractMap`](https://docs.oracle.com/javase/8/docs/api/java/util/AbstractMap.html), which is part of the Collections Framework. Its subclasses (which include `HashMap`, `TreeMap`, and `ConcurrentHashMap`) share many methods (including `get`, `put`, `isEmpty`, `containsKey`, and `containsValue`) that `AbstractMap` defines. ### Interface in JDK - HashMap An example of a class in the JDK that implements several interfaces is [`HashMap`](https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html), which implements the interfaces `Serializable`, `Cloneable`, and `Map<K, V>`. By reading this list of interfaces, you can infer that an instance of `HashMap` (regardless of the developer or company who implemented the class) can be cloned, is serializable (which means that it can be converted into a byte stream; see the section [Serializable Objects](https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html)), and has the functionality of a map. In addition, the `Map<K, V>` interface has been enhanced with many default methods such as `merge` and `forEach`that older classes that have implemented this interface do not have to define. Note that many software libraries use both abstract classes and interfaces; the `HashMap` class implements several interfaces and also extends the abstract class `AbstractMap`. An Abstract Class Example ------------------------- In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects (for example: position, fill color, and moveTo). Others require different implementations (for example, resize or draw). All `GraphicObject`s must be able to draw or resize themselves; they just differ in how they do it. This is a perfect situation for an abstract superclass. You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object (for example, `GraphicObject`) as shown in the following figure. ![Classes Rectangle, Line, Bezier, and Circle Inherit from GraphicObject ](https://docs.oracle.com/javase/tutorial/figures/java/classes-graphicObject.gif) Classes Rectangle, Line, Bezier, and Circle Inherit from GraphicObject First, you declare an abstract class, `GraphicObject`, to provide member variables and methods that are wholly shared by all subclasses, such as the current position and the `moveTo` method. `GraphicObject` also declares abstract methods for methods, such as `draw` or `resize`, **that need to be implemented by all subclasses but must be implemented in different ways.** The `GraphicObject` class can look something like this: ``` abstract class GraphicObject { int x, y; ... void moveTo(int newX, int newY) { ... } // delcare abstrct methods abstract void draw(); abstract void resize(); } ``` Each nonabstract subclass of `GraphicObject`, such as `Circle` and `Rectangle`, must provide implementations for the `draw` and `resize` methods: ``` class Circle extends GraphicObject { void draw() { ... } void resize() { ... } } class Rectangle extends GraphicObject { void draw() { ... } void resize() { ... } } ``` When an Abstract Class Implements an Interface ---------------------------------------------- In the section on [`Interfaces`](https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html), it was noted that a class that implements an interface must implement _all_ of the interface's methods. It is possible, however, to define a class that does not implement all of the interface's methods, provided that the class is declared to be `abstract`. For example, ``` abstract class X implements Y { // implements all but one method of Y } class XX extends X { // implements the remaining method in Y } ``` In this case, class `X` must be `abstract` because it does not fully implement `Y`, but class `XX` does, in fact, implement `Y`. --- References: - [Java面試問題集錦 (Collections、Threads、GC、Java8)](https://www.lightblue.asia/java-interview-questions/) - [Java线程面试题 Top 50](http://www.importnew.com/12773.html) - [Java Programming tutorials and Interview Questions](http://www.java67.com/2012/12/what-is-difference-between-thread-vs-process-java.html#ixzz56J2b0x7S) - https://www.team-bob.org/java-%E8%AE%8A%E6%95%B8%E7%9A%84%E7%AF%84%E5%9C%8D%E8%88%87%E9%A1%9E%E5%9E%8B/ ## Override與Overloading的差異? - **重載(Overload)**: 表示同一個類中可以有多個名稱相同的方法,但這些方法的參數列表各不相同,即參數個數、類型或順序不同。 - **重寫(Override)** :表示子類別中的方法可以與父類中的某個方法的名稱和參數完全相同,通過子類創建的實例對象調用這個方法時,將調用子類中的定義方法,這相當於把父類中定義的那個完全相同的方法給覆蓋了,這也是面向對象編程的多態性的一種表現。 ## Java ThreadPool的使用情況?好處? ```javascript= new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } }).start(); ``` new Thread的弊端如下: * 每次new Thread新建對象性能差。 * 線程缺乏統一管理,可能無限制新建線程,相互之間競爭,及可能佔用過多系統資源導致死機或Out of memory。 * 缺乏更多功能,如定時執行、定期執行、線程中斷。 相比new Thread,Java提供的四種ThreadPool的好處在於: * 重用存在的線程,減少對象創建、消亡的開銷,性能佳。 * 可有效控制最大並發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。 * 提供定時執行、定期執行、單線程、並發數控制等功能。 Java通過[ThreadPoolExecutors](https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html)提供四種線程池,分別為: * [newCachedThreadPool](https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool()) : 創建一個可緩存線程池,如果線程池長度超過處理需要,**可靈活回收空閒線程**,若無可回收,則新建線程。 * [newFixedThreadPool(int)](https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)) : 創建一個一定長度線程池,可控制線程最大並發數,超出的線程會在隊列中等待。 * [newScheduledThreadPool](https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool(int)) : 創建一個定長線程池,支持定時及週期性任務執行。 * [newSingleThreadExecutor](https://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor()) : 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO,優先級)執行。 Ref :+1: http://www.trinea.cn/android/java-android-thread-pool/ https://www.ewdna.com/2011/11/java-thread-pool.html