How I passed the SCJP / OCPJP

After procrastinating for many years (4 to be precise), I finally sat and passed the SCJP exam. The exam itself wasn’t particularly difficult, but theres a lot of things you can get tested on that you’ll rarely use in everyday development. Having been developing in Java for around 4 years now, I’ve never needed to do any serialisation or do any fancy concurrency work other than starting a thread for an asynchrnous task.

So to iterate, theres a lot in there that you may not use, but the test expects you to know it well, so be sure to practice and write a lot of code.

Anyways, the reason for this post was to discuss some of the tactics I used to get through.

The study part

The first thing you need to do, is to get hold of the study guide and start reading through it. If you’re relatively new to Java, such as a student or someone transitioning from another background, then you can get Head First Java which will give you a fantastic intro to the Java programming language in an easy to digest read. You should be able to get through HFJ in a few weeks as it has a relatively informal style, but you should certainly allow a month or two to read the study guide, as its around 800 pages and you need to keep focus!

Write code

I can’t stress how important this is! My memory is pretty useless, I can read a book and then a month or two later I’ll have forgotten most of it. I found the best way to remember things is to practice them, so when I’ve read a chapter (or even a few pages on a specific topic) I’d start experimenting with some code. It just helps the knowledge stay in.

My advice here, just download an IDE and start writing, you can also post your code up onto Github too, it makes a great reference point, and may help others. You can also blog using your study notes, which is pretty much the main reason I setup this blog in the first place.

 

Resources, things to buy, free stuff

  1. Head First Java
  2. SCJP Study Guide
  3. SCJP Practice exam book
  4. A set of blank flash/record cards, these will be around £4 from your local stationary shop, use them to write important points and revise when you can spare the odd 5 minutes here and there.
  5. Evernote.com - Get signed up on there, its a great way to store your study notes. You can also get the mobile app to revise your notes when on a train / plane etc.
  6. JavaRanch.com – Post up here in the certification section any questions that you may have, very useful community
  7. StackOverflow.com – I used this a lot for finding answers that were not always obvious in the study guides. If your questions are well defined, you’ll get great help here
  8. Colleagues – Don’t underestimate your peers, if you don’t understand areas of the syllabus, chat to people!
  9. Whizlabs – Great testing kit, but make sure you use it. I wasn’t aware that the software expires after 1 year, so unfortunately I didn’t get to use it for my exam :(
  10. Enthuware – This is much better than whizlabs as it doesn’t require being online, and you get to select how many questions. Often I didn’t want to do all 60 in one go

 

Suggested schedule

When booking my exam, I gave myself around 3 months, considering I’d already been over the book a few times it was plenty enough to recap the important chapters and squeeze in some mock tests. If you’re sitting this for the first time, I’d suggest a preparation schedule like below, assuming you will have 8 months to prepare. Of course, if you’ve been developing for a while you can probably skip the first 2 weeks, read the study guide in a condensed amount of time, and take less practice tests.

 

Week 1 Read Head First Java
Week 2 Read Head First Java
Week 3 Take a week off
Week 4 Study guide chapter 1
Week 5 Experiment with code relating to chapter, then do chapter quiz
Week 6 Study guide chapter 2
Week 7 Experiment with code relating to chapter, then do chapter quiz
Week 8 Study guide chapter 3
Week 9 Experiment with code relating to chapter, then do chapter quiz
Week 10 Study guide chapter 4
Week 11 Experiment with code relating to chapter, then do chapter quiz
Week 12 Study guide chapter 5
Week 13 Experiment with code relating to chapter, then do chapter quiz
Week 14 Study guide chapter 6
Week 15 Experiment with code relating to chapter, then do chapter quiz
Week 16 Study guide chapter 7
Week 17 Experiment with code relating to chapter, then do chapter quiz
Week 18 Study guide chapter 8
Week 19 Experiment with code relating to chapter, then do chapter quiz
Week 20 Study guide chapter 9
Week 21 Experiment with code relating to chapter, then do chapter quiz
Week 22 Study guide chapter 10
Week 23 Take a week off
Week 24 Whizlabs Tests
Week 25 Whizlabs Tests
Week 26 Whizlabs Tests
Week 27 Take a week off
Week 28 enthuware tests
Week 29 enthuware tests
Week 30 enthuware tests
Week 31 Take a week off
Week 32 Self assessment 1, then brush up on any key areas you really missed on
Week 33 Self assessment 2, then brush up on any key areas you really missed on
Week 34 Practice test 1 & 2
Week 35 Practice test 3 & 4

Tips for the exam:

  • Get there early, my train got cancelled so I was running/stressing to the exam room, which didn’t help.
  • Don’t stress! Thats the worst thing you can do!
  • The actual exam will say how many answers you need to select, so don’t worry about the “select all that apply” that you often see in mock tests.
  • You can “strikeout” answers on the real exam, which means you can eliminate the answers you think are wrong, very useful for those questions that are a complete guess.
  • You don’t get your results immediately, you have to login to Oracle Certview about an hour after completing the exam to see your score card.

 

Continue and break, with and without labels, for the SCJP

Looping constructs are very useful in any programming language, however they can be come particularly complex when you have a variety of nested loops and you need to drop out from particular iterations, or exit the loops entirely under a set of given circumstances. Fortunately for us, Java provides us with 2 keywords that we can use to help in these situations:

  • break - breaks out of the entire loop, and no more iterations will occur. The thread of execution will then move onto the next line of code after the loop.
  • continue - the current iteration will be terminated, and the thread of execution will move onto the next iteration, if there is one, otherwise the loop will complete.

It is important to note, that in both of these keywords, unless otherwise specified via the use of a label, they will apply to the inner most loop that is currently executing.

If you would like to break or continue out of a loop that happens to be nested outside of your current loop, then you need to use labeled loops, whereby you give each one a label and then you can continue/break on one of those given labels. For example, if you have 3 loops, one nested in another, and you’re cycling through the inner most loop and decide that you don’t need to iterate over any of them anymore, as you have all the data you need, then you can call break on the outermost loop and move onto the next piece of code.

Please consider the following example that I have on my SCJP examples page, if I’ve missed anything obvious please let me know:

package com.jameselsey.demo.scjp.flow_control;

/**
 * Author:  JElsey
 * Date:    22/08/2012
 *
 * Experimenting with the break and continue keywords, also using labeling.
 */
public class UsingBreakAndContinue
{
    public static void main(String[] args)
    {
        doUnlabeledBreak();
        doUnlabeledContinue();

        doLabeledBreak();
        doLabeledContinue();

        doNestedLabeledBreak();
        doNestedLabeledContinue();
    }

    /*
        Since we're not using any labels here, the break will break out of the inner most loop, then move
        onto the next statement AFTER the loop. Break will "break out" immediately from the iteration, great for
        cases when you're counting up something, find you have done all the iterations you need, then you can break out
        and prevent wasting time on iterations you no longer need.
     */
    private static void doUnlabeledBreak()
    {
        System.out.println("START - Un-labeled break");
        for (int i = 0; i < 5; i++)
        {
            System.out.println("\tIteration on i:" + i);
            System.out.println("\tLets call break, we don't want to do any more");
            break;
            // We're done with the whole loop, "break out" and move onto whatever comes after the loop
            // we don't want to do any more iterations
        }
        System.out.println("END - Un-labeled break");

    }

    /*
        We're using no labeling here, so much like the example above, the continue will take effect on the inner most
        loop. Continue drops out of the current iteration immediately, and attempts the next iteration, if there is one.
        This is great for scenarios where you're checking numbers for odd/even, if its an odd number, you could continue on
        to the next iteration; if you only require doing stuff with even numbers (just an example).
     */
    private static void doUnlabeledContinue()
    {
        System.out.println("START - Un-labeled continue");
        for (int i = 0; i < 5; i++)
        {
            System.out.println("\tIteration on i:" + i);
            System.out.println("\tLets call continue, we don't want to do any more in this iteration");
            continue;
            // anything under here can't be accessed, since you've called continue which drops out
            // of the iteration and "continues" with the next iteration, if there is one
        }
        System.out.println("END - Un-labeled continue");
    }

    /*
        Behaves similar to the unlabeled break, however if you break on a label, it will break for THAT label rather
        than the inner most loop. This is great when you have complex, nested iteration cycles.
     */
    private static void doLabeledBreak()
    {
        System.out.println("START - labeled break");
        labeledBreak:
        for (int i = 0; i < 5; i++)
        {
            System.out.println("\tIteration on i: " + i);
            System.out.println("\tLets call break, we don't want to do any more in this iteration");
            break labeledBreak;
            // We've broken out to the "labeledBreak", so we won't do any more further iterations of this label
        }
        System.out.println("END - labeled break");
    }

    /*
        Similar to the labled break, the labeled continue will move onto the next iteration of the label you've
        specified, if there is an iteration, otherwise the loop is complete.
     */
    private static void doLabeledContinue()
    {
        System.out.println("START - Labeled continue");
        labeledContinue:
        for (int i = 0; i < 5; i++)
        {
            System.out.println("\tIteration on i:" + i);
            System.out.println("\tLets call continue, we don't want to do any more in this iteration");
            continue labeledContinue;
            // anything under here can't be accessed, since you've called continue which drops out
            // of the iteration and "continues" with the next iteration, if there is one
        }
        System.out.println("END - Labeled continue");
    }

    /*
        Using nested breaks here, with labels, so you can see how breaking out of individual nested looping
        constructs would work.
     */
    private static void doNestedLabeledBreak()
    {
        System.out.println("START - Nested Labeled break");
        outerLoop:
        for (int i = 0; i < 5; i++)
        {
            innerLoop:
            for(int inner = 0; inner < 5; inner++)
            {
                System.out.println("We're in the inner loop, lets break out of it...");
                break innerLoop;
            }
            System.out.println("Now lets break out of the outer loop too");
            break outerLoop;
        }
        System.out.println("END - Nested Labeled break");
    }

    /*
        Using nested labeled continues here to demonstrate how you'd continue onto labeled looping constructs.
     */
    private static void doNestedLabeledContinue()
    {
        System.out.println("START - Nested Labeled continue");
        outerLoop:
        for (int i = 0; i < 5; i++)
        {
            innerLoop:
            for(int inner = 0; inner < 5; inner++)
            {
                System.out.println("We're in the inner loop, lets continue out of it...");
                continue innerLoop;
            }
            System.out.println("Now lets continue out of the outer loop too");
            continue outerLoop;
        }
        System.out.println("END - Nested Labeled continue");
    }

    /*
        Not quite sure where I was going with this one, but was experimenting with some continue
        and break combinations.
     */
    private static void countingNumbers()
    {
        outerLoop:
        for(int i = 0; i         {
            if(i % 2 == 0)
            {
                System.out.println("Number is odd, lets continue to next iteration");
                continue outerLoop;
            }

            int sumOfEvens = 0;
            for(int j = 0; j < i; j++)
            {
                 sumOfEvens+= j;
            }

            if(i == 50)
            {
                System.out.println("We'll only count halfway, and give up at 50");
                break outerLoop;
            }
        }
    }
}

Interfaces, declaring and implementing

Another bite-size SCJP blog post, this time we’ll tackle interfaces.

Interfaces are, in the simplest terms, just a contract. It specifies things that a class must do if that class signs up to its contract, but it doesn’t provide any details of how those things must be done.

For example, you may wish to create an interface called Driveable. This interface defines the behaviour of anything that wants to become driveable, whether it be a Car class, a Motorcycle class, or even a Boat class.

You can think of an interface like a 100% abstract class, whereby all methods are implicitly abstract and public. Any class that decides to implement the interface, but provide method bodies for every single method in that interface, otherwise the compiler will complain.

Have a look at my sample below of a really basic interface and its implementation, you can find these on my SCJP samples on Github:

package com.jameselsey.demo.scjp.declarations_initialisation_scoping;

/**
 * Author:  JElsey
 * Date:    20/08/2012
 *
 * A quick example to show how an interface can be created, and more importantly how it is implemented.
 */
public class ImplementingAnInterface
{
    public static void main(String[] args)
    {
        // Notice the polymorphism here once again, how car IS-A driveable
        Driveable d1 = new Car();
        Driveable d2 = new Motorcycle();
        // The implementations provide the drive() method body.
        d1.drive();
        d2.drive();
    }
}

/*
 Create an interface, along with its methods. Think of it like a contract, anything that wants to become Driveable MUST
 implement the drive method, otherwise the contract is not fulfilled and the compiler will complain!
  */
interface Driveable
{
    public void drive();
}

class Car implements Driveable
{
    @Override
    public void drive()
    {
        System.out.println("Super charged v8 goes VROOOOM!!");
    }
}
class Motorcycle implements Driveable
{
    @Override
    public void drive()
    {
        System.out.println("Front rears up, wheelie down the highway!");
    }
}

Polymorphism, a little overview with code samples

Polymorphism basically means that one thing can take many forms, and this is particularly useful for programmers, as it allows us to treat similar types of object in a single manner, yet the objects may actually be slightly different at runtime.

One application of this might be where we have an animal class, we know that the animal class has methods like makeNoise(), move() and eat(), and we can happily develop our application against this. However, we may then like to extend the animal class, and create subclasses like Dog, Fish, and Cat, each which would inherit those methods, and optionally override the implementation to do things that are a little more Dog specific.

Consider the following example that I have hosted up on my SCJP samples Github page:

package com.jameselsey.demo.scjp.oo_concepts;

/**
 * Author:  JElsey
 * Date:    16/08/2012
 *
 * A few examples of polymorphism, meaning that one thing can represent many, or in another words, "morphed" in many (poly) ways
 */
public class Polymorphism
{
    public static void main(String[] args)
    {
        Animal animal;

        //  Polymorphic assignments here, animal being assigned as one of its sub-classes
        animal = new Cat();
        System.out.println("Cat makes a noise : " + animal.makeANoise());
        animal = new Dog();
        System.out.println("Dog makes a noise : " + animal.makeANoise());
        animal = new Fish();
        System.out.println("Fish makes a noise : " + animal.makeANoise());

        // Polymorphic array, declared as type Animal but contains sub-types
        Animal[] theAnimals = new Animal[]{new Cat(), new Dog(), new Fish()};
        for (Animal a : theAnimals)
        {
            // Since they're all of type animal, they all have a makeANoise() method, but the actual
            // implementation varies
            System.out.println(a.makeANoise());
        }
    }
}

abstract class Animal
{
     public abstract String makeANoise();
}

class Cat extends Animal
{
    @Override
    public String makeANoise()
    {
        return "Meow";
    }
}

class Dog extends Animal
{
    @Override
    public String makeANoise()
    {
        return "Woof";
    }
}

class Fish extends Animal
{
    @Override
    public String makeANoise()
    {
        return "Gurgle";
    }
}

Most of the time, you’ll actually use polymorphism without even realising, you just do it naturally. You’ll often find that it is useful especially when you “code to the interface, not the implementation”.

That is all.

Inheritance, some examples for SCJP study

Inheritance is a practice of one thing extending another. So you can more specific subclasses of a class. Inheritance is available in most programming languages, and in Java it is implied using the extends keyword.

For example, you may have several objects like Car, Boat, Truck, these may all have common behaviour and state between them. You could duplicate the shared members between them, but that can lead to a maintenance nightmare for some poor man in the future. The best option would be too look at inheritance, and try to move common, generic code to a superclass, such as Vehicle.

Then, your subclasses can all extend Vehicle, and automatically inherit the shared members, so you only have them coded once. Inheritance can do down as many levels as you like, and both classes and interfaces can use inheritance (a class can extend another class, and an interface can extend another interface, but never implement it).

In Java, you can only extend a single class at a time, which prevents multiple inheritance that you would otherwise get in another language.

Consider the below sample that I have on my SCJP samples Github project, which portrays a simple inheritance structure:

package com.jameselsey.demo.scjp.oo_concepts;

/**
 * Author:  JElsey
 * Date:    16/08/2012
 *
 * Sample of inheritance, showing a few classes that extend from each other, there is a little bit of polymorphism in here
 * too, can you spot it?
 */
public class Inheritance
{
    public static void main(String[] args)
    {
        Grandfather grandfather = new Grandfather();
        Daddy daddy = new Daddy();
        Son son = new Son();

        // The Grandfather is at the top of the inheritance tree (extends from java.lang.Object), so he only has wisdomLevel
        System.out.println("The grandfather has a wisdom level of " + grandfather.wisdomLevel);

        // The Daddy is strong, and also inherits his wisdom
        System.out.println("The daddy is " + daddy.strengthLevel + " and also gets the grandfathers wisdom: " + daddy.wisdomLevel);

        // The boy is lucky, hes very energetic, but also inherits strength from his dad, and wisdom from his grandfather
        System.out.println("The son is " + son.energyLevel + " and " + son.strengthLevel + " and " + son.wisdomLevel);

        // Inheritance also works on methods too, since they're all part of the same family, we can safely put the
        // family name in the grandfather, both the son and daddy will inherit that method
        System.out.println("Grandfathers surname : " + grandfather.getFamilyName());
        System.out.println("Daddys surname : " + daddy.getFamilyName());
        System.out.println("Sons surname : " + son.getFamilyName());
    }
}

class Grandfather
{
    String wisdomLevel = "Wise";

    public String getFamilyName()
    {
        return "Jones";
    }
}

class Daddy extends Grandfather
{
    String strengthLevel = "Strong";
}

class Son extends Daddy
{
    String energyLevel = "Energetic";
}

Encapsulation; shielding state via the use of accessors

Encapsulation is a fantastic OOP concept of being able to shield class state via the use of accessor methods.

Imagine that you have a class, perhaps called Person. This class will have some form of state, such as name, age, date of birth. These would most likely be stored against reference variables. If you left these publicly available, then anyone who develops against your class can freely access them and assign them to whatever they feel necessary.

Later on, you may like to change the way some of this state is represented, for example you may wish to start storing ages as Strings instead of Integers, if you do that, then anyone who is dependant on your class will now be screaming up and down as you would have broken their code that interfaces with yours, as you’ve changed the data type and it will cause compilation issues for them.

Encapsulation helps protect against these scenarios, whereby you would make the state private so other people can’t access it directly, but at the same time you would provide public methods so that developers can still use your class, and those public methods would access the private state.

This means that if you change your internal representation, you’d just need to update the implementation of the accessor method to retrieve the new data type, convert it to what the old API was expecting, and return it. Developers using your code won’t be interested in how its stored internally provided they can get their data in and out, if you change something behind the scenes, they won’t care (maybe they would, but this is just an example).

By forcing developers to access state via accessor methods, you can also enforce other restrictions like validation, without encapsulation the developers could put any value into name, and there is nothing you could do about it. However, using accessor methods, you could check the value beforehand and see that it meets your requirements, if it doesn’t, throw an exception.

Encapsulation is generally perceived to be good practice, and you should try to use it where possible. Some languages, such as Groovy even implement this out of the box for you, unless you state otherwise.

Please consider this example from my SCJP samples Github project, which displays the basics of encapsulation:

package com.jameselsey.demo.scjp.oo_concepts;

/**
 * Author:  JElsey
 * Date:     16/08/2012
 *
 * Demonstrating an understanding of the Encapsulation OOP term, which basically means to shield instance behaviour
 * behind publicly accessible accessors, thus giving more control of the internal representation of the values
 * and provides a single point of access.
 */
public class Encapsulation
{
    public static void main(String[] args)
    {
       // Create a class that doesn't use encapsulation

        UnencapsulatedMess mess = new UnencapsulatedMess();
        mess.personName = "James";
        mess.personAge = 26;
        System.out.println(mess);

        // now create a similar class, but one which implements encapsulation, notice the use of the accessor methods
        // rather than direct variable access
        EncapsulatedDream dream = new EncapsulatedDream();
        dream.setPersonName("James");
        dream.setPersonAge(26);
        System.out.println(dream);


        // Now, lets create another mess, but this time we want to have some control over what values the variable takes
        UnencapsulatedMess anotherMess = new UnencapsulatedMess();
        String someNameThatWouldComeFromAnotherClass = "Daniel";
        int anAgeThatWouldComeFromAnotherClass = 12;
        if (anAgeThatWouldComeFromAnotherClass < 16 || anAgeThatWouldComeFromAnotherClass > 60)
        {
            // handle an error
        }
        else
        {
            anotherMess.personAge = anAgeThatWouldComeFromAnotherClass;
            anotherMess.personName = someNameThatWouldComeFromAnotherClass;
        }
        // Woah! A lot of waffle to validate a value before we place it, and whereever you refer to this unecapsulated
        // class, you'd have to do the same thing, and how easy that would be to get wrong or be inconsistent!

        // With the encapsulated class, you could do all your validation in a central place, and be sure it is ALWAYS invoked,
        // This may not be the BEST place to validate, but its just an example of the benefits of encapsulation.
    }
}


class UnencapsulatedMess
{
    public String personName;
    // no access modifier specified, so takes default
    int personAge;

    @Override
    public String toString()
    {
        return "UnencapsulatedMess{" +
                "personName='" + personName + '\'' +
                ", personAge=" + personAge +
                '}';
    }
}

class EncapsulatedDream
{
    // make the state private, so only accessible within the class itself.
    private String personName;
    private int personAge;

    // Accessors
    public String getPersonName()
    {
        return personName;
    }

    public void setPersonName(String personName)
    {
        this.personName = personName;
    }

    public int getPersonAge()
    {
        return personAge;
    }

    /**
     * Another useful utlitly method that encapsulation aids with, returning the person
     * age as a user friendly, readable String.
     * @return String the persons age as a String
     */
    public String getPersonAgeAsString()
    {
        return personAge + " years old";
    }

    /**
     * This is an accessor method to set the persons age, this method also performs some validation
     * on the value being set
     * @param personAge int the persons age, in years
     */
    public void setPersonAge(int personAge)
    {
        if (personAge < 16 || personAge > 60)
        {
            // Do something here! Throw an exception or log something
        }
        else
        {
            this.personAge = personAge;
        }
    }

    @Override
    public String toString()
    {
        return "EncapsulatedDream{" +
                "personName='" + personName + '\'' +
                ", personAge=" + personAge +
                '}';
    }
}

Overloading in Java, what it is and how you can use it, along with some examples

There are times when developing, when you need to do similar behaviour but with differing input arguments, for example you may have a method that prints something to the console. You may need to print Strings, Integers, and all sorts of other objects. You could (if you really wanted), create a method for each one with some kind off suffix, such as printString(), printInteger(), printMyObject(), however there is a much neater way of doing this, called overloading.

Overloading basically allows you to reuse the method name multiple times, providing you supply a different number and type of input arguments for each one, so that the compiler can tell them apart. This means we can have methods like print(String string), print(Integer integer) and print(String string, Integer integer), this makes code structure a lot neater and is generally considered good practice.

This is quite different to overriding, and you need to be careful not to get the two mixed up, you may be interested in a previous post where I compared the two.

This is one example of overloading that I have up on my SCJP examples Github project :

package com.jameselsey.demo.scjp.oo_concepts;

/**
 * Author:  JElsey
 * Date:    17/08/2012
 *
 * A simple demonstration of what Overloading is and how it can be used. Overloading allows you to have a method with the same
 * name, but overloaded with differing arguments, this is applicable to methods and constructors
 */
public class Overloading
{
    public static void main(String[] args)
    {
        Overloading ol = new Overloading();

        // Same method name, but overloading with differing input arguments
        ol.sayAboutAPerson();
        ol.sayAboutAPerson("James");
        ol.sayAboutAPerson("James", 26);

        // now lets instantiate an object using overloaded constructors
        Person p1 = new Person();
        Person p2 = new Person("James");
        Person p3 = new Person("James", 26);
        System.out.println(p1);
        System.out.println(p2);
        System.out.println(p3);
    }

    public void sayAboutAPerson()
    {
        System.out.println("We don't know anything about this person");
    }

    public void sayAboutAPerson(String name)
    {
        System.out.println("Persons name is " + name);
    }

    public void sayAboutAPerson(String name, int age)
    {
        System.out.println("Persons name is " + name + " and age is " + age);
    }
}

class Person
{
    String name;
    int age;

    // Look! We can overload constructors too, particulary helpful if you want the flexibility to
    // instantiate objects using a variety of arguments
    public Person()
    {

    }

    public Person(String name)
    {
        this.name = name;
    }

    public Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Basics of the switch statement in Java

If statements are great, but sometimes they are just not very practical when you have to test for more than a handful of conditions, have a look at this very poor example of how you build up a long set of if-else statements, its fine for a few checks, but if you’re doing multiple equality checks on a value, its best to use a switch statement for flexibility and readability:


public class PoorIfStatement
{
    public static void main(String[] args)
    {
        int myInt = 5;

        if (myInt == 1)
        {
            System.out.println(myInt);
        }
        else if (myInt == 2)
        {
            System.out.println(myInt);
        }
        else if (myInt == 3)
        {
            System.out.println(myInt);
        }
        else if (myInt == 4)
        {
            System.out.println(myInt);
        }
        else if (myInt == 5)
        {
            System.out.println(myInt);
        }
        else
        {
            System.out.println("Unexpected number...");
        }
    }
}

Now, lets have a look at the same example, but using a switch statement instead, looks cleaner huh?

public class CaseStatements
{
    static int myInt ;

    public static void main(String[] args)
    {

        myInt = 2;

        switch(myInt)
        {
            case 1:
                System.out.println("first");
                break;
            case 2:
                System.out.println("second");
                break;
            case 3:
                System.out.println("third");
                break;
            case 4:
                System.out.println("fourth");
                break;
            case 5:
                System.out.println("fifth");
                break;
            default :
                System.out.println("Unexpected number...");
        }

    }
}

Before we grab our coats and get ready to run, there is a lot more to the switch statement than a mere alternative to a set of ifs, the switch statement can execute more than one case statement! The program will read down from the top of the switch block, and as soon as it finds a suitable match, it will drop in and start processing whatever it finds. Think of it a little bit like a penny machine, the program is looking down the switch block, trying to find one which its penny will fit in, once it does, it pushes the penny in and it drops all the way down. That’s a little strange analogy of it, but its a good one to remember.

It is important to note, that like the above example, if you put in a break statement, then the program will exit out at that point, and not execute any further statements, this is great for if you need to one case statement and not “this case statement and then everything else below me”.

A lot nicer to read isn’t it? And what is better, it is much more flexible. If you need to check for additional conditions, you just need to add a case statement and specify what to do.

Don’t forget, that you can use the default block to catch conditions that don’t specifically match any of the cases, typically you’d put this at the bottom.

Here is another set of examples, that are available up on my SCJP code snippets on Github:

package com.jameselsey.demo.scjp.flow_control;

/**
 * Author:  JElsey
 * Date:    07/08/2012
 *
 * Toying around with the Switch statement a little, running on Java 1.6 so not using switch on Strings yet.
 */
public class SwitchStatement
{
    enum Animals
    {
        CAT, DOG, FISH
    }

    public static void main(String... args)
    {
        switchOnInt(5);
        switchOnInt(0);
        switchOnInt(2);
        switchOnInt(3);

        switchOnChar('a');
        switchOnChar('b');
        switchOnChar('c');
        switchOnChar('d');
        switchOnChar('A');
        switchOnChar('g');

        switchOnEnum(Animals.CAT);
        switchOnEnum(Animals.DOG);
        switchOnEnum(Animals.FISH);
    }

    /**
     * This method switches on an int, notice the (1+2) which is evaluated to 3. Also note no appearance
     * of the break statement in the 3rd block, so default will be execute in addition to 3
     *
     * @param theInt int
     */
    public static void switchOnInt(int theInt)
    {
        System.out.println("\n\nAssessing int :" + theInt);
        switch (theInt)
        {
            case 1:
            {
                System.out.println("The int was 1");
                break;
            }
            case 2:
            {
                System.out.println("The int was 2");
                break;
            }
            case (1 + 2):
            {
                System.out.println("The int was 3, and we're not going to break here either");
                //break;
            }
            default:
            {
                System.out.println("This is the default");
            }
        }
    }

    public static void switchOnChar(char theChar)
    {
        System.out.println("\n\nAssessing char : " + theChar);
        switch (theChar)
        {
            case 'a':
            {
                System.out.println("The char was a");
                break;
            }
            case 'b':
            {
                System.out.println("The char was b");
                break;
            }
            case ('c' | 'd'):
            {
                System.out.println("The char bitwised to make g");
                break;
            }
            default:
            {
                System.out.println("The char didn't match anything, must be something else");
            }
        }
    }

    public static void switchOnEnum(Animals theAnimal)
    {
        System.out.println("\n\nAssessing Animal :" + theAnimal);
        switch (theAnimal)
        {
            case CAT:
            {
                System.out.println("The Animal was CAT");
                break;
            }
            case DOG:
            {
                System.out.println("The Animal was DOG");
                break;
            }
            default:
            {
                System.out.println("The animal was something other than CAT or DOG");
            }
        }
    }
}

String concatenation operator

The string concatenation operator is a bit like a hedgehog, it looks cute and sweet, but try to grab hold of it quickly and you’ll soon know about it…

It’s actually quite simple, however there are some traps that are very easily overlooked (just got caught out with it on a mock test, so I’m here to rant).

The rule of thumb is, that if either one of the operands being “+” is a String, then concatenation will occur, but if they are both numbers, arithmetic addition will occur. Sounds simple right? What do you think the following equate to?

package operators;
public class MockTest
{
    public static void main(String[] args)
    {
        System.out.println(3 + 2);
        System.out.println(3 + "s");
        System.out.println("s" + 2);
        System.out.println("hello " + "world");
    }
}

Think you know it? Well its going to be : 5, 3s, s2. The first one is an arithmetic addition, since both sides of the operator are numeric. The second and third are String concatenation, because at least one of them is a String. The fourth one are both Strings, so concatenation once again.

those are the simple ones, however it can get a lot more tricky, have a look at these common ones that those exam creators try to catch you with!

package operators;

public class MockTest
{
    public static void main(String[] args)
    {
        // Inside brackets are evaluated first, so it'll be 7String
        System.out.println( (3 + 4) + "String");

        /* This is the little bugger that caught me, I vouched for 34String, but its actually 7String.
         Concatenation happens from left to right, one at a time, so it'll break it down to:
            3 + 4 then...
            <thing on left> + "String"

         Careful on these ones!
        */
        System.out.println(3 + 4 + "String");

    }
}


So remember, it’ll evaluate from left to right, one “+” operator at a time. Brackets are always evaluated first however.

Take my examples and have a play!

Happy coding (or raging at the screen if the mock tests catch you out…)

The instanceof Operator

The instanceof operator is a great way for checking if a reference variable is of a given type, in other words, does it pass the IS-A inheritance test. Ask yourself, is a Cat a Dog? A Dog a Cat? Or is a Cat an Animal and a Dog an Animal? In true Harry Hill style, there is only one way to decide….FIGHT!!!!

Have a look at my following example :

package operators;

public class InstanceOfOperatorDemo
{
    public static String myString = "James";

    public static void main(String[] args)
    {
        // myString variable is of type String, so returns true
        System.out.println("myString instanceof String : " + (myString instanceof String));
        // Even though myString is a String, a String is actually an Object (extends from Object), so the below is also true
        System.out.println("myString instanceof Object : " + (myString instanceof Object));

        B b = new B();
        // B is technically an instance of the implemented interface, so this should return true
        System.out.println("B instance of Foo : " + (b instanceof Foo));
        // This should return true also for the same reasons as above
        System.out.println("A new A() instance of Foo : " + (new A() instanceof Foo));
        // An A isn't an instance of a B, its the other way around; a B IS-A A, so returns false
        System.out.println("A new A() instance of B : " + (new A() instanceof B));

        // Any checks with null always return false, since null isn't an instance of anything
        System.out.println("null instanceof Object : " + (null instanceof Object));

        int[] myInts = new int[10];
        // Even though this array contains primitives, the array itself is still an Object at heart..
        System.out.println("myInts instanceof Object : " + (myInts instanceof Object));
    }
}

interface Foo {}
class A implements Foo {}
class B extends A {}

As we can see, a String IS-A Object, so that will pass the instanceof test. It is also important to note, that interfaces are also included in the instanceof check, so by checking if a class or a subclass is an instanceof an interface will return true.

Arrays, no matter what they hold, are always objects themselves, so they can be checked for instanceof too, of which they are Objects, as shown above.

It is important to note, that you can’t use instanceof across class hierarchies, this is something they’ll try to trick you out of in the exam, such as comparing a cat against a dog, you can compare up the hierarchy, but not across it, have a look at this example :

package operators;

public class InstanceOfOperatorCrossHierarchyDemo
{
    public static void main(String[] args)
    {
        // a Cat IS-A Dog, plain and simple
        System.out.println("Is cat an instanceof Animal? : " + (new Cat() instanceof Animal));

        // This will fail to compile, since we are not allowed to instanceof check across the
        // object hierarchy, a Cat is not an instance of Dog, so compiler fails
        System.out.println("Is cat an instanceof Dog? : " + (new Cat() instanceof Dog));
    }
}

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

That’s it! A nice and easy one, please leave me comments if you can suggest improvements!

Happy coding.