Что такое побитовые операторы?

В Java все переменные, которые вы объявляете, на самом деле являются «ссылками» на объекты (или примитивы), а не самими объектами.

При попытке выполнить один метод объекта , ссылка просит живой объект выполнить этот метод. Но если ссылка ссылается на NULL (ничего, нуль, void, nada), то нет способа, которым метод будет выполнен. Тогда runtime сообщит вам об этом, выбросив исключение NullPointerException.

Ваша ссылка «указывает» на нуль, таким образом, «Null -> Pointer».

Объект живет в памяти виртуальной машины пространство и единственный способ доступа к нему - использовать ссылки this. Возьмем этот пример:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

И в другом месте вашего кода:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

Это важно знать - когда больше нет ссылок на объект (в пример выше, когда reference и otherReference оба указывают на null), тогда объект «недоступен». Мы не можем работать с ним, поэтому этот объект готов к сбору мусора, и в какой-то момент VM освободит память, используемую этим объектом, и выделит другую.

127
задан meagar 12 April 2016 в 15:31
поделиться

7 ответов

Так как никто не начал обсуждение темы того, почему они полезны:

я использую битовые операции много при работе с флагами. Например, если Вы хотите передать серию флагов к операции (скажите, File.Open(), с Режимом чтения и Режимом записи, который оба включили), Вы могли передать их как единственное значение. Это выполняется путем присвоения каждому возможному флагу своего собственного бита в bitset (байт, короткий, международный, или долго). Например:

 Read: 00000001
Write: 00000010

Поэтому, если бы Вы хотите передать чтение И запись, Вы передали бы (ЧТЕНИЕ | ЗАПИСЬ), который затем комбинирует два в [1 118]

00000011

, Который затем может быть дешифрован на другом конце как:

if ((flag & Read) != 0) { //...

, который проверяет

00000011 &
00000001

, который возвращается

00000001

, который не является 0, таким образом, флаг действительно указывает ЧТЕНИЕ.

можно использовать XOR для переключения различных битов. Я использовал это при использовании флага для определения направленных исходных данных (Вниз, Левый, Правильный). Например, если спрайт перемещается горизонтально, и я хочу, чтобы он обернулся:

     Up: 00000001
   Down: 00000010
   Left: 00000100
  Right: 00001000
Current: 00000100

я просто XOR текущее значение с (ОСТАВЛЕННЫЙ | ПРАВО), который станет Брошенным и прямо на в этом случае.

Разрядное Смещение полезно в нескольких случаях.

x << y

совпадает с

x * 2 <глоток> y

, если необходимо быстро умножиться питанием два, но не упустить смещение 1-разрядного в главный бит - это делает число отрицательным, если это не не подписано. Это также полезно при контакте с различными размерами данных. Например, читая целое число из четырех байтов:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Предположение, что A является старшим значащим байтом и D меньше всего. Это закончилось бы как:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

Цвета часто хранятся этот путь (со старшим значащим байтом, или проигнорированным или используемым в качестве Alpha):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

Для нахождения значений снова просто сместите биты направо, пока это не будет внизу, затем маска от остающихся битов высшего порядка:

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFF совпадает с 11111111. Таким образом, по существу, для Красного, Вы сделали бы это:

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)
182
ответ дан 24 November 2019 в 00:45
поделиться

Стоит отметить, что одноразрядные таблицы истинности перечислили как другую работу ответов над только одним или двумя входными битами за один раз. Что происходит, когда Вы используете целые числа, такие как:

int x = 5 & 6;

ответ заключается в двоичном расширении каждого входа:

  5 = 0 0 0 0 0 1 0 1
& 6 = 0 0 0 0 0 1 1 0
---------------------
      0 0 0 0 0 1 0 0

Каждая пара битов в каждом столбце пробегается, "И" функция для предоставления соответствующего вывода обдумала нижнюю строку. Таким образом, ответ на вышеупомянутое выражение равняется 4. ЦП сделал (в этом примере) 8 отдельных "И" операции параллельно, один для каждого столбца.

я упоминаю это, потому что я все еще не забываю иметь это "АГА!" момент, когда я узнал об этом много лет назад.

27
ответ дан 24 November 2019 в 00:45
поделиться

Побитовые операторы являются операторами, которые продолжают работать понемногу.

И 1, только если оба из его исходных данных равняются 1.

ИЛИ 1, если один или несколько его исходных данных равняется 1.

XOR равняется 1, только если точно одни из его исходных данных равняются 1.

НЕ 1, только если его вход 0.

Они могут быть лучше всего описаны как таблицы истинности. Возможности исходных данных находятся на вершине и оставлены, результирующий бит является одним из четырех (два в случае НЕ, так как это только имеет вход того), значения, показанные на пересечении двух исходных данных.

AND|0 1      OR|0 1
---+----    ---+----
  0|0 0       0|0 1
  1|0 1       1|1 1

XOR|0 1     NOT|0 1
---+----    ---+---
  0|0 1        |1 0
  1|1 0

Один пример - то, если Вы только хотите более низкие 4 бита целого числа, Вас И его с 15 (двоичный 1111) так:

    203: 1100 1011
AND  15: 0000 1111
------------------
 IS  11: 0000 1011
27
ответ дан 24 November 2019 в 00:45
поделиться

Это побитовые операторы, все поддерживаемые в JavaScript:

  • op1 & op2 - AND оператор сравнивает два бита и генерирует результат 1, если оба бита равняются 1; иначе это возвращается 0.

  • op1 | op2 - OR оператор сравнивает два бита и генерирует результат 1, если биты дополнительны; иначе это возвращается 0.

  • op1 ^ op2 - EXCLUSIVE-OR оператор сравнивает два бита и возвращается 1, если или битов 1, и он дает 0, если оба бита 0 или 1.

  • ~op1 - COMPLEMENT оператор используется для инвертирования всех битов операнда.

  • op1 << op2 - SHIFT LEFT оператор перемещает биты налево, отбрасывает крайне левый бит и присваивает самому правому биту значение 0. Каждое перемещение налево эффективно умножает op1 на 2.

  • op1 >> op2 - SHIFT RIGHT оператор перемещает биты направо, отбрасывает крайний правый бит и присваивает крайнему левому биту значение 0. Каждое перемещение направо эффективно разделяет op1 пополам. Крайний левый знаковый бит сохраняется.

  • op1 >>> op2 - SHIFT RIGHT - ZERO FILL оператор перемещает биты направо, отбрасывает крайний правый бит и присваивает крайнему левому биту значение 0. Каждое перемещение направо эффективно разделяет op1 пополам. Крайний левый знаковый бит отбрасывается.

15
ответ дан 24 November 2019 в 00:45
поделиться

Для повреждения его вниз немного больше он имеет непосредственное отношение к двоичному представлению рассматриваемого значения.

For example (in decimal):
x = 8
y = 1

would come out to (in binary):
x = 1000
y = 0001

From there, you can do computational operations such as 'and' or 'or'; in this case:
x | y = 
1000 
0001 |
------
1001

or...9 in decimal

Hope это помогает.

4
ответ дан 24 November 2019 в 00:45
поделиться

То, когда термин "поразрядный" упоминается, он иногда разъясняет, что это, не является "логическим" оператором.

, Например, в JavaScript, побитовые операторы рассматривают свои операнды как последовательность 32 битов (нули и) ; между тем логические операторы обычно используются с булевыми (логическими) значениями , но могут работать с небулевыми типами.

Берут expr1 & & expr2, например.

Возвраты expr1, если это может быть преобразовано в ложь; иначе, возвраты expr2. Таким образом, при использовании с булевыми значениями, & & возвращает true, если оба операнда верны; иначе, возвращает false.

a = "Cat" && "Dog"     // t && t returns Dog
a = 2 && 4     // t && t returns 4

, Поскольку другие отметили, 2 & 4 поразрядное И, таким образом, это возвратится 0.

можно скопировать следующее в test.html или что-то и тест:

<html>
<body>
<script>
    alert("\"Cat\" && \"Dog\" = " + ("Cat" && "Dog") + "\n"
        + "2 && 4 = " + (2 && 4) + "\n"
        + "2 & 4 = " + (2 & 4));
</script>
4
ответ дан 24 November 2019 в 00:45
поделиться

Я продолжал слышать о том, как медленные побитовые операторы JavaScript были. Я сделал некоторые тесты для мое последнее сообщение в блоге и узнал, что они были 40% к на 80% быстрее, чем арифметическая альтернатива в нескольких тестах. Возможно, они раньше были медленными. В современных браузерах я люблю их.

у меня есть один случай в моем коде, который будет быстрее и легче читать из-за этого. Я буду держать глаза открытыми для больше.

-5
ответ дан 24 November 2019 в 00:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: