Editor's note: Sometimes the most interesting discussions begin when someone says, "This may be a stupid question, but .... " If the person asking the question has taken the time to think about the problem before asking, the question is often not stupid at all. The uncertainty points out an ambiguity in the specs, holes in the docs, or a search for how more experienced programmers might address a particular problem. From time to time, we will print one of the "(Not So) Stupid Questions" we receive and invite our readers to answer the question in the feedback section.
Remember that new people are joining the Java community all the time and may be looking for help from those with more experience. Also, those who began with Java as their first language can benefit from those coming to the community with experience in other languages. As always, answer the questions with kindness. You are also welcome to submit your questions to
This may be a stupid question, but ... "There are some weird Java operators I don't understand."
First thoughts:
In my development, I often use the operators for mathematical functions (+, -, *, etc.), assigning values (=), testing values (==, >, >=, etc.), and combinations of these (+=).
But sometimes, in other people's code, I occasionally see some weird "greater than/less than" type operators like >> and <<. I assume those aren't the mathematical "much greater than" and "much less than," but then, what are they? There's also a "question mark" operator (?) that really isn't very self-descriptive. What is that supposed to be telling me?
My question is:
What are these operators, what do they do, and why would I ever want or need to use them?
Just look at this code I wrote before I found about bitwise operators in java, because of this article; thanks!
Here I am trying to break a byte that I read from a file into four tertiary numbers:
public static final int[] bite(int inByte)
{
int[] bites = new int[4];
int tooth = 0;
int remainder = inByte;
for(int i = 0; i < 4; i++)
{
bites[i] = remainder / (int)(Math.pow(4,3-i));
remainder = remainder % (int)(Math.pow(4,3-i));
}
return bites;
}
now bitwise:
Just look at this code I wrote before I found about bitwise operators in java, because of this article; thanks!
Here I am trying to break a byte that I read from a file into four tertiary numbers:
public static final int[] bite(int inByte)
{
int[] bites = new int[4];
for(int i = 0; i < 4; i++)
{
bites[i] = inByte%4;
inByte = inByte >>2;
}
return bites;
}
That code doesn't do quite what it appears to. If inByte is negative, then the elements of the returned array will all be non-positive. Perhaps the method should only be called with values between 0 and 255 inclusive, in which case it should throw an IllegalArgumentException for exceptional cases when it is passed an illegal argument.
The problem is that both % and >> are signed operators. The semantics of % (and integer division) are rather arbitrary, so check the Java Language Spec (JLS) for the tedious details. Replacing either by unsigned equivalent operations would do. As 4 is a power of two, x%4 can be replaced with the bitwise expression x & 3, giving a non-negative result. x >> 2 can be replaced using the logical (rather than arithmetic) right shift operator, x >>> 2. The intent is more obvious if both expressions are replaced.
For code like this I would tend to write it as:
public static final int[] byteToLittleEndianCrumbs(int byteValue) {
if (!(0 <= byteValue && byteValue <= 0x100)) {
throw new IllegalArgumentException();
}
return new int[] {
(byteValue >> 0) & 0xf,
(byteValue >> 2) & 0xf,
(byteValue >> 4) & 0xf,
(byteValue >> 6) & 0xf,
}
}
It is repetive, but in this case clearer than the loop.
Since Java 1.5, Integer and Long have gained a number of bit twiddling methods, along similar lines to these bitwise operators. IMO, the library would have been a better place for them all.
Oops. & 0xf in the above should read & 0x3. <= 0x100 should be <= 0xff or < 0x100. And probably >>, >>>.Damn O'Reilly Collabnet and their lack of preview facility.
If op1 is true, returns op2; otherwise, returns op3
Well they are quite intuitive i think...
2006-01-17 05:53:22 wfvoogd
[Reply | View]
Let's start with the easy one; the question mark and colon (? :)
That a shorthand for the if statement. sometimes you just want to assign a certain value under a certain condition.
ie.
int a = 0;
boolean negativeValue;
if (a>=0)
negativeValue = false;
else
negativeValue = true;
you could write that as:
int a = 0;
boolean negativeValue = (a>=0)?false:true;
So it's just a shorthand if..else really.
Hope this helps,
Willem
Otherwise known as a ternary operator
2006-01-17 13:49:46 phuego
[Reply | View]
The ? and : chars are correctly known when used together as a 'ternary operator'.
I find them particularly useful for refactoring a block of code that does this, or that, based on a boolean.
For example you have a method that filters a List.
The way the List is filtered depends on a GUI setting, for arguments sake 'include zero'.
So you might code like this:
public List filterListOfIntegersToPositives(List original, boolean inclZero) {
List ret = new ArrayList(original.size());
if (inclZero) {
// code that does filtering
for(int i=0; i<original.size(); i++){
Integer thisInt = originals.get(i);
if (thisInt.compareTo(Integer.valueOf(0)) > -1) {
ret.add(thisInt);
}
}
// end code that does filtering
} else {
// code that does filtering
for(int i=0; i<original.size(); i++){
Integer thisInt = originals.get(i);
if (thisInt.compareTo(Integer.valueOf(0)) > 0) {
ret.add(thisInt);
}
}
// end code that does filtering
}
return ret;
}
Now you look at that code, and you think to yourself - the code that does filtering (as commented) is duplicated, and that violates "Don't repeat Yourself" and so I need to refactor that to a better design. good thought.
So we look and we see that the only part that changes in the duplicated code is the value of the int we compare to (it changes from -1, to 0)
So, using a ternary operator, we could refactor that method as follows:
public List filterListOfIntegersToPositives(List original, boolean inclZero) {
List ret = new ArrayList(original.size());
for(int i=0; i<original.size(); i++){
Integer thisInt = originals.get(i);
if (thisInt.compareTo(Integer.valueOf(0)) > (inclZero? -1 : 0)) {
ret.add(thisInt);
}
}
return ret;
}
Much cleaner.
Now, i have to admit, I've never used bitshifting either! So I'm looking forward to the "why you'd actually do this" post on that.
Hope that helps to clarify ternary operators and why you'd use them just a little.
Adrian
Otherwise known as a ternary operator
2006-01-17 14:11:25 sirian98
[Reply | View]
Just look at this code I wrote before I found about bitwise operators in java, because of this article; thanks!
Here I am trying to break a byte that I read from a file into four tertiary numbers:
public static final int[] bite(int inByte)
{
int[] bites = new int[4];
int tooth = 0;
int remainder = inByte;
for(int i = 0; i < 4; i++)
{
bites[i] = remainder / (int)(Math.pow(4,3-i));
remainder = remainder % (int)(Math.pow(4,3-i));
}
return bites;
}
now bitwise:
Just look at this code I wrote before I found about bitwise operators in java, because of this article; thanks!
Here I am trying to break a byte that I read from a file into four tertiary numbers:
public static final int[] bite(int inByte)
{
int[] bites = new int[4];
for(int i = 0; i < 4; i++)
{
bites[i] = inByte%4;
inByte = inByte >>2;
}
return bites;
}
modulus + bitwise = power
[Reposted] Otherwise known as a ternary operator
2006-01-17 13:56:54 phuego
[Reply | View]
So sorry, completely forgot about formatting.
Here is the 'before' code from my first post.
public List filterListOfIntegersToPositives(List original, boolean inclZero) {
List ret = new ArrayList(original.size());
if (inclZero) {
// code that does filtering
for(int i=0; i<original.size(); i++){
Integer thisInt = (Integer) original.get(i);
if (thisInt.compareTo(Integer.valueOf("0")) > -1) {
ret.add(thisInt);
}
}
// end code that does filtering
} else {
// code that does filtering
for(int i=0; i<original.size(); i++){
Integer thisInt = (Integer) original.get(i);
if (thisInt.compareTo(Integer.valueOf("0")) > 0) {
ret.add(thisInt);
}
}
// end code that does filtering
}
return ret;
}
And here is the code after you've refactored using a ternary operator...
public List filterListOfIntegersToPositives(List original, boolean inclZero) {
List ret = new ArrayList(original.size());
// code that does filtering
for(int i=0; i<original.size(); i++){
Integer thisInt = (Integer) original.get(i);
if (thisInt.compareTo(Integer.valueOf("0")) > (inclZero ? -1 : 0)) {
ret.add(thisInt);
}
}
// end code that does filtering
return ret;
}
Apologies for the mistake before - why is there no Preview post in this forum???
Hi!. The ? operator is a one line conditional, it's like an if statement.
The << and >> operators are for bit shifting.
For more information, check http://java.sun.com/docs/books/tutorial/java/nutsandbolts/bitwise.html