Friday, December 31, 2010

Wrapping things up

... for the year as well as for primitive types.

In my last post I covered Java's primitive types: byte, short, int, long, float, double, boolean, and char. In some situations you'd like to be able to work with values for these types as objects, say, to place them into data structures that can hold objects. For this purpose, as well as others, Java ships with a set of wrapper classes for the primitive types.

All of the wrappers are in the java.lang package. Their class names are simply the capitalized form of the corresponding primitive types (e.g., Double for double) except for int's wrapper, Integer.
Integer io = new Integer (42);
int i = io.intValue();
The wrappers all work similarly, but each one has some special features that are specific to, and very helpful for, their respective type. Let's take Integer for an example. It has some really useful static methods.
int i1 = Integer.parseInt ("42");
int i2 = Integer.parseInt ("2a", 16);  // hexadecimal parsing
String hex = Integer.toHexString (42);  /// ... and back
Integer i1 = Integer.valueOf ("42");
Other wrappers have similar, useful methods.

Integer and the other numeric wrappers have MIN_VALUE and MAX_VALUE constants (remember, those are public static final fields) for the smallest (most negative) and largest values those types can hold. Again, handy in many situations.

The Boolean class has a couple of very useful constants, TRUE and FALSE, which are Boolean instances of true and false. You should use those instead of saying new Boolean (true) because you can avoid creating extra objects that way. In fact, you can stick to using just those two constants this way:
boolean b = someComplexExpression;
Boolean bo = Boolean.valueOf (b);
The valueOf method returns either the TRUE or FALSE instance.

You should generally prefer using valueOf methods over constructors for the wrappers because the JRE might be able to reuse existing wrapper objects. Considering how frequently some values, like one and zero, are used, this could really help out with your memory usage.

I should delve just a little deeper here. Is it really OK to reuse these same objects over and over in different circumstances? It truly is, because wrapper class instances are immutable, that is, their internal states (the values they wrap) cannot be altered after the instances are constructed. This eliminates a whole host of issues with sharing the instances across your application, and in particular across different threads. It is because of this benefit that there isn't, say, a setIntValue() method on Integer. If you need to change a wrapped value, just get a new instance instead. It's OK, the JVM can deal with it.

One final note, which I won't get into deeply: Java 5 introduced a new language feature called "autoboxing", which lets you skip the conversion between primitives and wrappers in almost all cases. So, these statements are legal now:
Integer io = 42;  // autoboxing
int i = io;       // autounboxing
And ... that's a wrap.

Thursday, December 30, 2010

Call of the primitives

OK, so "Call of the Primitives" is my favorite episode of the old Transformers cartoon. Other than it having "primitive" in its title, it probably has nothing else to do with this post.

In Java, a "primitive" type is any type that isn't an array or an object. Primitives are the most basic types available in the language.

I already introduced int in prior posts. An int is specifically a 32-bit signed integer, which means it can range from somewhere around negative two billion to somewhere around positive two billion. (Since I'm not writing a reference book here, I'm not going to find the exact values just for this post. You should definitely go find a good Java reference book for that sort of thing.)

I should note that this particular definition of int was a big deal back when Java was introduced. Two of its primary inspirations, C and C++, did not have a specific definition for int, which seems wacky these days. But in those languages, an int was usually either 16 or 32 bits, depending on the architecture of the machine you were compiling on. This illustrates how Java is more portable than C or C++, because no matter where your code runs, your int variables are always the same size.

Another useful primitive type is long, which is a 64-bit signed integer. Its minimum and maximum values are humungous. Use a long when an int isn't going to be big enough. There are also particular applications where you use long, like expressing the time and specifying serial version UID values (that last one is kind of advanced).

There is also a short type, which is a 16-bit signed integer. It isn't used very often; you should prefer int unless you really need to save those two bytes and you know your values are going to stay between -32768 and 32767. (Yeah, I have the powers of two memorized up to at least 2 to the 16th. Shut up. ;) )

You can go even smaller with byte, which is an 8-bit signed integer. Having byte be signed (-128 to 127) is weird, since when you work with bytes you generally think of them being between 0 and 255. Sorry, Charlie, Java doesn't have unsigned types. Working with byte can be strange for that reason, but it's doable.

All the types I've already discussed are integer types. Java has two primitive floating point types: float and double, which are single-precision and double-precision IEEE 754 floating point number types. There are lots of issues with these types because you just can't represent some decimal numbers well in binary (I think 0.1 is one of them?), so you can get weird results doing math with them. Generally I avoid float; Java prefers to do floating point math in double anyway. If you need true precision, say for scientific calculations, use the class java.lang.BigDecimal instead.

There are a couple of primitive types in Java that aren't numbers. One is boolean, which represents a true or false value. Extremely handy.

The other is char, which is a single Unicode (16-bit) character. To be honest, this is kind of a number as well; you can assign an integer to a char and it will work. Also, I kind of lied up above about Java not having unsigned types, because char is unsigned when you work with it as a number. However, um, don't, because you will confuse yourself and everyone who has to deal with your code. It's really only for character data.

That's all of the primitive types in Java. I should also show you how to represent their values in code so you can assign variables with the types. Here you go.

byte b = 65;
short s = 65;
int i = 65;
long l = 65L;
float f = 65.0f;
double d = 65.0;
boolean bo = true;
char c = 'A';

For byte, short, and int, just use the number you want. For a long stick a capital L on the end. For float add a lowercase f, and for double you can either add a lowercase d or just use a decimal number as is.

The boolean type only takes the keywords true or false, no quotes or nothing needed. Unlike in C or C++ or Perl, you can't equate true to 1 and false to 0.

A single char character is in single quotes / apostrophes / whatever they are really called.

One last thing: there is the type called void, which is "no type" or "nothing" or maybe "mu" for all you Zen folks out there. You cannot have a variable of type void, but you can use it as the return type of methods that don't return anything.

public void clapYourHands (int numberOfTimes) { ... }

The void type isn't considered a primitive, or even a type at all, but I figured I should mention it.

There you go, the primitive Java types. Now you can rock like Grimlock with them.

Wednesday, December 29, 2010

Composition over inheritance

In my last post I revealed the ugly truth about inheritance in object-oriented languages like Java, and how it breaks encapsulation by revealing to subclasses how a superclass works. Here I'll show how we can adjust our class hierarchy (of two classes, big whoop) to preserve encapsulation.

Before that, though, let me lay out another problem with inheritance: sometimes, the base class changes and it's hard to cope. Say I added getHourlyWage() and setHourlyWage() methods to the Employee class. Now the Manager class inherits those methods, but for your application, managers aren't paid hourly, they have a salary. Now what? Should the methods return the salary divided by some number of hours per year? Or -1 because it doesn't make sense? Or maybe throw an exception? Really, you just don't want those methods around, but with inheritance you're stuck with them.

When you learn about inheritance from a textbook, it's referred to as an "is-a" relationship. An instance of a subclass "is-a" instance of a superclass. From our examples, we can say that a Manager object "is-a" Employee object, because the former class derives from the latter base class.

The alternative relationship is called "has-a". This sort of relationship is also called composition, because you will have one object that is composed, at least in part, of other objects within it. The "other objects" stand in for the base class (or classes), and they provide the behaviors of the base class in more direct forms. The key is, because the "other objects" aren't actually base classes, their inner workings are hidden.

OK, so that's a lot of words, so let's make an example. We're going to extract out of Employee the stuff we like about it for using again ... oh yeah, it's pretty much the whole thing. Let's make it just a data-holding object.

public class EmployeeData {
  private String name;
  private int id;

  public String getName() { return name; }
  public void setName (String n) { name = n; }

  public int getId() { return id; }
  public void setId (int i) { id = i; }
}

This isn't terribly exciting, I just added "Data" to the class name. This will get more interesting in a sec. Now let's redefine the Employee class.

public class Employee {
  private EmployeeData data = new EmployeeData();

  public String getName() { return data.getName(); }
  public void setName (String n) { data.setName (n); }

  public int getId() { return data.getId(); }
  public void setId (int i) { data.setId (i); }
}

The class no longer has its own fields for name and ID; it delegates to an internal EmployeeData instance. This is a common pattern for object-oriented programming, and it is called ... the Delegate pattern. Whee. But it is useful, and you'll see it appear here and there.

So we can now break our inheritance for the Manager class.

public class Manager {
  private EmployeeData data = new EmployeeData();

  public String getName() { return data.getName(); }
  public void setName (String n) { data.setName (n); }

  public int getId() { return data.getId(); }
  public void setId (int i) { data.setId (i); }
}

Gee, it's the same as Employee now, except for the name. But this effort is buying us something. I can now add methods for hourly wage support to Employee without messing up Manager. The classes now share a common idea on employee data, instead of one class forcing itself on the other. So we have more freedom to work.

We did lose something here, though; we can't do this.

Employee e = new Manager();

If that isn't important for your application, then don't worry about it. But if it is, you can bring in one last tool to save the day: You can define an interface.

public interface Worker {}

Well, technically yes, that is an interface called "Worker". Let's make it more interesting.

public interface Worker {
  String getName();
  int getId();
}

There we go. The interface has two methods in it (which are automatically public, by the way, since this is a public interface), but the methods are only declared, not defined. They have no bodies, just semicolons. So what gives?

An interface is a contract. It defines a type of object, but doesn't have any of the guts to make it work. Classes have the ability to implement interfaces, which means that they satisfy the contract and supply the guts. At first glance this may seem sort of useless, but interfaces are great for spreading a simple concept across tons of classes that are otherwise really different.

Since both the Employee and Manager classes have getName() and getId() methods that match the interface, they can implement it.

public class Employee implements Worker { ... }
public class Manager implements Worker { ... }

It's totally fine for a class to have extra stuff in it beyond the interface it implements. The Employee class still has setters for the name and ID, and that doesn't fall within the Worker interface. The only requirement is that Employee support at least what its interface demands.

So with this interface, we got back our ability to assign either an Employee or Manager object to the same variable.

Worker w1 = new Employee();
w1 = new Manager();

(There's no reason that I couldn't have made the interface "Employee" and renamed the Employee class to something else, by the way. Sorry if that messed up the example for you.)

So, in the end, we increased our code from two classes to three plus an interface, and it seems like we are fundamentally back where we started. However, remember that we gained some freedoms. First, we have more freedom to mess with the Employee class now that Manager isn't dependent on it. Second, the Manager class is free from inheriting junk from Employee that it doesn't want. Third, with the Worker interface, we are free to define new implementing classes that aren't related to Employee or Manager, yet work with them all interchangeably.

There are even more advantages, but I'll save those for another time.

All of this may cause you to wonder whether you should ever use inheritance and subclasses and all that. The answer is: sure! It's completely appropriate in a lot of situations, and it can be a lot less awkward than using composition. What's important is to understand that there are two strategies available, and you should think about which one fits best for your application.

Thursday, December 23, 2010

The truth about your inheritance

I can't develop many more Java topics without covering object inheritance. It's sort of the embarrassing uncle in the family of object-oriented concepts: once a proud part of the clan, but now held in disregard and ignored as much as possible. But, one day we must come to grips that he's an integral part of the family. In fact, every time you work in Java you are working with inheritance.

In Java, as in probably every other object-oriented language, a class can extend another class. The "base" class passes on its unhidden fields and methods to the "derived" class, which is free to add to or redefine the base class behaviors as it sees fit.

Let's use the time-honored example of an employee. Here's a base class.
public class Employee {
  private String name;
  private int id;

  public String getName() { return name; }
  public void setName (String n) { name = n; }

  public int getId() { return id; }
  public void setId (int i) { id = i; }
}
There's nothing special here.

Some employees are actually managers. We can define a class for them by extending the Employee class.
public class Manager extends Employee {
  private int promotionYear;

  public int getPromotionYear() { return promotionYear; }
  public void setPromotionYear (int py) { promotionYear = py; }
}

The Manager class inherits the public accessor methods of the Employee class, and adds some methods of its own. This means you can do this:
Employee e1 = new Employee();
Employee e2 = new Manager();
// ...
System.out.println (e1.getName());
System.out.println (e2.getName());
An instance of a Manager object is also an instance of an Employee object, so you can work with it either way. The reverse, of course, is not true:
Manager m1 = new Employee();  // nope
While the Manager class inherits the public methods of Employee in a pretty intuitive fashion, it inherits the private fields, well, not so intuitively. Each Manager object certainly has the fields (since they are also Employee instances), but the code in the Manager class cannot get at the fields directly, because, well, they are private.

It's a good idea not to let derived classes have direct access to fields of their base classes (or "superclasses"). The base class may be doing some wacky stuff to the fields and not want to risk having some derived class mess things up ... like the aforementioned uncle. As far as our example goes, the accessors are a fine substitute for that direct access, but if we really wanted to, we could grant it:
public class Employee {
  protected String name;
  // ...
}
A protected field can be accessed within its class, within other classes in its class's package, and also by derived classes in any package. A protected method can be called from those same locations. While protected fields are generally frowned upon, protected methods are pretty much OK.

I hope you're ready for the ugly truth about this object-oriented business. Remember when I said you work with inheritance every time you work in Java? It's true. If a class doesn't extend another class, it automatically extends the class java.lang.Object. It's like the primordial object definition, the source of all classes, or something epic like that.

To be honest it's not so bad. We can do this:
Object o1 = new Employee();
Object o2 = new Manager();
Object o3 = "get to work";  // o3 is a String

The Object class also has some useful (and one horrendous) methods in it, which I can cover some other time.

So, one last thing that might blow your mind, although I hope not. We can add to our Employee class to give every employee a manager.
public class Employee {
  private String name;
  private int id;
  private Manager manager;
  // ...
}
This sort of interdependence between the two classes is perfectly fine in Java.

I haven't really driven home why object inheritance isn't popular these days. The idea of avoiding protected fields points to one of the main reasons, though: as they say, "inheritance violates encapsulation". This means that we can do all sorts of work to encapsulate, or hide, what goes on in our class, but if we allow inheritance, lots of those details can leak out. There are other ways to reuse functionality than inheritance. Still, though, there are plenty of cases where it's appropriate.

Tuesday, December 21, 2010

Some refactoring

So it's been a few days, and I've got this urge to fix something in our Die class. Let's look at the roll methods.
public int roll() {
    Random r = new Random();
    return r.nextInt (numberOfSides) + 1;
}
public int[] roll (int n) {
    int[] rolls = new int[n];
    int i;
    for (i = 0; i < n; i++) {
        rolls[i] = roll();
    }
    return rolls;
}
They work fine, but there's a design problem. The logic for performing multiple rolls is split across the two methods. And when you think about it, rolling once is just a special case of rolling multiple times. We can concentrate our rolling logic into the multiple roll method.
public int[] roll (int n) {
    int[] rolls = new int[n];
    Random r = new Random();
    int i;
    for (i = 0; i < n; i++) {
        rolls[i] = r.nextInt (numberOfSides) + 1;
    }
    return rolls;
}
Instead of reusing the single roll method, it now does its own thing. Besides being tighter design, this ought to be faster. In general, better design yields better performance. Now we can drastically simplify the single roll method.
public int roll() {
    int[] rolls = roll(1);
    return rolls[0];
}
This sort of change is called refactoring. Loosely put, refactoring is messing around with existing code to make it simpler or more organized, without making significant changes to the outward-facing interface. In this case, we rejiggered the rolling code to make it better designed, and faster to boot.

This is not the sort of change you can ask your boss for time to do. Generally, your management and customers are more interested in getting new features, or else getting bugs fixed. Taking time to make the innards of your code better, even if it would yield benefits in the long run, just isn't as appealing to taskmasters.

So what to do? In my opinion: do it when they're not looking. Seriously. If you can identify refactoring opportunities that will yield palpable payoffs, take the time to wend it into work you're already doing. This is one case where you should be entitled to use your expertise as a coder. Refactor mercilessly.

Wednesday, December 15, 2010

Source code

I started a Google Code project for this blog, so I have somewhere to post the code developed as time goes on. The project's home is:

https://code.google.com/p/gettingjavadone/

The code is hosted in a Subversion repository and uses Maven for builds.

Monday, December 13, 2010

Finally, main

A lot of Java tutorials kick things off with a "Hello World" program that you can run right away. This is nice, but it's also troublesome because there are so many concepts wrapped up in that "simple" program, unlike many other languages.

I've covered enough Java concepts in past posts that I can finally present a way to run the Die class that we've been developing. Hopefully, at this point, this seems like a natural next step instead of a lot of magic to be explained later.

You can run any Java class that has a method that starts like this:

public static void main (String args[])

  • The method is public.
  • The method is static. Just as a static field exists only once for all instances of a class, a static method belongs to the class itself and not any particular instance.
  • The method doesn't return anything, thus "void".
  • Its name is main. Usually it is just called "the main method". It's a really good idea not to use the name "main" for any other sort of method.
  • It takes as its single argument an array of String objects.

A string is just a sequence of characters, like "squeamish" or "ossifrage" or "abc123". The class java.lang.String is used for working with strings. Because you end up working with strings all the time, the Java language gives you an easy way to define them, using quotation marks.

String s = "my string";

You almost never need to bother doing new String, unless you're building up a string in some unusual way. A string literal with those quotation marks is what you'll use most of the time.

Here's a main method for our class, then.

public static void main (String args[]) {
    int numSides = Integer.parseInt (args[0]);
    int numRolls = Integer.parseInt (args[1]);
    Die d = new Die (numSides);
    for (int i = 0; i < numRolls; i++) {
        System.out.println (d.roll());
    }
}
  • The method is looking for the args array to have two strings in it: the number of sides on the die to roll, and the number of rolls to make.
  • The two arguments are converted from String objects to ordinary integers using the static parseInt method of the class java.lang.Integer. This method does what you might guess it does: it converts a string like "123" into an integer like plain old 123. The Integer class belongs to a small group of "wrapper classes" that Java provides for bridging the gap between object types and "primitive" types like int.
  • The result of each roll is printed out using an extremely commonly used method, System.out.println. The way to decipher that bit is:
    • "System" is the class java.lang.System, which provides access to, guess what, the system the JVM is running on.
    • "out" is a public static field of the System class. Its type happens to be java.io.PrintWriter, but what's important is that it represents the "way out" for output of your code.
    • "println" is a method on the out field, that spits out what you give it to the console.
So, to run this, first you compile the Die class, then you instruct the Java interpreter to run it.
bill$ ls gjd
Die.java
bill$ javac gjd/Die.java
bill$ java gjd.Die 6 5
4
1
6
5
6
bill$
Since we put the Die class in a package "gjd", it should be stored in a directory named "gjd". Then, javac will compile it into a file "Die.class" in that same directory, which we can run with java as shown. So, finally, after seven posts in this blog, we've finally run something. Thanks for sticking it out until this point. Like I said at the beginning of this post, I needed to build up to the main method to avoid it seeming too strange. Hopefully the method doesn't seem mysterious to you by now. I need to figure out the best way to present the entire Die class to you, so you can see the whole thing in one piece. In the meantime, here's a "Hello World" program in case you've been pining for it. :)
public class HelloWorld {
    public static void main (String args[]) {
        System.out.println ("Hello world!");
    }
}

Friday, December 10, 2010

Arrayed before you

Say we want to roll a die more than once. We could just do this:

Die d = new Die();
int r1 = d.roll();
int r2 = d.roll();
int r3 = d.roll();
int r4 = d.roll();

But that's sort of inefficient. We can do better. We'll take advantage of the array structure. An array is just a numbered, ordered list of values. All of the values in an array have the same type.

Here's the idea of what we want.

int[] rolls = d.roll (4);

We want to roll the die some number of times, and store the results in an array, as denoted by the square brackets.

Let's implement a multiple roll method.

public int[] roll (int n) {
  int[] rolls = new int[n];
  int i;
  for (i = 0; i < n; i++) {
    rolls[i] = roll();
  }
  return rolls;
}
Omigosh, so much new stuff here.
  • This roll method returns an array of integers.
  • This new method is called "roll", like our old single-roll version. Java doesn't have a problem with this; it's called overloading. As long as the two methods have different types of arguments, they don't interfere with each other. I'm even using the single-roll version inside this one.
  • The new keyword is used to create arrays, just like objects. You have to say how big the array is, so the JVM knows how much room to reserve for it. Unlike a lot of other languages, an array's length is fixed at its creation and can't be changed.
  • I'm using a for loop to do the repeated rolls. The for construct takes two statements and an expression in parentheses.
    • An initializer statement (i = 0) which is executed once, before the loop starts.
    • A loop condition (i < n) that's tested before each time the loop's statement block (in those curly braces again) is entered. If the condition passes, the loop runs; if not, the loop stops.

    • A "continue" statement (i++) which is executed at the end of each loop iteration, before the loop condition is tested again. In this loop, I'm using the post-increment operator, which is a fancy way of adding one to a value.
  • Array elements, i.e., each item in an array, are referenced by an index in square brackets. The lowest index is 0, just like in C, C++, and every other sane language.

The for loop fills up the array of n integers with random die rolls. The index starts at 0 and goes up by 1 each iteration until it reaches n - 1. On the next iteration, i will equal n and the loop will exit.

Thursday, December 9, 2010

Final static

Here's our Die class so far, in all its glory.

package gjd;
import java.util.Random;
public class Die {
    private int numberOfSides = 6;

    public Die() {}
    public Die (int n) {
        if (n < 4) {
            numberOfSides = 6;
        } else {
            numberOfSides = n;
        }
    }
    public void setNumberOfSides (int n) {
        if (n < 4) {
            return;
        }
        numberOfSides = n;
    }
    public int roll() {
        Random r = new Random();
        return r.nextInt (numberOfSides) + 1;
    }
}
It still needs some work, though. I want to draw your attention to the number 6. It's sort of special; it's the default number of sides on a die. It's bad form to use a literal number like that, especially in multiple places, because if you decide to change it it's hard to find. Add this line:
public static final int DEFAULT_NUMBER_OF_SIDES = 6;
It's just a field, but it's different from the numberOfSides field in several ways.
  • The field is marked as static. That means that this field exists once for all instances of the class. This makes sense because the idea isn't specific to any one instance.
  • The field is also marked as final. The value of a final field cannot be changed once it's set. That's why it's OK for this field to be public; nobody can mess with it.
  • The field name isn't in CamelCaseLikeThis, but is instead ALL_CAPS_WITH_UNDERSCORES_FOR_SPACES.
It's common to create public static final fields in classes to hold constant values. The naming convention is a carry-over from the C / C++ world. Let's adjust our class then, to use our new constant. Let's also add another constant for the minimum number of sides we accept.
public class Die {
    public static final int MINIMUM_NUMBER_OF_SIDES = 4;
    public static final int DEFAULT_NUMBER_OF_SIDES = 6;
    private int numberOfSides;

    public Die() {
        numberOfSides = DEFAULT_NUMBER_OF_SIDES;
    }
    public Die (int n) {
        if (n < MINIMUM_NUMBER_OF_SIDES) {
            numberOfSides = DEFAULT_NUMBER_OF_SIDES;
        } else {
            numberOfSides = n;
        }
    }
    public void setNumberOfSides (int n) {
        if (n < MINIMUM_NUMBER_OF_SIDES) {
            return;
        }
        numberOfSides = n;
    }

    // ... and the rest ...
}

You can see that the numberOfSides field is no longer assigned by default; the assignment happens in the no-arg constructor instead. The code also reads a little better with the constant names explaining what's going on, instead of just "6" or "4". There's some meaning now.

We're getting close to being able to finally run this thing. There's only one more concept I need to introduce before we are ready to write a main method.

Wednesday, December 8, 2010

Construction

I've already shown code for getting instances of our Die class, but here it is again.

Die d = new Die();

This uses the new keyword followed by the name of the class used like a method call, with the parentheses. In fact, this is a method call, for a special method called a constructor. We didn't need to write a constructor for the Die class because, if you don't bother, you get one for free, as if you had this:

public Die() {}

A constructor looks like any other method, except it has no return type, and it always has the same name as its class.

It's often a good idea to have a "no-arg" (no argument) constructor for your classes, as it makes it easier for others to get instances of your class. Still, there are plenty of cases where you wouldn't want that. Eventually I can get into that.

For now, though, let's make a second constructor that takes the number of sides you want as an argument. If you write your own constructor, you need to write out the no-arg constructor if you still want it.

public Die() {}
public Die (int n) {
  numberOfSides = n;
}

Nice. Oh, except that this lets people create instances with an invalid number of sides; it's the same problem we had when the numberOfSides field was unprotected. Let's tweak it similarly to what we did with the setter method.

public Die (int n) {
  if (n < 4) {
    numberOfSides = 6;
  } else {
    numberOfSides = n;
  }
}
It's a conditional if statement like before, and this time there is an else clause for what to do if the condition is not met.

Saturday, December 4, 2010

Leaving packages in public

In my last post I employed a class called "java.util.Random". That "java.util" part on the front of the class name denotes the package where the class lives. Most Java classes reside in a package; it's a handy way of grouping related classes together. Java also gives you some means of protecting code in a package, means that aren't as draconian as using private.

Unless you're writing some one-off test code, you should place all of your classes inside packages. The convention is to use your domain name, but backwards, e.g., com.awesome or edu.ncsu.wolfpack. It's just a convention, though, you really can use whatever you like as long as the package shouldn't belong to somebody else.

So we should give our Die class a package. You just add this as the first line.

package gjd;

So now the Die class belongs to the package "gjd". The class's full name is "gjd.Die". What's nice about this is that someone else can make a "Die" class in their package and there won't be any confusion.

Now that I've explained what a package is, I can rewrite the roll method to be a little cleaner.

package gjd;
import java.util.Random;
class Die {
    // ...
    int roll() {
        Random r = new Random();
        return r.nextInt (numberOfSides) + 1;
    }
    // ...
}

By using the import statement, I don't have to give the full name of the Random class anymore. I should mention that all the code that's in a class's package is automatically imported for you, as well as the package "java.lang", which includes a ton of useful classes.

So now that our class is in a package, we have a minor problem. As it stands now, the class cannot be used by code in any other package. Java's default visibility is called "package visibility", which means pretty much how it sounds. In order to let our class be used elsewhere, we need to make parts of it public, unsurprisingly by using the keyword public. We'll make the class public, and also its methods.

package gjd;
import java.util.Random;
public class Die {
    private int numberOfSides = 6;
    public void setNumberOfSides (int n) {
        // ...
    }
    public int roll() {
        // ...
    }
}

Great, our class is now available for use outside its package, by any code that needs it.

Thursday, December 2, 2010

Protecting your class

In the last post I put together a very simple class. There's lots more to do with it before it's in good shape. First, though, let's change it just a bit, so that the "numberOfSides" field is of some use.

class Die {
    int numberOfSides = 6;
    int roll() {
      return numberOfSides;
    }
}

Slightly better, although still loaded. You can see that it's simple to reference a field in a method.

Let's make this thing fair.

class Die {
    int numberOfSides = 6;
    int roll() {
        java.util.Random r = new java.util.Random();
        return r.nextInt (numberOfSides) + 1;
    }
}

Whoa, look at that.
  • The method now uses another class, called "java.util.Random". This class is supplied with the JDK, along with many, many others.
  • The first line of the method creates a new object of type java.util.Random. The object is stored as a variable called "r", that can be used from where it's defined until the end of the method.
  • The second line in the method calls a "nextInt" method on r. That method gives back a random number between 0 and one less than the number that you pass to it as an argument. The code passes the number of sides on the die, which is 6, so the nextInt method will return an integer between 0 and 5. You have to add one to that in order to get back an integer between 1 and 6.
What's cool about this change is that the roll method works for any valid number of sides on the die. You can use the class for a 20-sided die, or a 4-sided die, or even a 3-sided die which I don't think I've ever seen. All you need to do is change the number of sides.

I haven't shown you any code that uses this class yet. So, here's some now.

Die d = new Die();
int result = d.roll();

After this code runs, the variable "result" will hold the result of rolling the die, stored in the variable "d".

If I want to do a d20 roll:

Die d = new Die();
d.numberOfSides = 20;
int result = d.roll();

Now let's break it. Bwahaha.

Die d = new Die();
d.numberOfSides = -20;
int result = d.roll();

If you run this code, you'll get an error like this, because the nextInt method requires a positive argument.

java.lang.IllegalArgumentException: n must be positive

This would be a bug. In order for your class to be worth using, it should resist attempts to break it. It's not really as if there are people out there who just want to break your code for fun ... er, well ... regardless, you should write your code so that even unintentional breakage is rare, if not impossible.

The root of the bug is the ability to make the die have an invalid number of sides. As it is now, there is no protection on that numberOfSides field, so you can't stop me from messing it up. This is where we can shield that field from outside interference.

class Die {
    private int numberOfSides = 6;
    // ... and the rest ...
}

By the way, starting a line in Java with "//" makes that line a comment. You like how I just slide this stuff in?

Now the numberOfSides field is private, and only code within the Die class can get at it. So, hooray, the field is safe, but now no one can change the number of sides. Since we might still want to keep that feature, let's add a method that sets it. For some strange reason this sort of method is commonly called a "setter". Go figure.

class Die {
    private int numberOfSides = 6;
    void setNumberOfSides (int n) {
      numberOfSides = n;
    }
    // ... and the rest ...
}

This method takes a single argument of type integer, which is stored as the variable "n" for the method. It sets the numberOfSides field to that value. It doesn't return anything useful to whoever calls it, so the return type is "void".

So, we did all of this work but we brought the same bug back. I could still call the setNumberOfSides method with -20 and create the same error. The difference now, though, is that you can check on what I pass in and reject it, whereas before you didn't have that capability.

Let's fix the setter.

class Die {
    private int numberOfSides = 6;
    void setNumberOfSides (int n) {
        if (n < 4) {
            return;
        }
        numberOfSides = n;
    }
    int roll() {
        java.util.Random r = new java.util.Random();
        return r.nextInt (numberOfSides) + 1;
    }
}

There's now a conditional statement in the setter. If the integer passed in is less than 4, then the field doesn't get set—the method returns right away. Otherwise, the field does get set.

There's actually a better way to handle this, but I'm going to stop for now. We've accomplished the main goal of protecting the Die class from misuse.

In general, it's a great idea to hide as much of the inner workings of your class as possible. Most of the times, you can use methods to define the outward-facing interface to your class, but behind the scenes do whatever you like. This keeps you free to change how the class works internally without breaking the code of those who use the class. It also cuts down on bugs and other strange cases. I'll certainly be developing the ideas of data hiding and encapsulation in future posts.

Tuesday, November 30, 2010

Getting going

Greetings all. My name is Bill, and I'm a Java developer. ("Hi Bill.") My intent for this blog is to be a resource for discussing different aspects of the Java programming language, from the most basic to more advanced topics. Hopefully there will be something for everyone.

I don't have any fixed plans on how I'll approach things. I'll probably bounce between some pretty basic stuff and some more out-there topics, rather than use a more traditional, build-as-you-go model. I think it'll be more interesting that way. It'll give Java veterans (including me) some refreshers, and give Java newbies a peek ahead.

One overriding theme I intend to stick to is that of getting some code done and working. You could spend a lot of time delving into the details of, say, visibility or thread safety or any of many, many other Java topics, but instead I'm going to treat each topic like I treat Christmas shopping: get in, get what you need, get out. You probably have a job to do, anyway, so let's not spend too much time on abstractions.

Still, I do have to start somewhere, with some explanation. So, let's talk about what an object is. For most of you, this may be boring. You're free to wait until my next posting, which might be more to your liking.

Java is all about objects. It's object-oriented, after all. All the code you write will be contained in objects, and that's what you'll run, and break and fix, and deliver.

An object is a hunk of data, or code, or both. That's pretty much it. Some objects are only data, and some are only code, but most are both. Also, the code in an object tends to use the data in an object, although it doesn't have to. From a design point of view, though, you want to keep data and related code together.

Now that you know what an object is, let's make one. You have to define it, and that definition is called a class. I still remember the first class I wrote ... in C++ actually, not Java. You see, before I started learning C++, another object-oriented language, I was working in C, which is a procedural language that doesn't support objects. You could still write functions, though, and so I imagined that in C I could write a function to roll some dice. In pseudo-code, it might work like this:

int[] rollDice (int numberOfDice) {
    int[] results = new int [numberOfDice];
    for (int i = 0; i < numberOfDice; i++) {
      results[i] = random number between 1 and 6
    }
    return results;
  }

So, I thought, in an OBJECT-ORIENTED WORLD, it's about the dice, not the rolling. The dice roll themselves! What an epiphany.

Let's start a Java class for a die, which is one dice ... one of a set of dice ... well, you know what I mean.

class Die {
  int numberOfSides = 6;
  int roll() {
    return 2;
  }
}

OK, well, it's a loaded die right now. But you can see that it has some data (the number of sides) and some code (to roll it). The data would normally be called a "field", while the code would be called a "method".

Let's get just a little more detailed here, just so all our bases are covered for those new to Java.

This class definition starts with the word "class", followed by the name of the class. Class names should always be capitalized; it's a convention. For multi-word class names, use CamelCaseLikeThis. After the class name, the definition is in curly brackets, or curly braces, or curlies, or whatever you want to call them.

The field called "numberOfSides" is set equal to 6, which is hopefully pretty obvious. The field has a "type", which describes what sort of data it is. This field is type "int", which is short for "integer", which is a whole number ranging from around negative two billion to around positive two billion. So, you know, a regular number without a fractional part.

The method called "roll" also has a type, which indicates what sort of data it produces. This method always produces the number 2, which we can represent as an int. The 2 gets send back out of the method by that "return" statement. You can see that curly brackets are used again here, this time to hold the body of the method. And, last thing: The method name is followed by parentheses, which lets you know that it's a method and not a field or something else.

So, in my opinion, that's plenty of information to get this blog off and running. To bootstrap it, if you will. This class is by no means done, but it will compile. In ensuing posts we'll improve it, and even get it to where we can run it.