Monday, June 23, 2008

Those Pesky Semicolons

Sure, it sounds simple: "A semicolon ends a statement." The problem is that when you're new to the language, new to programming, and you sit down at the keyboard and start typing in your own programs from scratch for the first time, what seemed perfectly obvious when you were typing in code from someone else's examples turns weird and murky.

Let's take a look at a program and dink around with the semicolons in it and see what happens. Several versions of the program I'll give here won't compile, so be warned, this article contains non-working examples!

Here's our program, with no semicolons at all:
public class Semicolon{
public static void main(String arg[]){
System.out.println("argl bargl")
}
}

If you enter and try to compile this program with javac, you'll get the following error:
$ javac Semicolon.java
Semicolon.java:4: ';' expected
}
^
1 error
OK, the compiler is complaining that it got to line 4 and there was no semicolon. Does this mean it expected a semicolon here? No, the compiler tries to make as much sense of your program as it can, and when it gets to the point where it can't make any sense of things any more, it gives you an error message. That means that the place it is saying the error is at is after the place where the actual error lies.

The place that Java has to have a semicolon is at the end of line 3. When it got to the curly brace on line 4, the compiler saw that it had gotten past the point where it expected a semicolon.

So let's add a semicolon at the end of line 3:
public class Semicolon{
public static void main(String arg[]){
if (true) System.out.println("argl bargl");
}
}
This program will now compile and run. The statement here that needed a semicolon to end it was System.out.println("argl bargl"). So how can we know that it wasn't the if that needed the semicolon?

Let's try using a code block with if like this and see what happens. If the if is the statement that needs a semicolon, then we won't need a semicolon after the System.out.println("argl bargl") inside the code block:
public class Semicolon{
public static void main(String arg[]){
if (true) {System.out.println("argl bargl")};
}
}
When we hand this to the compiler, it says:
Semicolon.java:3: ';' expected
if (true) { System.out.println("argl bargl") };
^
1 error
OK, so we know it's the System.out.println("argl bargl") that needs the semicolon, not the if part of the program.

I Know How to Spell Banana, I Just Don't Know When to Stop...

OK, so now we've got the minimum number of semicolons that it takes to make our short and simple program to compile. But what about all those other lines? Why don't we need semicolons for them?

// The minimum number of semicolons:
public class Semicolon{
public static void main(String arg[]){
if (true) System.out.println("argl bargl");
}
}

Well, the comment (first line here) doesn't need a semicolon because technically it's not part of the program. The compiler ignores it. See Comments.

The second line isn't technically a statement, and neither is the line with main(). The curly braces are the same sort of thing to Java as the semicolon, they are all dividers. The curly braces at the end of the first two lines, and in the last two lines of the program define the code blocks associated with main() and the class Semicolon.

But what if we're programming away and this distinction eludes us? What happens if we just start throwing semicolons around like mad?

// Semicolons are cheap, so I use them everywhere! ;
public class Semicolon{;
public static void main(String arg[]){;
if (true){;
System.out.println("argl bargl");
}; // end of if;
};
};


Believe it or not, this program compiles and runs just fine:

$ javac Semicolon.java
$ java Semicolon
argl bargl
Now, I'm gonna shake my finger at you and say "You really ought to know where the semicolons are supposed to be!", but the fact is that if you accidentally thrown in extras it doesn't hurt. Java sees the extra semicolon as an empty statement, so you can put an extra semicolon anywhere a full statement would have been legal. So, if you accidentally throw a semicolon in at the end of a line where it's not necessary it's not going to hurt anything.

OK, where will extra semicolons do actual harm to your program? In the middle of a statement, that's where. Here's an example of a bad semicolon:

public class BadSemicolon{
// This program has an error in it! It won't compile!
public static void main(String arg[]){
int a=4;
int b=5;
int c;

a=b; +c;
System.out.println(a, b, c);
}
}
The semicolon that got put in between b and +c is going to hose the program. It's in the middle of an expression, breaking it up into two pieces. The first part, a=b;, makes sense to the compiler. It says "OK, take the value of b and stick it in a!" This isn't what you wanted it to do, but the compiler only knows what you tell it.

Then the compiler get to +c;, and by itself it doesn't make any sense:
BadSemicolon.java:6: not a statement
a=b; +c;
^
1 error

Because the semicolon is a separator, you've separated one statement into two by sticking one in the middle of things. +c is not a statement in Java, as the compiler tells you. So now you know why we don't just throw semicolons around everywhere, like every other character, just to make sure we get all the ones in that we need.

OK, so a few extra semicolons don't matter. If you just want to get something working in your early days as a programmer and don't want to fuss with semicolons you can throw them in pretty much whenever you think they might be called for and call it a day. If you do that I recommend that once the program is working with too many semicolons in it, that you go back and start taking them out and recompiling to see which ones you didn't need until you get down to just the ones that were really necessary.

Otherwise, I recommend that you only do the ones that you know you need for sure, and when in doubt, leave them out. Then, when you compile, expect to go back into the program and add them where needed. This is a far better approach for learning where you need them than spamming your program with semicolons.

Most of all, have fun!
StumbleUpon