我什么时候应该使用这种int变量?

java.awt.Event类中的一些int变量是按位设置的。 如下所示:

/** * This flag indicates that the Shift key was down when the event * occurred. */ public static final int SHIFT_MASK = 1 << 0; /** * This flag indicates that the Control key was down when the event * occurred. */ public static final int CTRL_MASK = 1 << 1; /** * This flag indicates that the Meta key was down when the event * occurred. For mouse events, this flag indicates that the right * button was pressed or released. */ public static final int META_MASK = 1 << 2; /** * This flag indicates that the Alt key was down when * the event occurred. For mouse events, this flag indicates that the * middle mouse button was pressed or released. */ public static final int ALT_MASK = 1 << 3; 

为什么不使用递增1的整数直接编码。

 public static final int SHIFT_MASK = 1; public static final int CTRL_MASK = 2; public static final int META_MASK = 3; public static final int ALT_MASK = 4; 

有历史原因还是程序员的编码习惯?

也许你可以使用a&b来比较两个变量,但是a == b也可以。

它适合某些情况吗?如果是的话,你能举个例子吗?

希望得到你的回答,谢谢。

如果你看一下它的二进制forms,它会更有意义:

 1 << 0 : 00000001 1 << 1 : 00000010 1 << 2 : 00000100 1 << 3 : 00001000 

这种位图通常允许您同时传递多于1个值(作为某种修饰符)。

因此,您可能会看到以下内容:

 // modifiers is a single int if ((modifiers & SHIFT_MASK) != 0) { // shift pressed } if ((modifiers & CTRL_MASK) != 0) { // ctrl pressed }.... 

(如果将它们定义为1,2,3,4,则不能这样做)

你可以认为它正在传递一组位。 这种掩码用于确定特定位是“ON”,还是打开/关闭特定位而不影响其他位

我不知道这里是否需要另一个答案,但我认为没有真正解释为什么你要这样做。

至于这种语法的原因,他们将它作为一个位域实现。 bitfield是一种将一堆布尔值存储在内存中的单个位置的方法。 这曾经很常见,仍然很有用。 一个拥有60个布尔值的对象(除了本身就是一个糟糕的设计)需要60×4个字节来存储,bit-packing可以将所有60个布尔值放入一个长度(4位备用)。 如果你有100万个这个对象的实例,那么打包你的位意味着需要8MB存储空间(100万个8字节长)和需要240MB存储空间(100万x 60个布尔值,每个占用4个字节)之间的差异。

这些天你几乎不应该使用位域 – 我们通常没有内存问题,并且有更好的结构可用。 当你开始将数据组合到位域时,操作实际上变得非常慢(这就是为什么java使用整个32位int来存储每个布尔值而不是为你打包它们)。

顺便说一句,了解打包数据结构仍然很重要,因为互联网上的数据经常被打包,有人必须编写代码来解压缩它(不得不写一次mp4头解码器,一塌糊涂)

另一个有趣的问题,为什么说“1 << 0”和“1 << 4”而不是只说“1”和“16”。 这是一件非常好的事情。 布局时,这些常量非常易读 - 第一个位置有一位,第五个位置有一位。 你只需看一眼就知道该位的确切位置。 指定该位的第二个最简单的方法是十六进制,如果你很好,你就知道0x0400是0000010000000000.最糟糕的是十进制,因为除非你是一个学者或者只是在计算机上工作很多你不会知道知道哪个位位置是1024或32768,并且设置2位的常数将是非常困难的。

编码方式符合您的意图,并且可以用另一种人类认为最自然的语言轻松理解,这是一种神奇的习惯。 这些天我通常使用它的代码如下:

 public final long SHORT_DELAY = 8000 public final long LONG_DELAY = 85808000 

是8000秒,8000天? 此外,当数字变得很长时,很难解析。

我更喜欢:

 public final long sec= 1000 public final long min=sec * 60 public final long hour=min * 60 public final long SHORT_DELAY = 8 * sec public final long LONG_DELAY = 2 * hour + 23 * min + 8 * sec 

这只是编码的一个问题,读者可以清楚地看到,而你引用的代码就是一个很好的例子,所以如果这就是“编码风格”,那就意味着它很棒,而且绝对是相关的。

为什么这样? 正如在其他答案中指出的那样,值是2的幂,因此你设置了一点。 假设您想测试一组条件。

然后你可以组合比特,例如,

SOME_COMBO_CONDITION = SHIFT_MASK | ALT_MASK

然后测试是否通过执行设置两个位来测试该条件

current_condition&SOME_COMBO_CONDITION

使用整数代码,您必须使用更复杂的条件进行测试。

示例很简单,假设控制移位键被按下。 使用上面的代码,这会使bitstring像这样:

 ...11 

为了使它具体化,让我们使用一个8位字符串,比如说:

 0111 0011 

这可能表示可能已经压下了几个键,但是您可能只对移位和控制键感兴趣。 如果您想知道何时按下shift键和控制键,您可以创建一个新组合:

 CTRL_AND_SHIFT_MASK = SHIFT_MASK | CTR_MASK; 

然后你可以做一个按位并确定返回的位串是否同时按下了控制键和Shift键:

 final boolean isCtrlAndShift = (CTRL_AND_SHIFT_MASK & val) == CTRL_AND_SHIFT_MASK; 

通过按位进行,如果CTRL和SHIFT的两个位都不 1,那么’和将导致两个位中的一个变为0.所有其他位都将为0(因为它们在CTRL_AND_SHIFT_MASK为0) 。 因此,如果您and它的值为val那么它应该返回您的CTRL_AND_SHIFT_MASK否则只有一个或两个都没有被压抑。

因为这些值不会增加一个。 它们是2的幂,用于按位或 – 或 – 二进制 – 等等进行测试。

 int[] arr = { 1 << 0, 1 << 1, 1 << 2, 1 << 3 }; System.out.println(Arrays.toString(arr)); 

输出是

 [1, 2, 4, 8] 

这是写n的一种方式,其中n<<右边的数字。