xml地图|网站地图|网站标签 [设为首页] [加入收藏]

Java操作符总结,到底有多小

来源:http://www.ruibiaowang.com 作者:国家域名安全中心 人气:182 发布时间:2019-10-24
摘要:原标题:浓厚 V8 引擎:“小平头”到底有多小?        Java语言中的表明式是由运算符与操作数组合而成的,所谓的演算符正是用来做运算的号子。        在Java中的运算符,基

原标题:浓厚 V8 引擎:“小平头”到底有多小?

        Java语言中的表明式是由运算符与操作数组合而成的,所谓的演算符正是用来做运算的号子。
        在Java中的运算符,基本上可分为算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、转型运算符等。

原文:V8 Internals: How Small is a “Small Integer?”

链接:

作者:Franziska Hinkelmann

译者:justjavac(迷渡)

风姿洒脱、算术运算符        所谓算术运算符,约等于我们数学中学到的加、减、乘、除等运算。这么些操作可以对多少个不等品种的数字进行混合运算,为了确定保障操作的精度,系统在运算的长河中会做相应的改变。
      1、数字精度        所谓数字精度,也正是系统在做数字之间的算术运算时,为了尽最大大概地保障计算机的精确性,而活动举行相应的转移,将分裂的数据类型转变为精度最高的数据类型。准则如下:
      1)当使用运算符把多个操作数结合到共同期,在开展演算前八个操作数会转产生相似的种类。
      2)三个操作数中有叁个是double类型的,则另贰个将转变来double型。
      3)五个操作数中有一个是float类型的,则另一个将也转移成float型。
      4)多个操作数中有八个是long类型的,则另一个将也转变来long型。
      5)任何别的系列的操作,七个操作数都要转变来int类型。
      2、整数型运算(int型)
       对于int型的相干操作,加、减、乘的结果都以极其轻便精晓的,重视讲一下除(/)的演算。
       多个整数相除的结果是整数,那或多或少与数学中是分歧的,在Java中,八个整数相除的结果肖似于数学中的求模运算。整除的余数是用%象征,比如15 / 2 = 7,并非7.5,15 % 2 = 1。大家用程序验证一下:

原稿副标题:“When binary is useful outside of a coding interview”

/*两个整数相除及求余数*/

public class Divide
{
   public static void main(String[] args)
   {
      int a = 15;
      int b = 2;
      double c = 2;
      System.out.println(a + "/" + b + "=" + (a / b));
      System.out.println(a + "%"+ b + "=" + (a % b));
      System.out.println(a + "/" + c + "=" + (a / c));
      System.out.println(a + "%" + c + "=" + (a % c));
    }
}

V8 是谷歌(Google)的开源 Java 引擎。Chrome,Node.js 和大多别样应用程序都应用了 V8 引擎。假诺您早已听过关于 V8 的解说,或许读过有关 V8 的文章:Understanding V8’s Bytecode(中文:),你一定据书上说过 Smis,小整数。本文通过深刻 V8 的源代码,具体切磋一下 Smis到底有多大。

出口结果:
                 15 / 2 = 7
                 15 % 2 = 1
                 15 / 2.0  =  7.5
                 15 % 2.0 = 1.0

依附规范,Java 并不知道整数(除了近日引进的 BigInts)(中文:)。它只略知生机勃勃二 IEEE 浮点数。不过众多操作都是依据整数,比方程序中的 for循环。全部 Java 引擎都有三个极度的整数表示方法。V8 有所谓的 Smis小卡尺头。

        3、自增和自减运算符
        在循环与垄断(monopoly)中,我们平日会用到相近于计数器的运算,它们的风味是每一遍的操作都是加1或减1。在Java中提供了自增、自减运算符,X++使变量X的脚下值每一次扩充1,而X--是自减运算符,每便操作使当前X的值减1。举个例子:

Smis在 64 位平台上的限制是 -2³¹ 到 2³¹-1(2³¹≈2*10⁹)。假让你查看 V8 源码,那恐怕并不是那些肯定。 kSmiMinValue并 kSmi马克斯Value在 include/v8.h 中定义如下:

/*测试自增、自减操作*/

public class SelfAction
{
   public static void main(String[] args)
   {
     int x = 10;
     int a = x+ x++;
     System.out.println("a =" + a);
     System.out.println("x =" + x);
     int b = x + ++x;
     System.out.println("b =" + b);
     System.out.println("x =" + x);
     int c = x + x--;
     System.out.println("c =" + c);
     System.out.println("x =" + x);
     int d = x + --x;
     System.out.println("d =" + d);
     System.out.println("x =" + x);
   }
}  
  1. static const int kSmiMinValue = (static_cast<unsigned int>(-1)) << (kSmiValueSize — 1);
  2. static const int kSmiMaxValue = -(kSmiMinValue + 1);

出口结果:
                 a = 20
                 x = 11
                 b = 23
                 x = 12
                 c = 24
                 x = 11
                 d = 21
                 x = 10

它是哪些等于 -2³¹ 和 2³¹-1 的吧?让我们将地方的 C++ 代码分解一下。

二、关系运算符         Java具备康健的关系运算符。那个涉嫌运算符基本上同数学中的关系运算符是一模一样的。“>”大于、“<”小于、“>=”大于等于、“<=”小于等于、“==”等于、“!=”不等于。例如:

左移

/*关系运算符测试*/

public class RelationTest
{
   public static void main(String[] args)
   {
     boolean x, y, z;
     int a = 15;
     int b = 2;
     double c =15;
     x = a > b;  //true;
     y = a < b;  //false;
     z = a != b;  //true;
     System.out.println("x =" + x);
     System.out.println("y =" + y);
     System.out.println("z =" + z);
   }
}

<<是按位左移运算。左移意味着大家将数字的二进制表示移到左边手,并用零填充左侧。比如,5 << 3 = 40。

输出结果:
                 x = true
                 y = false
                 z = true

图片 1

三、逻辑运算符
        在Java语言中有两种逻辑运算符,它们是NOT(非,以符号“!”表示)、AND(与,以符号“&&”表示、)OR(或,以符号“||”表示)。
        1、NOT运算符          NOT运算符是用来代表相反的意思。
                        NOT逻辑关系值表                           

你或者早就注意到了,正数的左移与乘以 2 相仿。

A

!A

true

false

false

true

静态转变为无符号整数

         2、AND运算符          AND运算符表示“与”的意思,也正是和的意思。
                       AND逻辑关系值表

  1. static_cast<unsigned int>(-1)

A

B

A&&B

false

false

false

true

false

false

当大家将负值转变为无符号整数(即正数)时会产生什么?全部的二进制位保持不改变,但值的象征却昨今不一致了。调换为无符号整数后,大家就足以把这么些数作为正数来张开左移运算了。

false

true

false

true

true

true

那么 -1的二进制表示是怎么着吗?在二进制补码中, -1代表为 (111...111)_2因为 2⁶³-2⁶²-2⁶¹- … -2²-2¹–1 = 1。

         3、OR运算符
         O奥迪Q5运算符是用来表示“或”有如我们平时生活中精晓的相近,两个只要有叁个为“真”,结果就为“真”。
                     O奥迪Q5逻辑关系值表

图片 2

A

B

A||B

false

false

false

true

false

true

false

true

true

合在一齐

true

true

true

借使您查看 V8 源代码中的 definitions,您会发觉在 64 位Computer上 kSmiValueSize被定义为 32,于是:

/*逻辑运算符测试*/

public class LogicSign
{
   public static void main(String[] args)
   {
     boolean x, y, z, a, b;
     a = 'a' > 'b';
     b = 'R' != 'r';
     x = !a;
     y = a && b;
     z = a || b;
     System.out.println("x =" + x);
     System.out.println("y =" + y);
     System.out.println("z =" + z);
   }
}
  1. kSmiMinValue =(static_cast<unsigned int>(-1)) << (kSmiValueSize — 1)
  2. = (111...111)_2 << (32-1)
  3. = (111...111)_2 << 31
  4. = (11...1100...00)_2 // 31个零
  5. = -2^31

输出结果:
                 x = true
                 y = false
                 z = true

今日我们能够采取那些结果来对 k马克斯Value进行起初化。

       4、“短路”现象
       在选择逻辑运算符进行连锁的操作时,大家会遇到风姿浪漫种很有意思的情景;短路现象。
       对于true && false依照大家的描述,处理的结果已然是false了,也正是说无论前边是结果是“真”照旧“假”,整个讲话的结果分明是false了,所以系统就觉着曾经远非须求再实行相比下去了。也就不会再实践了,这种理象便是大家所说的围堵现象。

  1. int kSmiMaxValue = -(kSmiMinValue + 1);

四、位运算符
          全体的数据、消息在微型Computer中都以以二进制格局存在的。大家得以对整数的二进制位实行相关的操作。那正是按位运算符,它根本总结:位的“与”、位的“或”、位的“非”、位的“异或”。
        1)位的“与”,用符号“&”表示,它属于二元运算符。 与位运算值表:

明显, kSmi马克斯Value=-(-2^31+1)=2^31-1。在 64 位平台上 V8 对 Smis定义的限量是 [-2³¹,2³¹-1]。

A

B

A&B

1

1

1

1

0

0

0

1

0

32 位平台

0

0

0

在 32 位平台上 kSmiValueSize=31。所以大家把它换为 30,总计获得 kMinValue=-2^30。注意,2³⁰≈10⁹。

         2)位的“或”用符号“|”表示,它属于二元运算符。。   或位运算值表:

为什么 Smis在 33位平台上的限量要小一些啊?在汽油发动机内部,V8 使用最低有效位将具有 Java 值标识为客栈对象或然 Smis。若是低于有效位是 1,则是指针。就算是 0,则是 Smi。那意味 32 位整数只好使用 33位存款和储蓄 Smi值,因为一个人(最低有效位)用作标记。

A

B

A|B

1

1

1

0

1

1

1

0

1

V8 使用最低有效位将拥有值标记为 Smis 或堆指针。

0

0

0

实则 Smis并从未你想象的那么小,但它们相当轻便以按位编码的章程来囤积到 32 位或 64 位整数中。

          3)位的“非”,用符号“~”表示,它是一元运算符,只对单个自变量起功能。它的效果是使二进制按位“取反”。 非位运算值表:

附加题:给定贰个非空的卡尺头数组,其中有些成分只现身了三回,别的各个元素都冒出了两回。找到十一分独一成分。您能够利用二进制表示方法,时间复杂度为 O(n),空间复杂度为 O(1),你能找到施工方案吗? class="backword">再次来到今日头条,查看越来越多

A

~A

1

0

0

1

主要编辑:

           4)位的“异或”,用符号“^”表示,它属于二元运算符。异或位运算值表:

A

B

A^B

1

1

0

0

1

1

1

0

1

0

0

0

/*测试位的四种运算*/

public class BitOperation
{
 public static void main(String[] args)
 {
  int a = 15;
  int b = 2;
  int x = a & b;
  int y = a | b;
  int z = a ^ b;
  System.out.println(a + "&" + b + "=" + x);
  System.out.println(a + "|" + b + "=" + y);
  System.out.println(a + "^" + b + "=" + z);
 }
}

出口结果:
                  15 & 2 = 2
                  15 | 2 = 15
                  15 ^ 2 = 13

五、移位运算符

        移位运算符正是在二进制的根基上对数字举办移动。根据活动的可行性和填充数字的平整分为三种:<<(左移)、>>(带符号右移)和>>>(无符号右移)。
  在运动运算时,byte、short和char类型移位后的结果会化为int类型,对于byte、short、char和int举办移动时,规定实际活动的次数是运动次数和32的余数,也正是活动二十六次和活动1次拿走的结果同样。移动long型的数值时,规定实际活动的次数是运动次数和64的余数,也便是活动陆18遍和活动2次拿走的结果同样。
二种运动运算符的移位法规和平运动用如下所示:
<<运算法则:
按二进制方式把具备的数字向左移动对应的位数,高位移出(废弃),低位的空位补零。
  语法格式:   须求活动的数字 << 移位的次数
  比方: 3 << 2,则是将数字3左移2位
  测算进程:   3 << 2
  首先把3转移为二进制数字0000 0000 0000 0000 0000 0000 0000 0011,然后把该数字高位(左边)的八个零移出,其余的数字都朝左平移2位,最终在未有(左侧)的八个空位补零。则收获的末段结出是0000 0000 0000 0000 0000 0000 0000 1100,则转移为十进制是12.数学意义:
  在数字还未溢出的前提下,对刘阳数和负数,左移壹位都也正是乘以2的1次方,左移n位就一定于乘以2的n次方。
>>运算规则:按二进制格局把具备的数字向右移动对应巍峨位数,低位移出(放任),高位的空位补符号位,即正数补零,负数补1.
  语法格式:   须求活动的数字 >> 移位的次数
  例如11 >> 2,则是将数字11右移2位
  测算进度:11的二进制格局为:0000 0000 0000 0000 0000 0000 0000 1011,然后把未有的末尾多少个数字移出,因为该数字是正数,所以在高位补零。则赢得的结尾结出是0000 0000 0000 0000 0000 0000 0000 0010.调换为十进制是3.数学意义:右移一位也正是除2,右移n位也正是除以2的n次方。
>>>运算准则:按二进制方式把持有的数字向右移动对应巍峨位数,低位移出(遗弃),高位的空位补零。对李樯数来讲和带符号右移相仿,对于负数来讲不一致。
  别的组织和>>相近。
  小结
  二进制运算符,蕴含位运算符和活动运算符,使程序猿能够在二进制基础上操作数字,能够更平价的张开演算,而且能够以二进制的款型积累和转移数据,是实现互联网合同拆解解析以致加密等算法的底蕴。
  实例操作:   

public class URShift {
  public static void main(String[] args) {
  int i = -1;
  i >>>= 10;
  //System.out.println(i);
  mTest();
  }
  public static void mTest(){
  //左移
  int i = 12; //二进制为:0000000000000000000000000001100
  i <<= 2; //i左移2位,把高位的两位数字(左侧开始)抛弃,低位的空位补0,二进制码就为0000000000000000000000000110000
  System.out.println(i); //二进制110000值为48;
  System.out.println("<br>");
  //右移
  i >>=2; //i右移2为,把低位的两个数字(右侧开始)抛弃,高位整数补0,负数补1,二进制码就为0000000000000000000000000001100
  System.out.println(i); //二进制码为1100值为12
  System.out.println("<br>");
  //右移example
  int j = 11;//二进制码为00000000000000000000000000001011
  j >>= 2; //右移两位,抛弃最后两位,整数补0,二进制码为:00000000000000000000000000000010
  System.out.println(j); //二进制码为10值为2
  System.out.println("<br>");
  byte k = -2; //转为int,二进制码为:0000000000000000000000000000010
  k >>= 2; //右移2位,抛弃最后2位,负数补1,二进制吗为:11000000000000000000000000000
  System.out.println(j); //二进制吗为11值为2
  }
  }

  在Thinking in Java第三章中的意气风发段话:
  移位运算符面向的演算对象也是
  二进制的“位”。 可独立用它们管理整数类型(主类型的风度翩翩种)。左移位运算符(<<)能将运算符左侧的演算对象向左移动运算符侧面钦赐的位数(在未有补0)。 “有暗记”右移位运算符(>>)则将运算符左侧的运算对象向右移动运算符左侧钦赐的位数。“有标记”右移位运算符使用了“符号扩大”:若值为正,则在高位插入0;若值为负,则在高位插入1。Java也加多了黄金时代种“无符号”右移位运算符(>>>),它利用了“零恢弘”:无论正负,都在高位插入0。这一运算符是C或C++未有的。
  若对char,byte或许short实行活动管理,那么在活动进行事先,它们会自动转换来贰个int。唯有右边手的5个未有才会用到。那样可卫戍大家在二个int数里活动不合实际的位数。若对贰个long值进行管理,最终收获的结果也 是long。此时只会用到右边手的6个未有,制止移动超过long值里现有的位数。但在打开“无符号”右移位时,也大概碰到贰个标题。若对byte或 short值实行右移位运算,获得的只怕不是科学的结果(Java 1.0和Java 1.1特意卓越)。它们会活动转变来int类型,并展开右移位。但“零恢弘”不会生出,所以在此些景况下会取得-1的结果。   


Java 定义的位运算(bitwise operators )直接对整数类型的位张开操作,这一个整数类型包罗long,int,short,char,and byte 。表5.1 列出了位运算:
表5.1 位运算符及其结果

运算符 结果
~ 按位非(NOT)(一元运算)
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XO奔驰G级)
>> 右移
>>> 右移,左侧空出的位以0填充
运算符 结果
<< 左移
&= 按位与赋值
|= 按位或赋值
^= 按位异或赋值
>>= 右移赋值
>>>= 右移赋值,左侧空出的位以0填充
<<= 左移赋值

续表

既然如此位运算符在整数范围内对位操作,由此精晓那样的操作会对三个值产生如何效果与利益是主要的。具体地说,知道Java 是如何存款和储蓄整数值並且怎么着表示负数的是有效的。由此,在承继研究在此以前,让大家大约概述一下那多个话题。

具备的整数类型以二进制数字位的调换及其宽度来代表。例如,byte 型值42的二进制代码是00101010 ,当中每一种岗位在那表示2的次方,在最左侧的位以20上马。向左下三个职位将是21,或2,依次向左是22,或4,然后是8,16,32等等,由此及彼。因而42在其任务1,3,5的值为1(从左边以0起头数);那样42是21+23+25的和,也正是2+8+32 。

具有的平头类型(除了char 类型之外)都是有暗记的整数。那象征她们不仅可以表示正数,又能表示负数。Java 使用我们知晓的2的补码(two’s complement )这种编码来代表负数,也正是通过将与其相应的正数的二进制代码取反(就要1形成0,将0形成1),然后对其结果加1。举例,-42正是由此将42的二进制代码的逐一位取反,即对00101010 取反得到11010101 ,然后再加1,获得11010110 ,即-42 。要对八个负数解码,首先对其兼具的位取反,然后加1。比如-42,或11010110 取反后为00101001 ,或41,然后加1,那样就赢得了42。

要是虚构到零的交叉(zero crossing )难点,你就便于通晓Java (甚至其余大部语言)那样用2的补码的缘由。假定byte 类型的值零用00000000 代表。它的补码是独有将它的各个人取反,即生成11111111 ,它象征负零。但难题是负零在整数数学中是行不通的。为了化解负零的标题,在选取2的补码代表负数的值时,对其值加1。即负零11111111 加1后为100000000 。但这么使1位太靠左而不适合重回到byte 类型的值,因而公众规定,-0和0的象征方法黄金时代致,-1的解码为11111111 。固然大家在此个事例使用了byte 类型的值,但同样的着力的条件也适用于具备Java 的整数类型。

因为Java 使用2的补码来存款和储蓄负数,何况因为Java 中的全数整数都以有号子的,那样应用位运算符能够轻松地到达意料之外的结果。举例,不管您怎么着绸缪,Java 用高位来代表负数。为幸免那几个讨厌的古怪,请深深记住不管高位的生机勃勃一如何,它决定贰个整数的暗号。

5.1 位逻辑运算符
位逻辑运算符有“与”(AND)、“或”(OPRADO)、“异或(XO瑞虎)”、“非(NOT)”,分别用“&”、“|”、“^”、“~”表示,4-3 表展现了种种位逻辑运算的结果。在这里起彼伏研讨以前,请记住位运算符应用于每一个运算数内的各样独立的位。
表5.2  位逻辑运算符的结果
A 0 1 0 1 B 0 0 1 1 A | B 0 1 1 1 A & B 0 0 0 1 A ^ B 0 1 1 0 ~A 1 0 1 0

按位非(NOT)

按位非也称为补,一元运算符NOT“~”是对其运算数的每一人取反。例如,数字42,它的二进制代码为:

00101010

通过按位非运算成为

11010101

按位与(AND)

按位与运算符“&”,假若四个运算数都以1,则结果为1。其余意况下,结果均为零。看上面包车型地铁例证:

00101010 42 &00001111 15

00001010 10

按位或(OR)

按位或运算符“|”,任何八个运算数为1,则结果为1。如下边包车型地铁例子所示:

00101010 42 | 00001111 15

00101111 47

按位异或(XO逍客)

按位异或运算符“^”,唯有在多少个比较的位不一致不平时间其结果是 1。不然,结果是零。上边的例子彰显了“^”运算符的效用。那个例子也申明了XO奥迪Q7运算符的一个一蹴而就的品质。注意第贰个运算数有数字1的位,42对应二进制代码的相应位是哪些被撤换的。第三个运算数有数字0的位,第叁个运算数对应位的数字不改变。当对少数类别进行位运算时,你将会见到这么些性情的用途。

00101010 42 ^ 00001111 15

00100101 37
位逻辑运算符的行使

上边包车型大巴事例表达了位逻辑运算符:

// Demonstrate the bitwise logical operators.
class BitLogic {
public static void main(String args[]) {
String binary[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"

};
int a = 3; // 0 + 2 + 1 or 0011 in binary
int b = 6; // 4 + 2 + 0 or 0110 in binary
int c = a | b;
int d = a & b;
int e = a ^ b;
int f = (~a & b) | (a & ~b);
int g = ~a & 0x0f;

System.out.println(" a = " + binary[a]);
System.out.println(" b = " + binary[b]);
System.out.println(" a|b = " + binary[c]);
System.out.println(" a&b = " + binary[d]);
System.out.println(" a^b = " + binary[e]);
System.out.println("~a&b|a&~b = " + binary[f]);
System.out.println(" ~a = " + binary[g]);
}
} 

    在本例中,变量a与b对应位的三结合代表了二进制数全数的 4 种组合情势:0-0,0-1,1-0 ,和1-1 。“|”运算符和“&”运算符分别对变量a与b各类对应位的运算得到了变量c和变量d的值。对变量e和f的赋值表达了“^”运算符的功用。字符串数组binary 代表了0到15 对应的二进制的值。在本例中,数组各要素的排列顺序展现了变量对应值的二进制代码。数组之所以如此构造是因为变量的值n对应的二进制代码能够被精确的囤积在数组对应成分binary[n] 中。举例变量a的值为3,则它的二进制代码对应地蕴藏在数组元素binary[3] 中。~a的值与数字0x0f (对应二进制为0000 1111 )进行按位与运算的目标是减小~a的值,保障变量g的结果小于16。因而该程序的运作结果能够用数组binary 对应的成分来表示。该程序的输出如下:

a = 0011 b = 0110 a|b = 0111 a&b = 0010 a^b = 0101 ~a&b|a&~b = 0101 ~a = 1100

5.2 左移运算符
左移运算符<<使钦定值的具备位都左移规定的次数。它的通用格式如下所示:

value << num
这里,num 钦命要运动值value 移动的位数。相当于,左移运算符<<使钦点值的具有位都左移num位。每左移一个位,高阶位都被移出(何况废弃),并用0填充侧面。这意味着当左移的运算数是int 类型时,每移动1位它的第叁十五个人将要被移出並且吐弃;当左移的运算数是long 类型时,每移动1位它的第六11人将要被移出何况抛弃。

在对byte 和short类型的值进行运动运算时,你不得不小心。因为你驾驭Java 在对表达式求值时,将自动把那一个种类扩充为 int 型,並且,表明式的值也是int 型。对byte 和short类型的值举办活动运算的结果是int 型,何况假使左移不超越三11人,原本对应各位的值也不会吐弃。可是,即便你对一个负的byte 恐怕short类型的值举办移动运算,它被扩大为int 型后,它的号子也被扩充。那样,整数值结果的上位就能被1填充。由此,为了拿走准确的结果,你将在废弃得到结果的上位。那样做的最轻松易行方法是将结果转变为byte 型。上边包车型客车程序表明了那或多或少:

// Left shifting a byte value.
class ByteShift {


public static void main(String args[]) {
byte a = 64, b;
int i;


i = a << 2;
b = (byte) (a << 2);


System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
}
}

该程序发生的出口下所示:
Original value of a: 64
i and b: 256 0
因变量a在赋值表明式中,故被扩大为int 型,64(0100 0000 )被左移两遍生成值256 (10000 0000 )被赋给变量i。不过,经过左移后,变量b中惟风流倜傥的1被移出,低位全体成了0,由此b的值也形成了0。
既是每一遍左移都得以使本来的操作数翻倍,技术员们日常使用这么些法子来进展快速的2 的乘法。但是你要小心,若是你将1移进高阶位(31或陆11人),那么该值将改为负值。上面包车型地铁次序表达了那或多或少:

// Left shifting as a quick way to multiply by 2.
class MultByTwo {


public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;


for(i=0; i<4; i++) {
num = num << 1;
System.out.println(num);


}
} 

    这里,num 内定要活动值value 移动的位数。也正是,左移运算符<<使钦点值的装有位都左移num位。每左移二个位,高阶位都被移出(並且舍弃),并用0填充右侧。那表示当左移的运算数是int 类型时,每移动1位它的第34位就要被移出并且丢掉;当左移的运算数是long 类型时,每移动1位它的第63个人将要被移出并且扬弃。

    在对byte 和short类型的值实行移动运算时,你一定要当心。因为你知道Java 在对表明式求值时,将活动把那一个品种扩充为 int 型,何况,表明式的值也是int 型。对byte 和short类型的值实行运动运算的结果是int 型,并且只要左移不超过三十位,原本对应各位的值也不会放弃。可是,假如您对八个负的byte 或许short类型的值进行运动运算,它被扩展为int 型后,它的暗记也被扩展。那样,整数值结果的上位就能被1填充。由此,为了获取准确的结果,你将在废弃得到结果的高位。那样做的最简易方法是将结果转换为byte 型。上边包车型地铁主次表明了这或多或少:

// Left shifting a byte value.
class ByteShift {


public static void main(String args[]) {
byte a = 64, b;
int i;


i = a << 2;
b = (byte) (a << 2);


System.out.println("Original value of a: " + a);
System.out.println("i and b: " + i + " " + b);
}
} 

该程序发生的输出下所示:
Original value of a: 64
i and b: 256 0
    因变量a在赋值表明式中,故被扩大为int 型,64(0100 0000 )被左移一遍生成值256 (10000 0000 )被赋给变量i。不过,经过左移后,变量b中独步天下的1被移出,低位全体成了0,因此b的值也化为了0。
    既然每一趟左移都得以使本来的操作数翻倍,工程师们时有的时候应用这些措施来拓宽神速的2 的乘法。不过你要小心,如果您将1移进高阶位(31或63人),那么该值将变为负值。上面包车型大巴程序说明了那或多或少:

// Left shifting as a quick way to multiply by 2.
class MultByTwo {


public static void main(String args[]) {
int i;
int num = 0xFFFFFFE;


for(i=0; i<4; i++) {
num = num << 1;
System.out.println(num);


}
}
} 

该程序的出口如下所示:

536870908
1073741816
2147483632
-32

初值经过留心选用,以便在左移 4 位后,它会发出-32。正如你看看的,当1被移进31 位时,数字被解释为负值。

5.3  右移运算符
右移运算符>>使钦命值的全部位都右移规定的次数。它的通用格式如下所示:

value >> num

那边,num 内定要运动值value 移动的位数。也正是,右移运算符>>使钦命值的装有位都右移num位。上面包车型大巴前后相继片段将值32右移2次,将结果8赋给变量a:

int a = 32;
a = a >> 2; // a now contains 8

当班值日中的有个别位被“移出”时,这几个位的值将放弃。比如,上面包车型地铁主次片段将35右移2 次,它的2个未有被移出放任,也将结果8赋给变量a:

int a = 35;
a = a >> 2; // a still contains 8

用二进制表示该进度能够更清楚地阅览程序的运行进度:

00100011 35
>> 2
00001000 8

将值每右移二回,就一定于将该值除以2而且遗弃了余数。你能够动用这一个天性将三个平头进行高效的2的除法。当然,你势须求保管您不会将该数原有的别样一个人移出。

右移时,被移走的最高位(最左侧的位)由原本最高位的数字补充。比如,假设要移走的值为负数,每次右移都在侧面补1,如若要移走的值为正数,每三回右移都在左臂补0,那称之为符号位扩大(保留符号位)(sign extension ),在举办右移操作时用来保持负数的符号。比如,–8 >> 1 是–4,用二进制表示如下:

11111000 –8 >>1 11111100 –4

三个要静心的有意思问题是,由于符号位扩张(保留符号位)每趟都会在高位补1,由此-1右移的结果总是–1。一时你不指望在右移时保留符号。譬如,上边包车型客车例子将贰个byte 型的值转变为用十二
进制表示。注意右移后的值与0x0f举办按位与运算,那样能够放任任何的号子位扩充,以便拿到的值能够用作定义数组的下标,从而赢得相应数组元素代表的十五进制字符。

// Masking sign extension.
class HexByte {
static public void main(String args[]) {

char hex[] = {
’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’,
’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’
};
byte b = (byte) 0xf1;

System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}} 

该程序的输出如下:
b = 0xf1
5.4  无符号右移
    正如上边刚刚看见的,每一趟右移,>>运算符总是自动地用它的先前最高位的内容补它的万丈位。那样做保留了原值的符号。但有时那并不是大家想要的。举个例子,倘让你实行移动操作的演算数不是数字值,你就不愿意实行标志位扩大(保留符号位)。当您管理像素值或图表时,这种气象是一定普及的。在这里种气象下,不管运算数的初值是什么样,你愿意移位后连连在高位(最右边)补0。那正是人人所说的无符号移动(unsigned shift )。那时你能够利用Java 的无符号右移运算符>>> ,它总是在左臂补0。

    上面包车型客车程序段表达了无符号右移运算符>>> 。在本例中,变量a被赋值为-1,用二进制表示正是叁九位全部是1。这几个值然后被无符号右移23人,当然它忽视了符号位扩张,在它的左侧总是补0。那样得到的值255被赋给变量a。

int a = -1; a = a >>> 24;

下边用二进制情势越来越求证该操作:

11111111 11111111 11111111 11111111 int型-1的二进制代码>>> 24 无标识右移25位00000000 00000000 00000000 11111111 int型255的二进制代码

鉴于无符号右移运算符>>> 只是对三十二个人和陆十位的值有含义,所以它并不像您想像的那样有用。因为你要铭记在心,在表达式中过小的值总是被电动扩展为int 型。这表示符号位扩张和平运动动总是发出在三12个人并不是8位或拾肆个人。那样,对第7位以0开头的byte 型的值举办无符号移动是不只怕的,因为在骨子里活动运算时,是对扩充后的三十三个人值实行操作。上面包车型大巴例证表明了那一点:

// Unsigned shifting a byte value.
class ByteUShift {
static public void main(String args[]) {
进制表示。注意右移后的值与0x0f进行按位与运算,这样可以舍弃任何的符号位扩展,以便得到的值可以作为定义数组的下标,从而得到对应数组元素代表的十六进制字符。
// Masking sign extension.
class HexByte {
static public void main(String args[]) {

char hex[] = {
’0’, ’1’, ’2’, ’3’, ’4’, ’5’, ’6’, ’7’,
’8’, ’9’, ’a’, ’b’, ’c’, ’d’, ’e’, ’f’’
};
byte b = (byte) 0xf1;

System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]);}} 

该程序的出口如下:

b = 0xf1

5.4 无标记右移
正如上边刚刚看到的,每回右移,>>运算符总是自动地用它的先前最高位的剧情补它的参天位。那样做保留了原值的号子。但偶然那并非我们想要的。举个例子,假若您进行运动操作的运算数不是数字值,你就不希望进行标识位扩充(保留符号位)。当你管理像素值或图表时,这种情状是一对大器晚成布满的。在此种景况下,不管运算数的初值是何等,你愿意移位后连连在高位(最侧面)补0。那正是大家所说的无符号移动(unsigned shift )。这时你能够动用Java 的无符号右移运算符>>> ,它总是在左边补0。

下边包车型大巴程序段表达了无符号右移运算符>>> 。在本例中,变量a被赋值为-1,用二进制表示就是34人全都以1。那一个值然后被无符号右移25个人,当然它忽视了符号位扩充,在它的右侧总是补0。那样得到的值255被赋给变量a。

int a = -1; a = a >>> 24;

下边用二进制格局越来越验证该操作:

11111111 11111111 11111111 11111111 int型-1的二进制代码>>> 24 无标识右移23位00000000 00000000 00000000 11111111 int型255的二进制代码

是因为无符号右移运算符>>> 只是对33个人和六13位的值有含义,所以它并不像你想象的那样有用。因为您要铭记在心,在表明式中过小的值总是被自动增加为int 型。那意味符号位扩大和移动总是发出在34位并非8位或16人。那样,对第7位以0开头的byte 型的值实行无符号移动是不可能的,因为在其实活动运算时,是对扩展后的三十人值实行操作。下边包车型客车例子表明了那点:

// Unsigned shifting a byte value.
class ByteUShift {
static public void main(String args[]) {
int b = 2;
int c = 3;

a |= 4;
b >>= 1;
c <<= 1;
a ^= c;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
}
} 

该程序的出口如下所示:

a = 3
b = 1
c = 6

六、赋值运算符        

赋值运算符是程序中最常用的演算符了,只要有变量的注脚,将要有赋值运算。如a

3;这里的a大家都晓得是变量名,依据前边对变量的概念,我们得以理解这里的a实际上正是内部存款和储蓄器空间的多少个名字,它对应的是意气风发段内部存储器空间,后生可畏在要在此个空间放入3那个值。那些归入的历程就兑现了赋值的长河。
              赋值运算一览表

运算符

一般表示法

Java语言表示法

+=

a = a + b

a += b

-=

a = a - b

a -= b

*=

a = a * b

a *=b

/=

a=a / b

a /= b

%=

a = a % b

a %= b

>>=

a = a >> b

a >>= b

>>>=

a = a >>> b

a >>>= b

七、伊利运算符         伊利运算符比超级少有,因为它有五个运算对象,但它也的确属于运算符的生机勃勃种,因为它谈起底也是发出三个值。它也足以转正为尺度判定语句,只不过这种管理情势更简单、明了。
        它的演算进程是那样的:
         尽管“布尔表达式”的结果是“true”,就回去值0;
         如若“布尔表达式”的结果是“false”,就回来值1;
         它的再次回到值做为最终结出重返。

八、逗号运算符
        在Java中,逗号运算符的天下无双使用场所就是在for循环语句中。

九、字符串运算符         “+”号这些运算符,在Java中有风流倜傥项极其的用法,它不只起到一而再不一致的字符串,还大概有后生可畏种隐式的转型成效。

十、转型运算符
        转型运算符能够说是生机勃勃种新鲜的运算符,它是将后生可畏体系型的数额或对象,强制转换为另生龙活虎种档案的次序。

/*强制转型测量试验*/

public class TypeTran
{
   public static void main(String[] args)
   {
     int x ;
     double y;
     x = (int)22.5 + (int)34.7;  //强制转型恐怕引起精度错过
     y = (double)x;
     System.out.println("x = " + x);
     System.out.println("y = " + y);
   }
}
输出结果:
                  x = 56
                  y = 56.0
分析:
          能够窥见,由于强制转型,使数码精度遗失。系统会忽视强制转型的检查。所以对于强制转型,必得精晓转型是还是不是可行。

         最后总括一下运算符的先行级

运算符

优先级

括号()

1最高

++、--

2

~、!

3

*、/、%

4

+、-(减)

5

<<、>>、>>>

6

>、<、>=、<=

7

==、!=

8

&

9

^

10

|

11

&&

12

||

13

? :

14

本文由澳门新葡萄京娱乐网站发布于国家域名安全中心,转载请注明出处:Java操作符总结,到底有多小

关键词:

最火资讯