In the last lesson we focused mostly on math operators.
Numbers are important, but we need to construct larger more complex logic
operations like, hey is my shape a circle or
is it colored red? We also need to perform bit
manipulations. That's what we're covering in this lesson.
The goal for this lesson is to finish up our understanding of Java operators.
We need to cover the equality operators, logical operators,
bit operators, and then we'll take a final look at operator precedence.
Equality in relational operators check to see how two values are related.
These operators all return a boolean value.
Remember a boolean value is either true or false.
So each one of these evaluates to either true
or false. To determine if two values are equal
we use two equal symbols for equality. This is different than the assignment
operator.
That only uses one sign, and it's a common mistake to use one equal sign when you
meant two. Luckily Java is going to complain about that when we try to compile.
I'll show you that when we get to the code. In this example
isEqual would return "false". You can also test if two values
are not equal. That uses the exclamation point with the equal sign.
We read that as A is not equal to B.
If they're not equal, the test returns true.
This is the opposite of the quality operator. One
not equal to 2 would return "true".
We use the greater than and the less than operators
to test for strict inequalities. A strict inequality says
"is A strictly greater than B". The answer is always
and true or false. So if A equals B,
then the strict inequality is false. For this example
1 > 2 will be "false". While
1 < 2 will be "true". If both values are 1,
greater than 1 is false. The "not-so" strict version is
is A greater than or equal to B, or
is A less than or equal to B. In this case
we're allowing equals to return true as well.
So if A equals B, then the operator returns "true".
We use an equals symbol with the greater than or less than symbol
for these operators. Let's look at a assigning
booleans to equality and relational operators. So if we set
a = 3 and b=4,
let's see what happens for each operator. Equals is "false",
not equals is "true", greater than is "false",
greater than or equals is "false", less than is "true",
and less than or equals is "true".
Now let's set a and b equal to 4 and run it again.
In this case equals is "true",
not equals is "false", greater than is "false",
greater than or equal is "true". This is because the two values are equal. So that
counts as "true" in this test.
Less than is "false" and less than or equal is "true".
Now I said earlier its a common mistake to use
the single equals. Let's see what happens if I delete
one of the equals sign in the first test. It won't even compile.
It complains with "int cannot be converted to a boolean". That's because
its actually trying to do the assignment chaining we saw in the last lesson.
It's setting a equal to b, then trying to assign it to the boolean value.
It's not a boolean and so we get an error.
Next up are the conditional operators.
Conditional operators perform logical operations on boolean values.
You may know these as AND and OR.
AND is the first one we're going to look at.
It reads like an English statement, a AND b.
If a is "true" and B is "true",
a && b is "true". If either one of them are "false",
then a && b is "false". Both
a and b must be "true" for the result to be "true".
OR also reads like an English statement.
a OR b. If a is "true"
or if b is "true", then a || b is "true".
If a and b both "false", then a || b is "false".
Only one, either a or b, needs to be "true" for the result to be "true".
Finally there's one unary operator
we didn't cover in the last lesson. It's called NOT. So if b is "true",
!b is "false". If b is "false",
!b is "true". Basically NOT just flips the sign of the boolean value.
We use an exclamation point in front of the boolean value, or
for the expression, for NOTs. When ever you see the exclamation point,
you can substitute the word "not". Let's look at the boolean operators.
Assume a is "true" and b is "true". Here's what AND, OR, and NOT look like.
Now let's make b "false".
Here's what AND, OR and NOT look like.
Now the power of the boolean expressions is that we can chain several of these together.
We can also use equality and relational expressions.
So assume a is "true" and b is "4 > 3".
Let's play with that a bit.
Note these can get pretty long. Equality operators will be evaluated first,
then the ANDs, then the ORs. You really don't want to string them together like
this however.
It's not intuitive to know which operators have precedence.
You want to be explicit about the order statements are evaluated.
To do so use parentheses. We'll look at this closer in a minute. Finally we have the
bit operators. These operators are for changing the individual
bits ip an integer number. Remember integers include bytes, shorts,
ints, and longs. The first group of bit operators that will look at are the
bitwise operators.
The bitwise operators are for AND,
OR, and exclusive or (XOR). These take
two integer types, and return an integer or a long.
That's important. If you use these operations on two bytes,
or two shorts, your result's going to be an integer. The result is always an int
or long, unless we cast to back down. The bitwise operators are similar to the
boolean operators we saw before.
In fact you can mentally think of these operations as 1 is "true" and
0 is "false"
as you work through each bit in the number. We call a bit that has a 1 is set,
and 0 is clear. The bitwise operators use a single ampersand
for the AND, a single bar for the OR, and the caret symbol
for a new operation we call exclusive or (XOR). Let's assume that we have two bits
and we want to AND. We're saying if the first bit is 1,
and the second is 1, then the result from an AND
is 1. If we had a 1 and a 0, the result is a 0.
ANDs want both to be a 1, otherwise
it's a 0. We can extend this for every bit in a byte.
if we AND each of the 8 bits in a
byte, we get the following result. We get set
bits only the positions where a and b bits
were also set. ORs are a little different. For an OR we're saying
if the first bit is a 1, or the second is a 1,
then the result of an OR is 1. If they're both a 1
it's still a 1. For ORs the answer is a 1
unless both initial bits are 0. Again
this can be extended to the whole integer. Here
if we OR each of the eight bits in a and b, we have the following result.
We get bits set only in positions where there's a bit set
in a or b. Exclusive or
is spelled XOR, and uses the caret symbol. This behaves
like an OR, except that if both are a 1.
In this case if both are a 1, the result is 0.
It's like the Highlander bit operator, there can only be one.
It's exclusive. Well that's how I remember it.
Here if we XOR each of the 8 bits
in a and b, we'll get the following result.
we get bits set only in the positions where a bit
was set in only a or only b,
but not both. When unary operation we skipped last lesson
is a bitwise urinary NOT. We skipped it because I wanted to keep all the bit
manipulating
operations together. Unary NOT flips all the bits
in your integer. So if the bit
is 1, it becomes 0 and vice versa.
Here if we NOT each of the 8 bits in a,
all the bits get flipped. Set bits become clear bits,
clear bits become set bits. Let's look at some of the code for this and
hopefully it'll become clear.
We'll work with integers. We'll set our first number to all 1s.
The second number will be half 1s,
half 0s. We AND the numbers.
We get back a number with half 1s and half 0s.
Basically the same number we got back. If we
OR the numbers, we get all the bits set. This is because
all the bits are set in the first number.
Things are little bit more interesting for XOR. When we run this,
we get the reverse of the second number. Look at what happens
if we set the first number 42 and then we set the second number to 24.
We XOR the two numbers and we get 50.
OK, we then XOR50
with the second number again and we get back to 42.
You can do this with any two numbers. It's pretty cool!
And for completeness here's how we flip the bits using NOT.
These operators
are used for bit shifts. What does that mean?
It means we move all the bits to the left
or the right depending on the direction of the arrows. The direction
the symbol points determine the direction of the shift. If we're shifting to
the right,
the most significant digit number determines what shifted in.
So if the highest digit is 1, we shift 1 into the number.
If it's a 0, we shift a 0. The reason for this is
we're keeping the number either positive or negative. As you remember
the highest bit determines the sign of the number. We saw that
in the "How the computer store negative numbers" lesson. Sometimes we always want
to shift
0 into the number. So for that we use the unsigned shift right.
That has three greater than symbols.
A O's always shifted in. Again let's play with these in code.
We'll take a number,
and shift it to the left. The cool thing to note here is
the result is just the previous number times 2. So when you shift left,
each shift is a power of 2. If we shifted by two, the
number multiplied is by four. Shifting right is just going in the
opposite direction.
Let's do one negative number and one positive number.
As you can see, shifting keeps the sign.
We do it again with unsigned shift, you see the sign changes for the negative
number.
That's because we shifted a 0 in making it positive.
If you want to see more bit operations,
check out "Four ways to count bits in a byte". Manipulating bits as a
common interview question, although the types of programs you work on
really determine how often you work with bits. The last thing we want to discuss is
operator precedence.
We covered all the Java operators individually. You can chain many of these
into larger
more complex operations. The catch is
Java performs operations in a specific order.
It's not always left to right. Here's a list of operator precedence.
The way to read this chart is Java is going to start from the top,
and work it's way down. If the operator is on the same line
it works from left to right. Again you want to use parentheses to make this
explicit. It's not a good practice to chain long operations without
parentheses if you're
expression is really long. You might want to break it up into smaller statements
like this.
That way there's no ambiguity in what you trying to calculate.
Parentheses always go first. And that wraps it up for the different operators.
We now have the power to control our numbers down to the bit level.
We can form complex boolean expressions using a logical operators.
And we know how to test for equality. We can start using these operators to build
bigger and bigger programs.
Programs that actually do something! You'll want to play with these in your own Java
programs.
It's easier to understand when you see what happens in code.
If you have any questions leave them in the comments below or on DeegeU.com.
And I'll see you in the next lesson.
Hey thanks for watching the video.
There is a quick quiz for this on DeegeU.com if you'd like to gauge how much you
learned.
If you like the videos are seeing, please let me know by liking the video
and hitting the subscribe button to
the DeegeU channel on YouTube. I'd really appreciate that. If you have concerns or
questions please leave them in the comments below
or on DeegeU.com. There's a poll on the front page of
DeegeU.com so you can let me know what topic is covered
next. Thanks for watching and see you next video.