亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

JAVA面試題解惑系列(十一)——這些運(yùn)算符你是

系統(tǒng) 1739 0

好東西分享

有些運(yùn)算符在JAVA語言中存在著,但是在實(shí)際開發(fā)中我們或許很少用到它們,在面試題中卻時常出現(xiàn)它們的身影,對于這些運(yùn)算符的含義和用法,你是否還記得呢?

自增(++)和自減(--)運(yùn)算符

我們先來回答幾個問題吧:

Java代碼 復(fù)制代碼
  1. int ?i?=? 0 ; ??
  2. int ?j?=?i++; ??
  3. int ?k?=?--i;??
    int i = 0;
int j = i++;
int k = --i;

  


這段代碼運(yùn)行后,i等于多少?j等于多少?k等于多少?太簡單了?好,繼續(xù):

Java代碼 復(fù)制代碼
  1. int ?i?=? 0 ; ??
  2. int ?j?=?i++?+?++i; ??
  3. int ?k?=?--i?+?i--;??
    int i = 0;
int j = i++ + ++i;
int k = --i + i--;

  


代碼執(zhí)行后i、j、k分別等于多少呢?還是很簡單?好,再繼續(xù):

Java代碼 復(fù)制代碼
  1. int ?i= 0 ; ??
  2. System.out.println(i++);??
    int i=0;
System.out.println(i++);

  


這段代碼運(yùn)行后輸出結(jié)果是什么?0?1?

Java代碼 復(fù)制代碼
  1. float ?f= 0 .1F; ??
  2. f++; ??
  3. double ?d= 0 .1D; ??
  4. d++; ??
  5. char ?c= 'a' ; ??
  6. c++;??
    float f=0.1F;
f++;
double d=0.1D;
d++;
char c='a';
c++;

  


上面這段代碼可以編譯通過嗎?為什么?如果你能順利回答到這里,說明你對自增和自減運(yùn)算符的掌握已經(jīng)很好了。

為了分析出上面提出的幾個問題,我們首先來回顧一下相關(guān)知識:

  • 自增(++):將變量的值加1,分前綴式(如++i)和后綴式(如i++)。前綴式是先加1再使用;后綴式是先使用再加1。
  • 自減(--):將變量的值減1,分前綴式(如--i)和后綴式(如i--)。前綴式是先減1再使用;后綴式是先使用再減1。


在第一個例子中,int j=i++;是后綴式,因此i的值先被賦予j,然后再自增1,所以這行代碼運(yùn)行后,i=1、j=0;而int k=--i;是前綴式,因此i先自減1,然后再將它的值賦予k,因此這行代碼運(yùn)行后,i=0、k=0。

在第二個例子中,對于int j=i++ + ++i;,首先運(yùn)行i++,i的值0被用于加運(yùn)算(+),之后i自增值變?yōu)?,然后運(yùn)行++i,i先自增變?yōu)?,之后被用于加運(yùn)算,最后將i兩次的值相加的結(jié)果0+2=2賦給j,因此這行代碼運(yùn)行完畢后i=2、j=2;對于int k=--i + i--;用一樣的思路分析,具體過程在此不再贅述,結(jié)果應(yīng)該是i=0、k=2。

自增與自減運(yùn)算符還遵循以下規(guī)律:

  1. 可以用于整數(shù)類型byte、short、int、long,浮點(diǎn)類型float、double,以及字符串類型char。
  2. 在Java5.0及以上版本中,它們可以用于基本類型對應(yīng)的包裝器類Byte、Short、Integer、Long、Float、Double、Character。
  3. 它們的運(yùn)算結(jié)果的類型與被運(yùn)算的變量的類型相同。


下面的這個例子驗(yàn)證以上列出的規(guī)律,它可以編譯通過并執(zhí)行。

Java代碼 復(fù)制代碼
  1. public ? class ?Test?{ ??
  2. ???? public ? static ? void ?main(String[]?args)?{ ??
  3. ???????? //?整型 ??
  4. ???????? byte ?b?=? 0 ; ??
  5. ????????b++; ??
  6. ???????? //?整型 ??
  7. ???????? long ?l?=? 0 ; ??
  8. ????????l++; ??
  9. ???????? //?浮點(diǎn)型 ??
  10. ???????? double ?d?=? 0.0 ; ??
  11. ????????d++; ??
  12. ???????? //?字符串 ??
  13. ???????? char ?c?=? 'a' ; ??
  14. ????????c++; ??
  15. ???????? //?基本類型包裝器類 ??
  16. ????????Integer?i?=? new ?Integer( 0 ); ??
  17. ????????i++; ??
  18. ????} ??
  19. }??
    public class Test {
	public static void main(String[] args) {
		// 整型
		byte b = 0;
		b++;
		// 整型
		long l = 0;
		l++;
		// 浮點(diǎn)型
		double d = 0.0;
		d++;
		// 字符串
		char c = 'a';
		c++;
		// 基本類型包裝器類
		Integer i = new Integer(0);
		i++;
	}
}
  



按位運(yùn)算符

你還能說出來按位運(yùn)算符一共有哪幾種嗎?對比下面的列表看看,有沒有從你的記憶中消失了的:

  1. 按位與運(yùn)算(&):二元運(yùn)算符。當(dāng)被運(yùn)算的兩個值都為1時,運(yùn)算結(jié)果為1;否則為0。
  2. 按位或運(yùn)算(|):二元運(yùn)算符。當(dāng)被運(yùn)算的兩個值都為0時,運(yùn)算結(jié)果為0;否則為1。
  3. 按位異或運(yùn)算(^):二元運(yùn)算符。當(dāng)被運(yùn)算的兩個值中任意一個為1,另一個為0時,運(yùn)算結(jié)果為1;否則為0。
  4. 按位非運(yùn)算(~):一元運(yùn)算符。當(dāng)被運(yùn)算的值為1時,運(yùn)算結(jié)果為0;當(dāng)被運(yùn)算的值為0時,運(yùn)算結(jié)果為1。


這里不像我們看到的邏輯運(yùn)算符(與運(yùn)算&&、或運(yùn)算||、非運(yùn)算!)操作的是布爾值true或false,或者是一個能產(chǎn)生布爾值的表達(dá)式;“按位運(yùn)算符”所指的“位”就是二進(jìn)制位,因此它操作的是二進(jìn)制的0和1。在解釋按位運(yùn)算符的執(zhí)行原理時,我們順便說說它們和邏輯運(yùn)算符的區(qū)別。

[list=1]

  • 邏輯運(yùn)算符只能操作布爾值或者一個能產(chǎn)生布爾值的表達(dá)式;按位運(yùn)算符能操作整型值,包括byte、short、int、long,但是不能操作浮點(diǎn)型值(即float和double),它還可以操作字符型(char)值。按位運(yùn)算符不能夠操作對象,但是在Java5.0及以上版本中,byte、short、int、long、char所對應(yīng)的包裝器類是個例外,因?yàn)镴AVA虛擬機(jī)會自動將它們轉(zhuǎn)換為對應(yīng)的基本類型的數(shù)據(jù)。
    下面的例子驗(yàn)證了這條規(guī)律:
    Java代碼 復(fù)制代碼
    1. public ? class ?BitOperatorTest?{ ??
    2. ???? public ? static ? void ?main(String[]?args)?{ ??
    3. ???????? //?整型 ??
    4. ???????? byte ?b1?=? 10 ,?b2?=? 20 ; ??
    5. ????????System.out.println( "(byte)10?&?(byte)20?=?" ?+?(b1?&?b2)); ??
    6. ???????? //?字符串型 ??
    7. ???????? char ?c1?=? 'a' ,?c2?=? 'A' ; ??
    8. ????????System.out.println( "(char)a?|?(char)A?=?" ?+?(c1?|?c2)); ??
    9. ???????? //?基本類型的包裝器類 ??
    10. ????????Long?l1?=? new ?Long( 555 ),?l2?=? new ?Long( 666 ); ??
    11. ????????System.out.println( "(Long)555?^?(Long)666?=?" ?+?(l1?^?l2)); ??
    12. ???????? //?浮點(diǎn)型 ??
    13. ???????? float ?f1?=? 0 .8F,?f2?=? 0 .5F; ??
    14. ???????? //?編譯報(bào)錯,按位運(yùn)算符不能用于浮點(diǎn)數(shù)類型 ??
    15. ???????? //?System.out.println("(float)0.8?&?(float)0.5?=?"?+?(f1?&?f2)); ??
    16. ????} ??
    17. }??
          public class BitOperatorTest {
    	public static void main(String[] args) {
    		// 整型
    		byte b1 = 10, b2 = 20;
    		System.out.println("(byte)10 & (byte)20 = " + (b1 & b2));
    		// 字符串型
    		char c1 = 'a', c2 = 'A';
    		System.out.println("(char)a | (char)A = " + (c1 | c2));
    		// 基本類型的包裝器類
    		Long l1 = new Long(555), l2 = new Long(666);
    		System.out.println("(Long)555 ^ (Long)666 = " + (l1 ^ l2));
    		// 浮點(diǎn)型
    		float f1 = 0.8F, f2 = 0.5F;
    		// 編譯報(bào)錯,按位運(yùn)算符不能用于浮點(diǎn)數(shù)類型
    		// System.out.println("(float)0.8 & (float)0.5 = " + (f1 & f2));
    	}
    }
    
        

    運(yùn)行結(jié)果:
    • (byte)10 & (byte)20 = 0
    • (char)a | (char)A = 97
    • (Long)555 ^ (Long)666 = 177
  • 邏輯運(yùn)算符的運(yùn)算遵循短路形式,而按位運(yùn)算符則不是。所謂短路就是一旦能夠確定運(yùn)算的結(jié)果,就不再進(jìn)行余下的運(yùn)算。下面的例子更加直觀地展現(xiàn)了短路與非短路的區(qū)別:
    Java代碼 復(fù)制代碼
    1. public ? class ?OperatorTest?{ ??
    2. ???? public ? boolean ?leftCondition()?{ ??
    3. ????????System.out.println( "執(zhí)行-返回值:false;方法:leftCondition()" ); ??
    4. ???????? return ? false ; ??
    5. ????} ??
    6. ??
    7. ???? public ? boolean ?rightCondition()?{ ??
    8. ????????System.out.println( "執(zhí)行-返回值:true;方法:rightCondition()" ); ??
    9. ???????? return ? true ; ??
    10. ????} ??
    11. ??
    12. ???? public ? int ?leftNumber()?{ ??
    13. ????????System.out.println( "執(zhí)行-返回值:0;方法:leftNumber()" ); ??
    14. ???????? return ? 0 ; ??
    15. ????} ??
    16. ??
    17. ???? public ? int ?rightNumber()?{ ??
    18. ????????System.out.println( "執(zhí)行-返回值:1;方法:rightNumber()" ); ??
    19. ???????? return ? 1 ; ??
    20. ????} ??
    21. ??
    22. ???? public ? static ? void ?main(String[]?args)?{ ??
    23. ????????OperatorTest?ot?=? new ?OperatorTest(); ??
    24. ??
    25. ???????? if ?(ot.leftCondition()?&&?ot.rightCondition())?{ ??
    26. ???????????? //?do?something ??
    27. ????????} ??
    28. ????????System.out.println(); ??
    29. ??
    30. ???????? int ?i?=?ot.leftNumber()?&?ot.rightNumber(); ??
    31. ????} ??
    32. }??
          public class OperatorTest {
    	public boolean leftCondition() {
    		System.out.println("執(zhí)行-返回值:false;方法:leftCondition()");
    		return false;
    	}
    
    	public boolean rightCondition() {
    		System.out.println("執(zhí)行-返回值:true;方法:rightCondition()");
    		return true;
    	}
    
    	public int leftNumber() {
    		System.out.println("執(zhí)行-返回值:0;方法:leftNumber()");
    		return 0;
    	}
    
    	public int rightNumber() {
    		System.out.println("執(zhí)行-返回值:1;方法:rightNumber()");
    		return 1;
    	}
    
    	public static void main(String[] args) {
    		OperatorTest ot = new OperatorTest();
    
    		if (ot.leftCondition() && ot.rightCondition()) {
    			// do something
    		}
    		System.out.println();
    
    		int i = ot.leftNumber() & ot.rightNumber();
    	}
    }
    
        

    運(yùn)行結(jié)果:
    • 執(zhí)行-返回值:false;方法:leftCondition()
    • 執(zhí)行-返回值:0;方法:leftNumber()
    • 執(zhí)行-返回值:1;方法:rightNumber()

    運(yùn)行結(jié)果已經(jīng)很明顯地顯示了短路和非短路的區(qū)別,我們一起來分析一下產(chǎn)生這個運(yùn)行結(jié)果的原因。當(dāng)運(yùn)行“ot.leftCondition() && ot.rightCondition()”時,由于方法leftCondition()返回了false,而對于“&&”運(yùn)算來說,必須要運(yùn)算符兩邊的值都為true時,運(yùn)算結(jié)果才為true,因此這時候就可以確定,不論rightCondition()的返回值是什么,“ot.leftCondition() && ot.rightCondition()”的運(yùn)算值已經(jīng)可以確定是false,由于邏輯運(yùn)算符是短路的形式,因此在這種情況下,rightCondition()方法就不再被運(yùn)行了。
    而對于“ot.leftNumber() & ot.rightNumber()”,由于“l(fā)eftNumber()”的返回值是0,對于按位運(yùn)算符“&”來說,必須要運(yùn)算符兩邊的值都是1時,運(yùn)算結(jié)果才是1,因此這時不管“rightNumber()”方法的返回值是多少,“ot.leftNumber() & ot.rightNumber()”的運(yùn)算結(jié)果已經(jīng)可以確定是0,但是由于按位運(yùn)算符是非短路的,所以rightNumber()方法還是被執(zhí)行了。這就是短路與非短路的區(qū)別。
    [/list]
    移位運(yùn)算符

    移位運(yùn)算符和按位運(yùn)算符一樣,同屬于位運(yùn)算符,因此移位運(yùn)算符的位指的也是二進(jìn)制位。它包括以下幾種:
    1. 左移位(<<):將操作符左側(cè)的操作數(shù)向左移動操作符右側(cè)指定的位數(shù)。移動的規(guī)則是在二進(jìn)制的低位補(bǔ)0。
    2. 有符號右移位(>>):將操作符左側(cè)的操作數(shù)向右移動操作符右側(cè)指定的位數(shù)。移動的規(guī)則是,如果被操作數(shù)的符號為正,則在二進(jìn)制的高位補(bǔ)0;如果被操作數(shù)的符號為負(fù),則在二進(jìn)制的高位補(bǔ)1。
    3. 無符號右移位(>>>):將操作符左側(cè)的操作數(shù)向右移動操作符右側(cè)指定的位數(shù)。移動的規(guī)則是,無論被操作數(shù)的符號是正是負(fù),都在二進(jìn)制位的高位補(bǔ)0。

    注意,移位運(yùn)算符不存在“無符號左移位(<<<)”一說。與按位運(yùn)算符一樣,移位運(yùn)算符可以用于byte、short、int、long等整數(shù)類型,和字符串類型char,但是不能用于浮點(diǎn)數(shù)類型float、double;當(dāng)然,在Java5.0及以上版本中,移位運(yùn)算符還可用于byte、short、int、long、char對應(yīng)的包裝器類。我們可以參照按位運(yùn)算符的示例寫一個測試程序來驗(yàn)證,這里就不再舉例了。

    與按位運(yùn)算符不同的是,移位運(yùn)算符不存在短路不短路的問題。

    寫到這里就不得不提及一個在面試題中經(jīng)常被考到的題目:
    引用
    請用最有效率的方法計(jì)算出2乘以8等于幾?

    這里所謂的最有效率,實(shí)際上就是通過最少、最簡單的運(yùn)算得出想要的結(jié)果,而移位是計(jì)算機(jī)中相當(dāng)基礎(chǔ)的運(yùn)算了,用它來實(shí)現(xiàn)準(zhǔn)沒錯了。左移位“<<”把被操作數(shù)每向左移動一位,效果等同于將被操作數(shù)乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。因此最有效率的計(jì)算2乘以8的方法就是“2<<3”。

    最后,我們再來考慮一種情況,當(dāng)要移位的位數(shù)大于被操作數(shù)對應(yīng)數(shù)據(jù)類型所能表示的最大位數(shù)時,結(jié)果會是怎樣呢?比如,1<<35=?呢?

    這里就涉及到移位運(yùn)算的另外一些規(guī)則:
    1. byte、short、char在做移位運(yùn)算之前,會被自動轉(zhuǎn)換為int類型,然后再進(jìn)行運(yùn)算。
    2. byte、short、int、char類型的數(shù)據(jù)經(jīng)過移位運(yùn)算后結(jié)果都為int型。
    3. long經(jīng)過移位運(yùn)算后結(jié)果為long型。
    4. 在左移位(<<)運(yùn)算時,如果要移位的位數(shù)大于被操作數(shù)對應(yīng)數(shù)據(jù)類型所能表示的最大位數(shù),那么先將要求移位數(shù)對該類型所能表示的最大位數(shù)求余后,再將被操作數(shù)移位所得余數(shù)對應(yīng)的數(shù)值,效果不變。比如1<<35=1<<(35%32)=1<<3=8。
    5. 對于有符號右移位(>>)運(yùn)算和無符號右移位(>>>)運(yùn)算,當(dāng)要移位的位數(shù)大于被操作數(shù)對應(yīng)數(shù)據(jù)類型所能表示的最大位數(shù)時,那么先將要求移位數(shù)對該類型所能表示的最大位數(shù)求余后,再將被操作數(shù)移位所得余數(shù)對應(yīng)的數(shù)值,效果不變。。比如100>>35=100>>(35%32)=100>>3=12。

    下面的測試代碼驗(yàn)證了以上的規(guī)律:
    Java代碼 復(fù)制代碼
    1. public ? abstract ? class ?Test?{ ??
    2. ???? public ? static ? void ?main(String[]?args)?{ ??
    3. ????????System.out.println( "1?<<?3?=?" ?+?( 1 ?<<? 3 )); ??
    4. ????????System.out.println( "(byte)?1?<<?35?=?" ?+?(( byte )? 1 ?<<?( 32 ?+? 3 ))); ??
    5. ????????System.out.println( "(short)?1?<<?35?=?" ?+?(( short )? 1 ?<<?( 32 ?+? 3 ))); ??
    6. ????????System.out.println( "(char)?1?<<?35?=?" ?+?(( char )? 1 ?<<?( 32 ?+? 3 ))); ??
    7. ????????System.out.println( "1?<<?35?=?" ?+?( 1 ?<<?( 32 ?+? 3 ))); ??
    8. ????????System.out.println( "1L?<<?67?=?" ?+?(1L?<<?( 64 ?+? 3 ))); ??
    9. ???????? //?此處需要Java5.0及以上版本支持 ??
    10. ????????System.out.println( "new?Integer(1)?<<?3?=?" ?+?( new ?Integer( 1 )?<<? 3 )); ??
    11. ????????System.out.println( "10000?>>?3?=?" ?+?( 10000 ?>>? 3 )); ??
    12. ????????System.out.println( "10000?>>?35?=?" ?+?( 10000 ?>>?( 32 ?+? 3 ))); ??
    13. ????????System.out.println( "10000L?>>>?67?=?" ?+?(10000L?>>>?( 64 ?+? 3 ))); ??
    14. ????} ??
    15. }??
          public abstract class Test {
    	public static void main(String[] args) {
    		System.out.println("1 << 3 = " + (1 << 3));
    		System.out.println("(byte) 1 << 35 = " + ((byte) 1 << (32 + 3)));
    		System.out.println("(short) 1 << 35 = " + ((short) 1 << (32 + 3)));
    		System.out.println("(char) 1 << 35 = " + ((char) 1 << (32 + 3)));
    		System.out.println("1 << 35 = " + (1 << (32 + 3)));
    		System.out.println("1L << 67 = " + (1L << (64 + 3)));
    		// 此處需要Java5.0及以上版本支持
    		System.out.println("new Integer(1) << 3 = " + (new Integer(1) << 3));
    		System.out.println("10000 >> 3 = " + (10000 >> 3));
    		System.out.println("10000 >> 35 = " + (10000 >> (32 + 3)));
    		System.out.println("10000L >>> 67 = " + (10000L >>> (64 + 3)));
    	}
    }
    
        

    運(yùn)行結(jié)果:
    1. 1 << 3 = 8
    2. (byte) 1 << 35 = 8
    3. (short) 1 << 35 = 8
    4. (char) 1 << 35 = 8
    5. 1 << 35 = 8
    6. 1L << 67 = 8
    7. new Integer(1) << 3 = 8
    8. 10000 >> 3 = 1250
    9. 10000 >> 35 = 1250
    10. 10000L >>> 67 = 1250
  • ?

    向原作者致敬,轉(zhuǎn)自:

    作者:臧圩人(zangweiren)
    網(wǎng)址: http://zangweiren.iteye.com

    JAVA面試題解惑系列(十一)——這些運(yùn)算符你是否還記得?


    更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

    微信掃碼或搜索:z360901061

    微信掃一掃加我為好友

    QQ號聯(lián)系: 360901061

    您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

    【本文對您有幫助就好】

    您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

    發(fā)表我的評論
    最新評論 總共0條評論
    主站蜘蛛池模板: 亚洲va高清中文字幕 | 激情影院在线观看 | 香蕉视频一级 | 日韩欧美亚洲一区精选 | 黄色影院视频 | 亚洲黄色在线视频 | 香蕉久久夜色精品国产2020 | 一本大道久久香蕉成人网 | 国产精品九九热 | 中文字幕热久久久久久久 | 日日艹夜夜艹 | 亚洲国产成人最新精品资源 | 欧美亚洲国产精品久久第一页 | 国产精品每日更新在线观看 | 精品国产高清自在线一区二区三区 | 99久久精品国产片 | 久久久精品免费视频 | 九九这里只有精品视频 | 亚洲欧美日韩国产一区二区精品 | 日本午夜大片a在线观看 | 日韩中文字幕久久精品 | 目韩一区二区三区系列片丶 | 欧美日日射 | 久久久久影视 | 日本在线不卡视频 | 欧美性视频在线激情 | 黄片一级毛片 | 日韩经典欧美一区二区三区 | 欧美亚洲国产另类 | 四虎影院最新网站 | 亚洲免费视频在线观看 | 精品久久中文网址 | 亚欧免费视频 | 一级特黄特黄的大片免费 | 欧美性啪啪 | 亚洲中字在线 | 综合图片亚洲 | 免费一级特黄a | 久久精品99毛片免费 | 久久www免费人成精品香蕉 | 国产精品毛片va一区二区三区 |