Java 为什么这些按位操作会产生大写字母?

Java 为什么这些按位操作会产生大写字母?,java,bitwise-operators,Java,Bitwise Operators,我有以下代码: static char toUpper(char c) { if (c >= 'a' && c <= 'z') return (char) (c & ~('a' - 'A')); return c; } staticchartoupper(charc) { 如果(c>='a'&&c它起作用是因为,在ASCII(与Unicode的下半部分相同)中,a的位模式是0100001(0x41),而a是0110001(0

我有以下代码:

static char toUpper(char c)
{
    if (c >= 'a' && c <= 'z')
        return (char) (c & ~('a' - 'A'));

    return c;
}
staticchartoupper(charc)
{

如果(c>='a'&&c它起作用是因为,在ASCII(与Unicode的下半部分相同)中,
a
的位模式是
0100001
0x41
),而
a
0110001
0x61

因此
'a'-'a'
0x20
0010 0000
,这是您必须在小写字母上清除的位,以使其成为大写字母

您可以从下表中看到,大写字母的范围从
0x41
0x5a
,等效的小写字母的范围从
0x61
0x7a

清除位位置的方法是
并用该位置的逻辑求反将其清除

因此(使用8位),
~0x20
0xdf
1101111
),字母
c
的操作如下:

  0110 0011     0x63 or 'c'
& 1101 1111     0xdf, or ~('a' - 'A')
  ---- ----
  0100 0011     0x43 or 'C'
有关按位运算符的更详细介绍,请参阅


当然,值得一提的是,您可以更轻松地使用:

c = Character.toUpperCase (c);

无需编写自己的函数。有关详细信息,请参阅。而且,如果您确实希望将其限制为ASCII小写字母,您仍然可以将其包装在
if
语句中,尽管我建议,如果您希望在非ASCII世界中使用应用程序,这不是一个好主意。

字符表示为数字。请请查看每个字符映射到的数字


上面的按位操作基本上将小写字母对应的数字更改为大写字母对应的数字。在Java中,字符只是无符号的16位整数

对于ascii,小写字符为97-122,对应的大写字母为65-90。因此,只需从每个值中减去32即可

如果您查看代码
(char)(c&~('a'-'a'))
,您可以从内部到外部对其进行求值开始

'a'-'a'
给出所需偏移量的负数32

~(32)
翻转位,因此您现在有了-33。这是一个位掩码,包含除第六位到最后一位1之外的所有内容

(c&-33)
应用位掩码,将适当的位设置为0。这实际上减去了32


(char)
只是对char执行不必要的强制转换(编译器无论如何都会插入强制转换)。

让我们举个例子来理解您的代码

1) 假设将字符“p”传递给方法toUpper()

2) 现在if语句中的条件将始终为true,因为任何字母表都在“a”和“z”之间

3) 在if语句中,您有以下代码

return (char) (c & ~('a' - 'A'));
4) 在上述声明中,本部分

('a' - 'A')
将始终首先执行,因为它位于括号中。在这里,您只需从'A'中减去'A',即97-65,这是ASCII值。(A-->65和A-->97)。因此,无论传递给toUpper()方法的字符是什么,答案都将始终为32

5) 那么接线员是怎么来的呢

正如我所说,'a'-'a')的答案总是32,因此运算符~应用于数字32,即

~32
要预测运算符~的输出,公式如下所示

~(number)
=-(number)-1

因为这里的数字是32,所以上面公式中~32的输出是

-(32)-1
=-32-1
=-33

那么

~('a' - 'A')
永远是-33

5) 现在你有了

(c & ~('a' - 'A'))
i、 e

这里c有用户通过的字母表,在我们的示例中是“p”

i、 e

因为“p”的ASCII值是112,即

112 & -33
i、 e

这是二进制中112和-33的对应值

所以在应用操作符之后,我们得到

1010000
6) 现在将1010000转换成十进制,我们得到80,这是大写字母“p”的ASCII值

7) 因此,一般来说,我们可以说将要执行的操作是

(ASCII value of user inputted alphabet) & -33

8) 还有一件事“Java支持Unicode。但是Unicode中的第一组字符是ASCII,也是@paxdiablo说的。所以我在上面的回答中提到了ASCII。

A'-'Z'和A'-'Z'之间的区别是一位。清除或设置该位,并将一位映射到另一位。注意:这对其他字母不起作用。
112 & -33
1110000 & 1011111
1010000
(ASCII value of user inputted alphabet) & -33