- 浏览: 154765 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
lovelimx:
最后一个java文件第37行 orignal = new S ...
JAVA笔试面试必考题系列(六)——字符串(String)杂谈 -
ponlya:
下午又去下了个eclipse3.4,再按这方法,ok了。谢谢楼 ...
eclipse 3.4 下配置 Hibernate tool工具 -
ponlya:
如楼主所说的第1,2步,我在第3步中怎么得不到那个文件夹?换用 ...
eclipse 3.4 下配置 Hibernate tool工具 -
chinaboby2008:
...
JBoss目录结构说明 -
chinaboby2008:
这是java中的j2se部分。是java的基础呢。
有关Java容器的基础知识
JAVA面试题解惑系列(十一)——这些运算符你是否还记得?
关键字: java 面试题 自增 自减 位运算符
作者:臧圩人(zangweiren)
网址:http://zangweiren.iteye.com
>>>转载请注明出处!<<<
有些运算符在JAVA语言中存在着,但是在实际开发中我们或许很少用到它们,在面试题中却时常出现它们的身影,对于这些运算符的含义和用法,你是否还记得呢?
自增(++)和自减(--)运算符
我们先来回答几个问题吧:
这段代码运行后,i等于多少?j等于多少?k等于多少?太简单了?好,继续:
代码执行后i、j、k分别等于多少呢?还是很简单?好,再继续:
这段代码运行后输出结果是什么?0?1?
上面这段代码可以编译通过吗?为什么?如果你能顺利回答到这里,说明你对自增和自减运算符的掌握已经很好了。
为了分析出上面提出的几个问题,我们首先来回顾一下相关知识:
在第一个例子中,int j=i++;是后缀式,因此i的值先被赋予j,然后再自增1,所以这行代码运行后,i=1、j=0;而int k=--i;是前缀式,因此i先自减1,然后再将它的值赋予k,因此这行代码运行后,i=0、k=0。
在第二个例子中,对于int j=i++ + ++i;,首先运行i++,i的值0被用于加运算(+),之后i自增值变为1,然后运行++i,i先自增变为2,之后被用于加运算,最后将i两次的值相加的结果0+2=2赋给j,因此这行代码运行完毕后i=2、j=2;对于int k=--i + i--;用一样的思路分析,具体过程在此不再赘述,结果应该是i=0、k=2。
自增与自减运算符还遵循以下规律:
下面的这个例子验证以上列出的规律,它可以编译通过并执行。
按位运算符
你还能说出来按位运算符一共有哪几种吗?对比下面的列表看看,有没有从你的记忆中消失了的:
这里不像我们看到的逻辑运算符(与运算&&、或运算||、非运算!)操作的是布尔值true或false,或者是一个能产生布尔值的表达式;“按位运算符”所指的“位”就是二进制位,因此它操作的是二进制的0和1。在解释按位运算符的执行原理时,我们顺便说说它们和逻辑运算符的区别。
[list=1]逻辑运算符只能操作布尔值或者一个能产生布尔值的表达式;按位运算符能操作整型值,包括byte、short、int、long,但是不能操作浮点型值(即float和double),它还可以操作字符型(char)值。按位运算符不能够操作对象,但是在Java5.0及以上版本中,byte、short、int、long、char所对应的包装器类是个例外,因为JAVA虚拟机会自动将它们转换为对应的基本类型的数据。
下面的例子验证了这条规律:
运行结果:
逻辑运算符的运算遵循短路形式,而按位运算符则不是。所谓短路就是一旦能够确定运算的结果,就不再进行余下的运算。下面的例子更加直观地展现了短路与非短路的区别:
运行结果:
运行结果已经很明显地显示了短路和非短路的区别,我们一起来分析一下产生这个运行结果的原因。当运行“ot.leftCondition() && ot.rightCondition()”时,由于方法leftCondition()返回了false,而对于“&&”运算来说,必须要运算符两边的值都为true时,运算结果才为true,因此这时候就可以确定,不论rightCondition()的返回值是什么,“ot.leftCondition() && ot.rightCondition()”的运算值已经可以确定是false,由于逻辑运算符是短路的形式,因此在这种情况下,rightCondition()方法就不再被运行了。
而对于“ot.leftNumber() & ot.rightNumber()”,由于“leftNumber()”的返回值是0,对于按位运算符“&”来说,必须要运算符两边的值都是1时,运算结果才是1,因此这时不管“rightNumber()”方法的返回值是多少,“ot.leftNumber() & ot.rightNumber()”的运算结果已经可以确定是0,但是由于按位运算符是非短路的,所以rightNumber()方法还是被执行了。这就是短路与非短路的区别。
[/list]
移位运算符
移位运算符和按位运算符一样,同属于位运算符,因此移位运算符的位指的也是二进制位。它包括以下几种:
注意,移位运算符不存在“无符号左移位(<<<)”一说。与按位运算符一样,移位运算符可以用于byte、short、int、long等整数类型,和字符串类型char,但是不能用于浮点数类型float、double;当然,在Java5.0及以上版本中,移位运算符还可用于byte、short、int、long、char对应的包装器类。我们可以参照按位运算符的示例写一个测试程序来验证,这里就不再举例了。
与按位运算符不同的是,移位运算符不存在短路不短路的问题。
写到这里就不得不提及一个在面试题中经常被考到的题目:
这里所谓的最有效率,实际上就是通过最少、最简单的运算得出想要的结果,而移位是计算机中相当基础的运算了,用它来实现准没错了。左移位“<<”把被操作数每向左移动一位,效果等同于将被操作数乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。因此最有效率的计算2乘以8的方法就是“2<<3”。
最后,我们再来考虑一种情况,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,结果会是怎样呢?比如,1<<35=?呢?
这里就涉及到移位运算的另外一些规则:
下面的测试代码验证了以上的规律:
运行结果:
下一期预告:JAVA面试题解惑系列(十二)——你真的了解数组吗?
网址:http://zangweiren.iteye.com
>>>转载请注明出处!<<<
有些运算符在JAVA语言中存在着,但是在实际开发中我们或许很少用到它们,在面试题中却时常出现它们的身影,对于这些运算符的含义和用法,你是否还记得呢?
自增(++)和自减(--)运算符
我们先来回答几个问题吧:
int i = 0; int j = i++; int k = --i;
这段代码运行后,i等于多少?j等于多少?k等于多少?太简单了?好,继续:
int i = 0; int j = i++ + ++i; int k = --i + i--;
代码执行后i、j、k分别等于多少呢?还是很简单?好,再继续:
int i=0; System.out.println(i++);
这段代码运行后输出结果是什么?0?1?
float f=0.1F; f++; double d=0.1D; d++; char c='a'; c++;
上面这段代码可以编译通过吗?为什么?如果你能顺利回答到这里,说明你对自增和自减运算符的掌握已经很好了。
为了分析出上面提出的几个问题,我们首先来回顾一下相关知识:
- 自增(++):将变量的值加1,分前缀式(如++i)和后缀式(如i++)。前缀式是先加1再使用;后缀式是先使用再加1。
- 自减(--):将变量的值减1,分前缀式(如--i)和后缀式(如i--)。前缀式是先减1再使用;后缀式是先使用再减1。
在第一个例子中,int j=i++;是后缀式,因此i的值先被赋予j,然后再自增1,所以这行代码运行后,i=1、j=0;而int k=--i;是前缀式,因此i先自减1,然后再将它的值赋予k,因此这行代码运行后,i=0、k=0。
在第二个例子中,对于int j=i++ + ++i;,首先运行i++,i的值0被用于加运算(+),之后i自增值变为1,然后运行++i,i先自增变为2,之后被用于加运算,最后将i两次的值相加的结果0+2=2赋给j,因此这行代码运行完毕后i=2、j=2;对于int k=--i + i--;用一样的思路分析,具体过程在此不再赘述,结果应该是i=0、k=2。
自增与自减运算符还遵循以下规律:
- 可以用于整数类型byte、short、int、long,浮点类型float、double,以及字符串类型char。
- 在Java5.0及以上版本中,它们可以用于基本类型对应的包装器类Byte、Short、Integer、Long、Float、Double、Character。
- 它们的运算结果的类型与被运算的变量的类型相同。
下面的这个例子验证以上列出的规律,它可以编译通过并执行。
- public class Test {
- public static void main(String[] args) {
- // 整型
- byte b = 0;
- b++;
- // 整型
- long l = 0;
- l++;
- // 浮点型
- double d = 0.0;
- d++;
- // 字符串
- char c = 'a';
- c++;
- // 基本类型包装器类
- Integer i = new Integer(0);
- i++;
- }
- }
public class Test { public static void main(String[] args) { // 整型 byte b = 0; b++; // 整型 long l = 0; l++; // 浮点型 double d = 0.0; d++; // 字符串 char c = 'a'; c++; // 基本类型包装器类 Integer i = new Integer(0); i++; } }
按位运算符
你还能说出来按位运算符一共有哪几种吗?对比下面的列表看看,有没有从你的记忆中消失了的:
- 按位与运算(&):二元运算符。当被运算的两个值都为1时,运算结果为1;否则为0。
- 按位或运算(|):二元运算符。当被运算的两个值都为0时,运算结果为0;否则为1。
- 按位异或运算(^):二元运算符。当被运算的两个值中任意一个为1,另一个为0时,运算结果为1;否则为0。
- 按位非运算(~):一元运算符。当被运算的值为1时,运算结果为0;当被运算的值为0时,运算结果为1。
这里不像我们看到的逻辑运算符(与运算&&、或运算||、非运算!)操作的是布尔值true或false,或者是一个能产生布尔值的表达式;“按位运算符”所指的“位”就是二进制位,因此它操作的是二进制的0和1。在解释按位运算符的执行原理时,我们顺便说说它们和逻辑运算符的区别。
[list=1]
下面的例子验证了这条规律:
- 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));
- // 浮点型
- float f1 = 0.8F, f2 = 0.5F;
- // 编译报错,按位运算符不能用于浮点数类型
- // System.out.println("(float)0.8 & (float)0.5 = " + (f1 & f2));
- }
- }
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)); // 浮点型 float f1 = 0.8F, f2 = 0.5F; // 编译报错,按位运算符不能用于浮点数类型 // System.out.println("(float)0.8 & (float)0.5 = " + (f1 & f2)); } }
运行结果:
- (byte)10 & (byte)20 = 0
- (char)a | (char)A = 97
- (Long)555 ^ (Long)666 = 177
- public class OperatorTest {
- public boolean leftCondition() {
- System.out.println("执行-返回值:false;方法:leftCondition()");
- return false;
- }
- public boolean rightCondition() {
- System.out.println("执行-返回值:true;方法:rightCondition()");
- return true;
- }
- public int leftNumber() {
- System.out.println("执行-返回值:0;方法:leftNumber()");
- return 0;
- }
- public int rightNumber() {
- System.out.println("执行-返回值: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();
- }
- }
public class OperatorTest { public boolean leftCondition() { System.out.println("执行-返回值:false;方法:leftCondition()"); return false; } public boolean rightCondition() { System.out.println("执行-返回值:true;方法:rightCondition()"); return true; } public int leftNumber() { System.out.println("执行-返回值:0;方法:leftNumber()"); return 0; } public int rightNumber() { System.out.println("执行-返回值: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(); } }
运行结果:
- 执行-返回值:false;方法:leftCondition()
- 执行-返回值:0;方法:leftNumber()
- 执行-返回值:1;方法:rightNumber()
运行结果已经很明显地显示了短路和非短路的区别,我们一起来分析一下产生这个运行结果的原因。当运行“ot.leftCondition() && ot.rightCondition()”时,由于方法leftCondition()返回了false,而对于“&&”运算来说,必须要运算符两边的值都为true时,运算结果才为true,因此这时候就可以确定,不论rightCondition()的返回值是什么,“ot.leftCondition() && ot.rightCondition()”的运算值已经可以确定是false,由于逻辑运算符是短路的形式,因此在这种情况下,rightCondition()方法就不再被运行了。
而对于“ot.leftNumber() & ot.rightNumber()”,由于“leftNumber()”的返回值是0,对于按位运算符“&”来说,必须要运算符两边的值都是1时,运算结果才是1,因此这时不管“rightNumber()”方法的返回值是多少,“ot.leftNumber() & ot.rightNumber()”的运算结果已经可以确定是0,但是由于按位运算符是非短路的,所以rightNumber()方法还是被执行了。这就是短路与非短路的区别。
[/list]
移位运算符
移位运算符和按位运算符一样,同属于位运算符,因此移位运算符的位指的也是二进制位。它包括以下几种:
- 左移位(<<):将操作符左侧的操作数向左移动操作符右侧指定的位数。移动的规则是在二进制的低位补0。
- 有符号右移位(>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,如果被操作数的符号为正,则在二进制的高位补0;如果被操作数的符号为负,则在二进制的高位补1。
- 无符号右移位(>>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,无论被操作数的符号是正是负,都在二进制位的高位补0。
注意,移位运算符不存在“无符号左移位(<<<)”一说。与按位运算符一样,移位运算符可以用于byte、short、int、long等整数类型,和字符串类型char,但是不能用于浮点数类型float、double;当然,在Java5.0及以上版本中,移位运算符还可用于byte、short、int、long、char对应的包装器类。我们可以参照按位运算符的示例写一个测试程序来验证,这里就不再举例了。
与按位运算符不同的是,移位运算符不存在短路不短路的问题。
写到这里就不得不提及一个在面试题中经常被考到的题目:
引用
请用最有效率的方法计算出2乘以8等于几?
这里所谓的最有效率,实际上就是通过最少、最简单的运算得出想要的结果,而移位是计算机中相当基础的运算了,用它来实现准没错了。左移位“<<”把被操作数每向左移动一位,效果等同于将被操作数乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。因此最有效率的计算2乘以8的方法就是“2<<3”。
最后,我们再来考虑一种情况,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,结果会是怎样呢?比如,1<<35=?呢?
这里就涉及到移位运算的另外一些规则:
- byte、short、char在做移位运算之前,会被自动转换为int类型,然后再进行运算。
- byte、short、int、char类型的数据经过移位运算后结果都为int型。
- long经过移位运算后结果为long型。
- 在左移位(<<)运算时,如果要移位的位数大于被操作数对应数据类型所能表示的最大位数,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。比如1<<35=1<<(35%32)=1<<3=8。
- 对于有符号右移位(>>)运算和无符号右移位(>>>)运算,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。。比如100>>35=100>>(35%32)=100>>3=12。
下面的测试代码验证了以上的规律:
- 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)));
- }
- }
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))); } }
运行结果:
- 1 << 3 = 8
- (byte) 1 << 35 = 8
- (short) 1 << 35 = 8
- (char) 1 << 35 = 8
- 1 << 35 = 8
- 1L << 67 = 8
- new Integer(1) << 3 = 8
- 10000 >> 3 = 1250
- 10000 >> 35 = 1250
- 10000L >>> 67 = 1250
下一期预告:JAVA面试题解惑系列(十二)——你真的了解数组吗?
发表评论
-
JAVA笔试面试必考题系列(十)——话说多线程
2009-07-01 10:59 4143JAVA面试题解惑系列(十)——话说多线程 关键字: jav ... -
JAVA笔试面试必考题系列(九)——继承、多态、重载和重写
2009-07-01 10:58 2370JAVA面试题解惑系列(九 ... -
JAVA笔试面试必考题系列(八)——聊聊基本类型(内置类型)
2009-07-01 10:57 1420JAVA面试题解惑系列(八)——聊聊基本类型(内置类型) 关 ... -
JAVA笔试面试必考题系列(七)——日期和时间的处理
2009-07-01 10:56 1466JAVA面试题解惑系列(七)——日期和时间的处理 关键字: ... -
JAVA笔试面试必考题系列(六)——字符串(String)杂谈
2009-07-01 10:55 2247JAVA面试题解惑系列(六)——字符串(String)杂谈 ... -
JAVA笔试面试必考题系列(五)——传了值还是传了引用?
2009-07-01 10:53 1248JAVA面试题解惑系列(五)——传了值还是传了引用? 关键字 ... -
JAVA笔试面试必考题系列(四)——final、finally和finalize的区别
2009-07-01 10:52 1197JAVA面试题解惑系列(四 ... -
JAVA笔试面试必考题系列(三)——变量(属性)的覆盖
2009-07-01 10:50 1190JAVA面试题解惑系列(三)——变量(属性)的覆盖 关键字: ... -
java笔试面试必考题(二)到底创建了几个String对象
2009-06-24 16:10 1540(二)到底创建了几个String对象?关键字: java 面试 ... -
java笔试必考题(一)类的初始化顺序
2009-06-24 15:34 1377(一)类的初始化顺序关键字: java 面试题 初始化 发布时 ... -
各种排序算法java实现
2009-05-11 16:40 868插入排序: package org.rut.util.a ... -
笔试(一)
2009-05-08 10:16 1130一、判断题(30分) 1. ... -
程序员面试之葵花宝典
2009-05-08 10:15 1196程序员面试之葵花宝典 面向对象的特征有哪些 ...
相关推荐
绝对经典JAVA面试笔试教程 绝对神器 JAVA笔试面试必备
JAVA笔试面试宝典JAVA笔试面试宝典JAVA笔试面试宝典JAVA笔试面试宝典
百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试面试150题 百度历年java笔试...
java面试笔试资料java笔试题大集合及答案题库java笔试题汇总资料188个合集 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx ...
java面试笔试题库java软件设计java笔试题大集合及答案文档资料合集300MB“ 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx 8张...
JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题JAVA笔试题,面试题
java面试笔试题库java学习比较开发教程互联网公司面试资料大全合集: 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring面试问答.docx 8张图解...
吉利汽车Java笔试面试题.zip_面试资料下载
笔试面试题.doc————电子版_doc版
Java常见笔试、面试系列深度剖析第2讲 张龙 风中叶
基本上包括了所有java的笔试和面试题目,汇集了网上的各类java笔试面试题目,希望对大家有所帮助。
java工程师面试题大全-100%公司笔试题你都能碰到几个.docx Java开发工程师上机笔试题.docx Java开发求职面试题.docx Java开发笔试题.docx Java数据结构类面试题.docx Java数据结构题.docx Java笔试面试宝典.docx ...
java面试笔试资料Java经典项目集锦java笔试题大集合及答案题库java笔试题汇总资料个合集(188) 100家大公司java笔试题汇总.doc 125条常见的java 面试笔试题大汇总.pdf 2011最新整理java经典代码.doc 25个经典的Spring...
详细收录了JAVA常见的笔试面试题,有JAVA基础,JAVA WEB,SCRIPT,AJAX等
java 面试宝典 Java中的23种设计模式 Java面试141题 Java入门需掌握的30个基本概念
Java必备推荐面试笔试宝典学习技巧Java必备推荐面试笔试宝典学习技巧Java必备推荐面试笔试宝典学习技巧Java必备推荐面试笔试宝典学习技巧Java必备推荐面试笔试宝典学习技巧Java必备推荐面试笔试宝典学习技巧Java必备...
java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题 java笔试面试题
超全的java笔试面试必备试题,让你从容应对java方方面面,也可做学习之用。 希望您成功胜出。 加油。
Python基础——笔试面试利器
Java 面试题汇总 2 Java笔试题及答案 26 大唐电信JAVA笔试题面试题 27 西安电讯盈科java笔试题 27 华为Java笔试题: 28 Java多线程常见面试题 31 ...java面试笔试必考题-抽象类与接口 107 Java面试宝典2011版 112