java面試互聯網應該知道的知識-1
一 Java中的值傳遞和引用傳遞(非常重要)
首先要明確的是:“對象傳遞(數組、類、接口)是引用傳遞,原始類型數據(整型、浮點型、字符型、布爾型)傳遞是值傳遞。”
那麽什麽是值傳遞和應用傳遞呢?
值傳遞是指對象被值傳遞,意味著傳遞了對象的一個副本,即使副本被改變,也不會影響源對象。(因為值傳遞的時候,實際上是將實參的值復制一份給形參。)
引用傳遞是指對象被引用傳遞,意味著傳遞的並不是實際的對象,而是對象的引用。因此,外部對引用對象的改變會反映到實際的對象上。(因為引用傳遞的時候,實際上是將實參的地址值復制一份給形參。)
有時候面試官不是單純問你“Java中是值傳遞還是引用傳遞”是什麽啊,而是給出一個例子,然後讓你寫出答案,這種也常見在筆試題目中!所以,非常重要了,請看下面的例子:
值傳遞和應用傳遞實例
1. 值傳遞
-
public static void main(String[] args) {
-
int num1 = 10;
-
int num2 = 20;
-
-
swap(num1, num2);
-
-
System.out.println("num1 = " + num1);
-
System.out.println("num2 = " + num2);
-
}
-
-
public static void swap(int a, int b) {
-
int temp = a;
-
a = b;
-
b = temp;
-
-
System.out.println("a = " + a);
-
System.out.println("b = " + b);
-
}
結果:
-
a = 20
-
b = 10
-
num1 = 10
-
num2 = 20
解析:
在swap方法中,a、b的值進行交換,並不會影響到num1、num2。因為,a、b中的值,只是從num1、num2的復制過來的。 也就是說,a、b相當於num1、num2的副本,副本的內容無論怎麽修改,都不會影響到原件本身。
2. 引用傳遞
-
public static void main(String[] args) {
-
int[] arr = {1,2,3,4,5};
-
-
change(arr);
-
-
System.out.println(arr[0]);
-
}
-
-
public static void change(int[] array) {
-
//將數組的第一個元素變為0
-
array[0] = 0;
-
}
結果:
-
1
-
0
解析:
無論是主函數,還是change方法,操作的都是同一個地址值對應的數組。 因此,外部對引用對象的改變會反映到實際的對象上。
一些特殊的例子
1. StringBuffer類型傳遞
-
// 測試引用傳遞:StringBuffer
-
@org.junit.Test
-
public void method1() {
-
StringBuffer str = new StringBuffer("公眾號:Java面試通關手冊");
-
System.out.println(str);
-
change1(str);
-
System.out.println(str);
-
}
-
-
public static void change1(StringBuffer str) {
-
str = new StringBuffer("abc");//輸出:“公眾號:Java面試通關手冊”
-
//str.append("歡迎大家關註");//輸出:公眾號:Java面試通關手冊歡迎大家關註
-
//str.insert(3, "(編程)");//輸出:公眾號(編程):Java面試通關手冊
-
-
}
結果:
-
公眾號:Java面試通關手冊
-
公眾號:Java面試通關手冊
解析:
很多要這個時候要問了:StringBuffer創建的明明也是對象,那為什麽輸出結果依然是原來的值呢?
因為在 change1
方法內部我們是新建了一個StringBuffer對象,所以 str
指向了另外一個地址,相應的操作也同樣是指向另外的地址的。
那麽,如果將 change1
方法改成如下圖所示,想必大家應該知道輸出什麽了,如果你還不知道,那可能就是我講的有問題了,我反思(開個玩笑,實際上,上面程序中已經給出答案):
-
public static void change1(StringBuffer str) {
-
-
str.append("歡迎大家關註");
-
str.insert(3, "(編程)");
-
-
}
2. String類型傳遞
-
// 測試引用傳遞:Sring
-
@org.junit.Test
-
public void method2() {
-
String str = new String("公眾號:Java面試通關手冊");
-
System.out.println(str);
-
change2(str);
-
System.out.println(str);
-
}
-
-
public static void change2(String str) {
-
// str="abc"; //輸出:公眾號:Java面試通關手冊
-
str = new String("abc"); //輸出:公眾號:Java面試通關手冊
-
}
結果:
-
公眾號:Java面試通關手冊
-
公眾號:Java面試通關手冊
可以看到不論是執行 str="abc;"
還是 str=newString("abc");
str的輸出的值都不變。 按照我們上面講“StringBuffer類型傳遞”的時候說的, str="abc;"
應該會讓str的輸出的值都不變。為什麽呢?因為String在創建之後是不可變的
3. 一道類似的題目
下面的程序輸出是什麽?
-
public class Demo {
-
public static void main(String[] args) {
-
Person p = new Person("張三");
-
-
change(p);
-
-
System.out.println(p.name);
-
}
-
-
public static void change(Person p) {
-
Person person = new Person("李四");
-
p = person;
-
}
-
}
-
-
class Person {
-
String name;
-
-
public Person(String name) {
-
this.name = name;
-
}
-
}
很明顯仍然會輸出 張三
。因為 change
方法中重新創建了一個 Person
對象。
那麽,如果把 change
方法改為下圖所示,輸出結果又是什麽呢?
-
public static void change(Person p) {
-
p.name="李四";
-
}
答案我就不說了,我覺得大家如果認真看完上面的內容之後應該很很清楚了。
二 ==與equals(重要)
== : 它的作用是判斷兩個對象的地址是不是相等。即,判斷兩個對象是不是同一個對象。(基本數據類型==比較的是值,引用數據類型==比較的是內存地址)
equals() : 它的作用也是判斷兩個對象是否相等。但它一般有兩種使用情況:
-
情況1:類沒有覆蓋equals()方法。則通過equals()比較該類的兩個對象時,等價於通過“==”比較這兩個對象。
-
情況2:類覆蓋了equals()方法。一般,我們都覆蓋equals()方法來兩個對象的內容相等;若它們的內容相等,則返回true(即,認為這兩個對象相等)。
舉個例子:
-
public class test1 {
-
public static void main(String[] args) {
-
String a = new String("ab"); // a 為一個引用
-
String b = new String("ab"); // b為另一個引用,對象的內容一樣
-
String aa = "ab"; // 放在常量池中
-
String bb = "ab"; // 從常量池中查找
-
if (aa == bb) // true
-
System.out.println("aa==bb");
-
if (a == b) // false,非同一對象
-
System.out.println("a==b");
-
if (a.equals(b)) // true
-
System.out.println("aEQb");
-
if (42 == 42.0) { // true
-
System.out.println("true");
-
}
-
}
-
}
上述運行結果說明:
-
String中的equals方法是被重寫過的,因為object的equals方法是比較的對象的內存地址,而String的equals方法比較的是對象的值。
-
當創建String類型的對象時,虛擬機會在常量池中查找有沒有已經存在的值和要創建的值相同的對象,如果有就把它賦給當前引用。如果沒有就在常量池中重新創建一個String對象
-
hashCode()與equals()的相關規定
-
如果兩個對象相等,則hashcode一定也是相同的
-
兩個對象相等,對兩個對象分別調用equals方法都返回true
-
兩個對象有相同的hashcode值,它們也不一定是相等的
-
因此,equals方法被覆蓋過,則hashCode方法也必須被覆蓋
-
hashCode()的默認行為是對堆上的對象產生獨特值。如果沒有重寫hashCode(),則該class的兩個對象無論如何都不會相等(即使這兩個對象指向相同的數據)
-
java面試互聯網應該知道的知識-1