麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發(fā)設計 > 正文

java筆試題(5)

2019-11-14 20:59:08
字體:
來源:轉載
供稿:網友
java筆試題(5)

1.Comparable和Comparator接口是干什么的?列出它們的區(qū)別。

Java提供了只包含一個compareTo()方法的Comparable接口。這個方法可以個給兩個對象排序。具體來說,它返回負數,0,正數來表明輸入對象小于,等于,大于已經存在的對象。

Java提供了包含compare()和equals()兩個方法的Comparator接口。compare()方法用來給兩個輸入參數排序,返回負數,0,正數表明第一個參數是小于,等于,大于第二個參數。equals()方法需要一個對象作為參數,它用來決定輸入參數是否和comparator相等。只有當輸入參數也是一個comparator并且輸入參數和當前comparator的排序結果是相同的時候,這個方法才返回true。

2.下面的代碼片段中,行A和行B所標識的代碼有什么區(qū)別呢?

public class ConstantFolding {     static final  int number1 = 5;     static final  int number2 = 6;     static int number3 = 5;     static int number4= 6;     public static void main(String[ ] args) {           int PRoduct1 = number1 * number2;         //line A           int product2 = number3 * number4;         //line B     } }

在行A的代碼中,product的值是在編譯期計算的,行B則是在運行時計算的。如果你使用Java反編譯器(例如,jd-gui)來反編譯ConstantFolding.class文件的話,那么你就會從下面的結果里得到答案。

public class ConstantFolding{  static final int number1 = 5;  static final int number2 = 6;  static int number3 = 5;  static int number4 = 6;   public static void main(String[ ] args)  {      int product1 = 30;      int product2 = number3 * number4;  }}

常量折疊是一種Java編譯器使用的優(yōu)化技術。由于final變量的值不會改變,因此就可以對它們優(yōu)化。Java反編譯器和javap命令都是查看編譯后的代碼(例如,字節(jié)碼)的利器。

3.你能想出除了代碼優(yōu)化外,在什么情況下,查看編譯過的代碼是很有幫助的?

Java里的泛型是在編譯時構造的,可以通過查看編譯后的class文件來理解泛型,也可以通過查看它來解決泛型相關的問題。

4.下面哪些是發(fā)生在編譯時,運行時,或者兩者都有?

1

  • 方法重載:這個是發(fā)生在編譯時的。方法重載也被稱為編譯時多態(tài),因為編譯器可以根據參數的類型來選擇使用哪個方法。
    public class {     public static void evaluate(String param1);  // method #1     public static void evaluate(int param1);   // method #2}
    如果編譯器要編譯下面的語句的話:
    evaluate(“My Test Argument passed to param1”);
    它會根據傳入的參數是字符串常量,生成調用#1方法的字節(jié)碼
  • 方法覆蓋:這個是在運行時發(fā)生的。方法重載被稱為運行時多態(tài),因為在編譯期編譯器不知道并且沒法知道該去調用哪個方法。JVM會在代碼運行的時候做出決定。
    public class A {   public int compute(int input) {          //method #3        return 3 * input;   }        } public class B extends A {   @Override   public int compute(int input) {          //method #4        return 4 * input;   }        }
    子類B中的compute(..)方法重寫了父類的compute(..)方法。如果編譯器遇到下面的代碼:
    public int evaluate(A reference, int arg2)  {     int result = reference.compute(arg2);}
    編譯器是沒法知道傳入的參數reference的類型是A還是B。因此,只能夠在運行時,根據賦給輸入變量“reference”的對象的類型(例如,A或者B的實例)來決定調用方法#3還是方法#4.
  • 泛型(又稱類型檢驗):這個是發(fā)生在編譯期的。編譯器負責檢查程序中類型的正確性,然后把使用了泛型的代碼翻譯或者重寫成可以執(zhí)行在當前JVM上的非泛型代碼。這個技術被稱為“類型擦除“。換句話來說,編譯器會擦除所有在尖括號里的類型信息,來保證和版本1.4.0或者更早版本的JRE的兼容性。
    List<String> myList = new ArrayList<String>(10);
    編譯后成為了:
    List myList = new ArrayList(10);
  • 注解(Annotation):你可以使用運行時或者編譯時的注解。
    public class B extends A {   @Override    public int compute(int input){      //method #4        return 4 * input;    }       }
    @Override是一個簡單的編譯時注解,它可以用來捕獲類似于在子類中把toString()寫成tostring()這樣的錯誤。在Java 5中,用戶自定義的注解可以用注解處理工具(Anotation Process Tool ——APT)在編譯時進行處理。到了Java 6,這個功能已經是編譯器的一部分了。
    public class MyTest{    @Test     public void testEmptyness( ){         org.junit.Assert.assertTrue(getList( ).isEmpty( ));     }      private List getList( ){        //implemenation goes here     }}
    @Test是JUnit框架用來在運行時通過反射來決定調用測試類的哪個(些)方法的注解。
    @Test (timeout=100)public void testTimeout( ) {    while(true);   //infinite loop}
    如果運行時間超過100ms的話,上面的測試用例就會失敗。
    @Test (expected=IndexOutOfBoundsException.class)public void testOutOfBounds( ) {       new ArrayList<Object>( ).get(1);}
    如果上面的代碼在運行時沒有拋出IndexOutOfBoundsException或者拋出的是其他的異常的話,那么這個用例就會失敗。用戶自定義的注解可以在運行時通過Java反射API里新增的AnnotatedElement和”Annotation”元素接口來處理。
  • 異常(Exception):你可以使用運行時異常或者編譯時異常。
  • 運行時異常(RuntimeException)也稱作未檢測的異常(unchecked exception),這表示這種異常不需要編譯器來檢測。RuntimeException是所有可以在運行時拋出的異常的父類。一個方法除要捕獲異常外,如果它執(zhí)行的時候可能會拋出RuntimeException的子類,那么它就不需要用throw語句來聲明拋出的異常。

    例如:NullPointerException,ArrayIndexOutOfBoundsException,等等

  • 受檢查異常(checked exception)都是編譯器在編譯時進行校驗的,通過throws語句或者try{}cathch{} 語句塊來處理檢測異常。編譯器會分析哪些異常會在執(zhí)行一個方法或者構造函數的時候拋出。
  • 面向切面的編程(aspect Oriented Programming-AOP):切面可以在編譯時,運行時或,加載時或者運行時織入。
  • 編譯期:編譯期織入是最簡單的方式。如果你擁有應用的代碼,你可以使用AOP編譯器(例如,ajc – AspectJ編譯器)對源碼進行編譯,然后輸出織入完成的class文件。AOP編譯的過程包含了waver的調用。切面的形式可以是源碼的形式也可以是二進制的形式。如果切面需要針對受影響的類進行編譯,那么你就需要在編譯期織入了。
  • 編譯后:這種方式有時候也被稱為二進制織入,它被用來織入已有的class文件和jar文件。和編譯時織入方式相同,用來織入的切面可以是源碼也可以是二進制的形式,并且它們自己也可以被織入切面。
  • 裝載期:這種織入是一種二進制織入,它被延遲到JVM加載class文件和定義類的時候。為了支持這種織入方式,需要顯式地由運行時環(huán)境或者通過一種“織入代理(weaving agent)“來提供一個或者多個“織入類加載器(weaving class loader)”。
  • 運行時:對已經加載到JVM里的類進行織入
  • 繼承 – 發(fā)生在編譯時,因為它是靜態(tài)的
  • 代理或者組合 – 發(fā)生在運行時,因為它更加具有動態(tài)性和靈活性。

    5.你能夠通過實例來區(qū)別編譯期繼承和運行時繼承,以及指出Java支持哪種嗎?

    “繼承”表示動作和屬性從一個對象傳遞到另外一個對象的場景。Java語言本身只支持編譯期繼承,它是通過“extends”關鍵字來產生子類的方式實現的,如下所示:

    public class Parent {    public String saySomething( ) {          return “Parent is called”;    }} public class Child extends Parent {     @Override     public String saySomething( ) {          return super.saySomething( ) +  “, Child is called”;    }}

    “Child”類的saySomething()方法的調用會返回“Parent is called,Child is Called”,因為,子類的調用繼承了父類的“Parenet is called”。關鍵字“super”是用來調用“Parent”類的方法。運行時繼承表示在運行時構建父/子類關系。Java語言本身不支持運行時繼承,但是有一種替代的方案叫做“代理”或者“組合”,它表示在運行時組件一個層次對象的子類。這樣可以模擬運行時繼承的實現。在Java里,代理的典型實現方式如下:

    public class Parent {    public String saySomething( ) {          return “Parent is called”;    }} public class Child  {     public String saySomething( ) {          return new Parent( ).saySomething( ) +  “, Child is called”;    }}

    子類代理了父類的調用。組合可以按照下面的方式來實現:

    public class Child  {     private Parent parent = null;      public Child( ){          this.parent = new Parent( );     }      public String saySomething( ) {          return this.parent.saySomething( ) +  “, Child is called”;    }}

    6.Java中的volatile 變量是什么?

    volatile是一個特殊的修飾符,只有成員變量才能使用它。在Java并發(fā)程序缺少同步類的情況下,多線程對成員變量的操作對其它線程是透明的。volatile變量可以保證下一個讀取操作會在前一個寫操作之后發(fā)生。

    7.什么是FutureTask?

    在Java并發(fā)程序中FutureTask表示一個可以取消的異步運算。它有啟動和取消運算、查詢運算是否完成和取回運算結果等方法。只有當運算完成的時候結果才能取回,如果運算尚未完成get方法將會阻塞。一個FutureTask對象可以對調用了Callable和Runnable的對象進行包裝,由于FutureTask也是調用了Runnable接口所以它可以提交給Executor來執(zhí)行。

    8.Java中interrupted 和 isInterrupted方法的區(qū)別?

    interrupted() 和 isInterrupted()的主要區(qū)別是前者會將中斷狀態(tài)清除而后者不會。Java多線程的中斷機制是用內部標識來實現的,調用Thread.interrupt()來中斷一個線程就會設置中斷標識為true。當中斷線程調用靜態(tài)方法Thread.interrupted()來檢查中斷狀態(tài)時,中斷狀態(tài)會被清零。而非靜態(tài)方法isInterrupted()用來查詢其它線程的中斷狀態(tài)且不會改變中斷狀態(tài)標識。簡單的說就是任何拋出InterruptedException異常的方法都會將中斷狀態(tài)清零。無論如何,一個線程的中斷狀態(tài)有有可能被其它線程調用中斷來改變。

    9.如果你提交任務時,線程池隊列已滿。會時發(fā)會生什么?

    這個問題問得很狡猾,許多程序員會認為該任務會阻塞直到線程池隊列有空位。事實上如果一個任務不能被調度執(zhí)行那么ThreadPoolExecutor’s submit()方法將會拋出一個RejectedExecutionException異常。

    10.Java線程池中submit() 和 execute()方法有什么區(qū)別?

    兩個方法都可以向線程池提交任務,execute()方法的返回類型是void,它定義在Executor接口中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口,其它線程池類像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有這些方法。

    11.volatile 變量和 atomic 變量有什么不同?

    首先,volatile 變量和 atomic 變量看起來很像,但功能卻不一樣。Volatile變量可以確保先行關系,即寫操作會發(fā)生在后續(xù)的讀操作之前, 但它并不能保證原子性。例如用volatile修飾count變量那么 count++ 操作就不是原子性的。而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它數據類型和引用變量也可以進行相似操作。

    12.如果同步塊內的線程拋出異常會發(fā)生什么?

    這個問題坑了很多Java程序員,若你能想到鎖是否釋放這條線索來回答還有點希望答對。無論你的同步塊是正常還是異常退出的,里面的線程都會釋放鎖,所以對比鎖接口我更喜歡同步塊,因為它不用我花費精力去釋放鎖,該功能可以在finally block里釋放鎖實現。

    我是天王蓋地虎的分割線


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 免费国产一级淫片 | 国产精品一区二区羞羞答答 | 亚洲网站在线观看视频 | sesee99| 成人在线免费观看视频 | 成人国产精品久久久 | 92看片淫黄大片欧美看国产片 | 伊人999| 日本一道aⅴ不卡免费播放 久久久久久久高清 | 久久久一区二区三区视频 | 久久精品99久久久久久2456 | 国产精品99久久免费观看 | 久草成人在线 | 亚洲福利在线视频 | 高清做爰免费无遮网站挡 | 天天操天天骑 | 久久精品久久精品久久精品 | 免费观看一区二区三区 | 斗破苍穹在线观看免费完整观看 | 噜噜社| 午夜色视频在线观看 | 色婷婷久久久亚洲一区二区三区 | 国产成人精品午夜 | 亚洲一区二区中文字幕在线观看 | 成人福利在线 | 97伦理| 色婷婷av一区二区三区久久 | 久久久久久久久久久av | 亚洲精品午夜在线 | 一级毛片真人免费播放视频 | 一级空姐毛片 | sm高h视频 | 亚洲二区免费 | 国产亚洲精品一区二区三区 | 999精品久久久 | 黄色视频a级毛片 | 污片在线观看视频 | 空姐一级毛片 | 国产精品成人久久久久a级 欧美特黄一级高清免费的香蕉 | 91看片淫黄大片欧美看国产片 | 午夜伦情电午夜伦情电影 |