Java面試題沖刺第十七天–基礎篇3
面試題1:JDK1.8的新特性有哪些?
接口的默認和靜態方法:
Java 8允許我們給接口添加一個非抽象的方法實現,隻需要使用 default關鍵字即可,這個特征又叫做擴展方法。
public interface JDK8Interface { // static修飾符定義靜態方法 static void staticMethod() { System.out.println("接口中的靜態方法"); } // default修飾符定義默認方法 default void defaultMethod() { System.out.println("接口中的默認方法"); } }
Lambda 表達式:
例如:(x, y) -> { return x + y; };λ表達式有三部分組成:參數列表,箭頭(->),以及一個表達式或語句塊。
在Java 8 中你就沒必要使用這種傳統的匿名對象的方式瞭,Java 8提供瞭更簡潔的語法,lambda表達式:
Collections.sort(names, (String a, String b) -> { return b.compareTo(a); });
方法與構造函數引用:
Java 8 允許你使用 :: 關鍵字來傳遞方法或者構造函數引用,上面的代碼展示瞭如何引用一個靜態方法,我們也可以引用一個對象的方法:
converter = something::startsWith; String converted = converter.convert("Java"); System.out.println(converted);
函數式接口:
所謂的函數式接口,當然首先是一個接口,然後就是在這個接口裡面隻能有一個抽象方法。
Annotation 註解:支持多重註解:
很多時候一個註解需要在某一位置多次使用。
@YourAnnotation @YourAnnotation public void test(){ //TODO }
新的日期時間 API:
Java 8新的Date-Time API (JSR 310)受Joda-Time的影響,提供瞭新的java.time包,可以用來替代java.util.Date和java.util.Calendar。
一般會用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration這些類,對於時間日期的改進還是非常不錯的。
Base64編碼:
Base64編碼是一種常見的字符編碼,可以用來作為電子郵件或Web Service附件的傳輸編碼。
在Java 8中,Base64編碼成為瞭Java類庫的標準。Base64類同時還提供瞭對URL、MIME友好的編碼器與解碼器。
JavaScript引擎Nashorn:
Nashorn允許在JVM上開發運行JavaScript應用,允許Java與JavaScript相互調用。
Stream的使用:
Stream API是把真正的函數式編程風格引入到Java中。其實簡單來說可以把Stream理解為MapReduce,當然Google的MapReduce的靈感也是來自函數式編程。她其實是一連串支持連續、並行聚集操作的元素。從語法上看,也很像linux的管道、或者鏈式編程,代碼寫起來簡潔明瞭,非常酷帥!
Optional:
Java 8引入Optional類來防止空指針異常,Optional類最先是由Google的Guava項目引入的。Optional類實際上是個容器:它可以保存類型T的值,或者保存null。使用Optional類我們就不用顯式進行空指針檢查瞭。
擴展註解的支持:
Java 8擴展瞭註解的上下文,幾乎可以為任何東西添加註解,包括局部變量、泛型類、父類與接口的實現,連方法的異常也能添加註解。
並行(parallel)數組:
支持對數組進行並行處理,主要是parallelSort()方法,它可以在多核機器上極大提高數組排序的速度。
編譯器優化:
Java 8將方法的參數名加入瞭字節碼中,這樣在運行時通過反射就能獲取到參數名,隻需要在編譯時使用-parameters參數。
其他核心 API 的改進
Java IO改進
一些IO改進包括:
- Files.list(Path dir) 返回延遲填充的Stream,其元素是目錄中的條目。
- Files.lines(Path path) 從文件中讀取所有行作為流。
- Files.find() 通過在以給定起始文件為根的文件樹中搜索文件,返回通過路徑延遲填充的Stream。
- BufferedReader.lines() 返回一個Stream,其元素是從此BufferedReader中讀取的行。
集合 API 的改進
我們已經看到瞭 forEach()方法和用於集合的 Stream API。Collection API還有一些新方法是:
- Iterator forEachRemaining(Consumer action)在所有元素都已處理完畢或該動作引發異常之前,對每個剩餘元素執行給定操作的默認方法。
- Collection removeIf(Predicate filter)刪除此集合中所有滿足特定條件的元素的默認方法。
- Collection spliterator() 該方法返回Spliterator實例,該實例可用於順序或並行遍歷元素。
- map replaceAll(),compute(),merge()方法。
- 具有鍵沖突的HashMap類的性能改進
面試題2:什麼是內部類?內部類的作用?
將一個類定義在另一個類或者另一個方法裡面,這樣的類稱著內部類;值得註意的是,內部類能夠訪問外部類的所有成員,包括private修飾的。
舉例:把類Inner定義在類Outer中,類Inner就被稱為內部類。
class Outer { class Inner { } }
註意:
內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩類。對於一個名為 outer 的外部類和其內部定義的名為 inner 的內部類。編譯完成後出現 outer.class 和 outer$inner.class 兩類。所以內部類的成員變量/方法名可以和外部類的相同。
內部類的作用
1、內部類可以很好的實現隱藏。
非內部類是不可以使用 private和 protected修飾的,但是內部類卻可以,從而達到隱藏的作用。同時也可以將一定邏輯關系的類組織在一起,增強可讀性。
2、間接的實現多繼承。
內部類提供瞭Java的”多重繼承”的解決方案,彌補瞭Java類是單繼承的不足
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外部類是否已經繼承瞭某個(接口的)實現,對於內部類都沒有影響。如果沒有內部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。所以說內部類間接的實現瞭多繼承。
內部類特點
- 內部類仍然是一個獨立的類,在編譯之後內部類會被編譯成獨立的.class文件,但是前面冠以外部類的類名和$符號
- 內部類不能用普通的方式訪問。內部類是外部類的一個成員,因此內部類可以自由地訪問外部類的成員變量,無論是否是private的
- 內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量瞭,此時內部類隻能訪問外部類的靜態成員變量
面試題3:內部類有哪幾種?分別介紹一下
成員內部類
局部內部類
靜態內部類
匿名內部類
成員內部類
成員內部類——就是位於外部類成員位置的類
public class Outer { //不對外開放的 class Inner{ public void show(){ System.out.println("成員內部類"); } } }
特點:
- 內部類就像一個實例成員一樣存在於外部類中。
- 內部類可以訪問外部類的所有成員就想訪問自己的成員一樣沒有限制。
- 內部類中的 this 指的是內部類的實例對象本身,如果要用外部類的實例對象就可以用類名 .this 的方式獲得。
- 內部類對象中不能有靜態成員,原因很簡單,內部類的實例對象是外部類實例對象的一個成員。
局部內部類
局部內部類——就是定義在一個方法或者一個作用域裡面的類;
class Outer { public void method(){ class Inner { System.out.println("局部內部類"); } } }
特點:
- 方法中的內部類沒有訪問修飾符, 即方法內部類對包圍它的方法之外的任何東西都不可見。
- 方法內部類隻能夠訪問該方法中的局部變量,所以也叫局部內部類。而且這些局部變量一定要是final修飾的常量。
靜態內部類
我們所知道static是不能用來修飾類的,但是成員內部類可以看做外部類中的一個成員,所以可以用static修飾,這種用static修飾的內部類我們稱作靜態內部類,也稱作嵌套內部類.
特點:不能使用外部類的非static成員變量和成員方法
class Outter { int age = 10; static age2 = 20; public Outter() { } static class Inner { public method() { System.out.println(age);//錯誤 System.out.println(age2);//正確 } } } public class Test { public static void main(String[] args) { Outter.Inner inner = new Outter.Inner(); inner.method(); } }
匿名內部類
一個沒有名字的類,是內部類的簡化寫法
本質:其實是繼承該類或者實現接口的子類匿名對象
public abstract class A implements B{ public void A(){ System.out.println("A"); } }
public interface B{ public void B(); }
public class Test { public static void main(String[] args) { //new出接口或者實現類 A a= new A (){ //實現接口裡未實現的方法 public void B() { System.out.println("匿名內部類"); } }; a.A(); a.B(); }
特點:
一個類用於繼承其他類或是實現接口,並不需要增加額外的方法,隻是對繼承方法的事先或是覆蓋。
隻是為瞭獲得一個對象實例,不需要知道其實際類型。
類名沒有意義,也就是不需要使用到。 每日小結
總結
本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!