Java面向對象面試題


1. Java面向對象的知識結構

  • 1.1 Java語法以及關鍵字、如接口與類、內部類,final/finally/finalize, throw/throws,域訪問符權限等;

  • 1.2 Java面向對象思想以及體系,例如設計思想。

2. 經典面試題

2.1 Java 有沒有 goto? 如果有,一般用在什么地方?如果沒有,如何跳出當前的多重嵌套循環?

goto是Java中的保留字,在目前Java版本中沒有使用。

在Java中跳出多重循環的的方法有三種:

1. break + 標簽,在外層循環前加上一個標簽lable,
然后在最里層循環使用 break lable.

public static void main(String[] args) {
    label:    //標記
    for (int i = 0 ; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
                System.out.println("i = " + i + ", j = " + j);
            if(j == 5) {  //滿中一定條件跳到某個標記
                break label;
            }
        }
    }
}

2. 通過異常捕獲

public static void main(String[] args) {
	try {
    	for (int i = 0; i < 10; i++) {
        	for (int j = 0; j < 10; j++) {
            	System.out.println("i = " + i + ", j = " + j);
            	if (j == 5) {// 滿足一定條件拋異常
                	throw new RuntimeException("test exception for j = 5");
            	}
        	}
    	}
	} catch (RuntimeException e) { //循環外層捕獲異常
    	e.printStackTrace();
	}
}


3. 通過標置變量

 public static void main(String[] args) {
    boolean flag = false; //初始化標置變量
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            System.out.println("i = " + i + ", j = " + j);
            if (j == 5) {   //滿足一定條件進行設置標置變量
                flag = true;
            }
            if (flag) { //內層循環判斷標置變量
                break;
            }

        }
        if (flag) {//外層循環判斷標置變量
            break;
        }
    }
}

2.2 抽象類(abstract class)和接口(interface)有什么異同?

  • 相同點

      1. 不能直接實例化。如果要實例化,抽象變量必須實現所有抽象方法,接口變量必須實現接口未實現的方法。
      2. 都可以有實現方法(Java1.8之前不能有實現方法)
      3. 都可以不需要實現類或者繼承者去實現所有方法(Java8 以前的接口,Java8 及以后的接口中可以包括默認方法,不需要實現者實現)。
    
  • 不同點

      1. 抽象類和接口所反映的設計理念不同,抽象類表示的是對象/類的抽象,接口表示的是行為的抽象。
      
      2. 抽象類不可以多重繼承,接口可以多重繼承。即一個類只能繼續一個抽象類,卻可以繼承多個接口。
       
      3. 抽象類中的方法可以用 public protected 和 default abstract 修飾符,不能用 private、static、synchronize、native 修飾;變量可以在子類中重新定義,也可以重新賦值;
      接口的方法默認修飾符是 public abstract, Java8 開始出現靜態方法,多加 static 關鍵字;變量默認是 public static final 型,且必須給其初值,在實現類中也不能重新定義,也不能改變其值。
    
      4. 抽象類可以有構造器,接口沒有構造器。
    

2.3 Java 創建對象的方式有哪些?

1. 使用 new關鍵字
2. 反射創建,使用java.lang.Class 類的newInstance 方法

這種方式會調用無參的構造函數來創建對象,有兩種實現方式。

//方式一,使用全路徑包名
User user = (User)Class.forName("com.imooc.interview.demo.User").newInstance(); 
//方法二,使用class類
User user = User.class.newInstance();

反射,使用 java.lang.reflect.Constructor 類的 newInstance 方法。

Constructor<User> constructor = User.class.getConstructor();
User user = constructor.newInstance();

使用 clone 方法。

public class User implements  Cloneable {
/** 構造方法 */
public User(Integer age) {
    this.age = age;
}

public Integer getAge() {
    return age;
}

private Integer age;

// 重寫(Overriding)Object的clone方法
@Override
protected User clone() throws CloneNotSupportedException {
    return (User) super.clone();
}


public static void main(String[] args) throws Exception {
    User person = new User(new Integer(200));
    User clone = person.clone();
    System.out.println("person == clone, result =  " +  (person == clone));  // false,拷貝都是生成新對象
    System.out.println("person.age == clone.age, result =  " +  (person.getAge() == clone.getAge())); // true,淺拷貝的成員變量引用仍然指向原對象的變量引用
}

}

淺拷貝和深拷貝

  • 淺拷貝:被復制對象的所有變量都含有與原來的對象相同的值,對拷貝后對象的引用仍然指向原來的對象。

  • 深拷貝:不僅要復制對象的所有非引用成員變量值,還要為引用類型的成員變量創建新的實例,並且初始化為形式參數實例值。

      3. 使用反序列化。
      為了序列化 / 反序列化一個對象,需要該類實現空接口 Serializable
      
      序列化時首先創建一個輸出流對象 oos, 使用 oos 的 writeObject () 方法將 p 對象寫入 oos 對象中去。使用反序列化創建對象時,首先創建一個輸入流對象 ois,使用輸入流對象 ois 的 readObject () 方法將序列化存入的對象讀出,重新創建一個對象。
    
      序列化是深拷貝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM