1. 程式人生 > >Java面試複習之Java深入解析二

Java面試複習之Java深入解析二

運算子與表示式

  1. 貪心規則:在分析符號時,編譯器會盡可能多的結合有效的符號。i+++j的運算就是(i++)+j。如果不貪心,“\1717”就會出現二義性,“\17”和“17”,因此,轉義符就會失去作用。編譯器會將“\1717”解析為“\171”和“7”。
  2. i++和++i之間的區別:在java中,兩者都是先對值加1,然後再參與運算。只不過i++在加1前會先將值複製一份作為臨時變數,然後用臨時變數參與運算。可以用一下程式碼進行驗證:
int i=5;
i=i++;
System.out.println(i);

結果

5

深層次的理解:前置++直接將變數的值+1,然後使用這個變數的值。後置++是先將變數的值壓棧(暫時儲存起來),然後將變數加1,再使用壓棧的值參與運算。

3.相除與求餘:

相除:

整型0除0,產生異常;浮點0除0,不會產生異常,結果為NAN。NAN不等於任何值,包括自身。可以用Float中的isNaN來判斷是否是一個NaN。

System.out.println(0.0/0.0);
System.out.println(0.0/0.0==NaN);
System.out.println(Double.isNaN( 0.0/0.0));

執行結果為:

NaN
false
true

除法運算規則:

  • 兩個運算元均為0或infinity時,結果為NaN;有NaN參與的運算,結果均為NaN。
  • 相除結果的符號與兩運算元的符號有關,相同為正,不同為負。
  • 0做被除數結果為0;0做除數結果為無窮。
  • 無窮做被除數結果為無窮;無窮做除數結果為0。

求餘:

  • 有NaN參與的求餘結果均為NaN;無窮作為被除數時,結果為NaN;正負0作為除數時結果為NaN。
  • 餘數的符號與被除數的符號相同。
  • 餘不過,得自身。

4.+0與-0的異同:在數值上是相等的,用==來比較也返回true。但是在參與浮點運算時,會產生不一樣的結果。+0和-0在儲存中,符號為是不同的。Java的某些類也把+0和-0視為兩個不同的數。在Float類中的compare方法裡+0大於-0。

System.out.println(Float.compare(+0f,-0f));

結果返回1。 5.位移運算子:byte、short、char參與時會自動提升至int,結果也為int。如果將int(long)型別移動超過31(64)位,就會把有效數全移走了。所以,當操作符右側的數大於31(63)時,系統做了處理。取右側數的補碼的低5(6)位進行操作。 右移與相除區別:相除時會向0舍入。而右移只會向下舍入。正數時,除法和右移都是向下舍入。負數時,除法是向上舍入,右移是向下舍入。如下:

System.out.println(-3/2);//向0舍入,結果為-1
System.out.println(-3>>1);//向下舍入,結果為-2

結果

-1
-2

“>>>”表示無符號右移,最高位是用0來填充。“>>”最高位用符號為來填充。一個負數經過無符號右移後變成正數

System.out.println(-1>>>1);

結果

2147483647

byte型別的-1經過無符號右移(一位一位移,不管移動多少次)後還是-1。因為byte參與運算時要擴充套件位int。-1的補碼全為1,符號位為1,擴充套件後為32個1。無符號右移一位後,最高位補0。使用“>>>=”時會自動進行型別轉換,因此右移後的int型別要擷取低八位轉回byte型別。

byte b=-1;
byte b1=b>>>=1;
System.out.println(b>>>1);//運算後為int型別
System.out.println(b1);//運算後將byte型別賦值給b1

執行結果

2147483647
-1

6.三目運算子:表示式1?表示式2:表示式3; 表示式1必須為boolean或者可以通過拆箱轉化為boolean的包裝器Boolean型別 7.從左向右的計算順序:程式碼如下

int[] a={0,0,0,0,0,0};
int i=1,j=3;
a[++i]=i++;//相當於a[2]=2,i=3;
a[j]=j=4;//相當於a[3]=4,j=4
System.out.println("i="+i+"\tj="+j);
System.out.println(Arrays.toString(a));

執行結果

i=3	j=4
[0, 0, 2, 4, 0, 0]

複合賦值運算子會自動進行隱式型別轉換,b+=1相當於b=(byte)(b+1)。複合賦值運算子在進行運算時,也是按照從左向右的規則。運算前,先會確定左側的運算元,將左側的運算元儲存起來,左側的運算元不會受到右側的表示式的影響而造成改變。

byte b=2;
b+=2;
b+=b++;//b=b+b++
System.out.println(b);

執行結果

8

8.三種交換變數的方式:

  • 第一種:通過第三個變數來備份某一個變數實現交換
int a=2,b=5;
int c;
c=a;
a=b;
b=c;
System.out.println("a="+a+"\t\tb="+b);
  • 第二種:通過相加的方式
int a=2,b=5;
int c=a+b;
a=c-a;
b=c-b;//也可以寫成b=c-a;
System.out.println("a="+a+"\t\tb="+b);
  • 第三種:通過異或的方式,如果對x異或y兩次,結果為x。
int a=2,b=5;
a=a^b;
b=a^b;//相當於b=a^b^b,異或兩次後變回原值
a=a^b;//相當於a=a^b^a,對b異或兩次還是b

9.switch語句表示式:可以使byte、short、char、int四種基本型別或這四種基本型別的包裝器型別。也可以使列舉型別或字串型別。會先計算表示式,然後和case中的值進行比較。然後執行case後面的所有語句。所以在當前case語句末尾要加break。 switch對字串型別的處理:遇到字串時,會先將switch語句拆分為兩個switch語句。第一個switch語句根據物件的雜湊嗎來對一個臨時變數賦值,第二個switch會根據臨時變數的值來匹配case表示式的值。