Java Tech: The Sweet Song of the BlueJ, Part 1 Blog

Version 2

    {cs.r.title}



              
                           

    Contents
    What is BlueJ?
    Installing B lueJ
    Touring the GUI
    BlueJ by Example
    Conclusion
    Resources
    Answers to Previous Homework

    I recently discovered a Java product called BlueJ. This product, symbolized by the image of a blue jay, is used to teach object orientation to students. In contrast to the harsh-sounding blue jay (which happens to be a member of the crow family), BlueJ is anything but harsh. This simple yet powerful product presents a short learning curve, which is ideal for students.

    Welcome to the first installment in a two-part series that explores BlueJ. This article introduces the product, reveals its reason for being (Java instructors, take note), shows how to install BlueJ, and takes a tour of BlueJ's GUI. The article climaxes with an example that illustrates several BlueJ features.

    Note: This series is based on BlueJ version 2.0.4 and J2SE 5.0 running on the Windows 98 SE platform.

    What is BlueJ?

    BlueJ is an integrated Java environment that has been designed to teach object orientation with the Java language. BlueJ is based on the earlier Blue system, a programming language and integrated environment. BlueJ, an almost identical environment to Blue, replaces the Blue language with Java.

    BlueJ provides a project manager and an editor. It relies upon an installed Java 2 Standard Edition software development kit for compilation, debugging, and other facilities. Tools are fully integrated in BlueJ: compilation from within the editor, compiler error message display in the editor, setting breakpoints in the editor, and so on.

    BlueJ was developed to provide an appropriate environment for teaching object-orientation concepts to students. Unlike many other environments, BlueJ emphasizes classes and objects as its basic units of interaction. Students are not required to learn Java'spublic static void main(String [] args) method, or worry about input/output prior to creating and interacting with objects: BlueJ takes care of those tasks on behalf of the student. Regarding main(), BlueJ's developers believe that introducing students to that method first is problematic. Why begin teaching object orientation by introducing a method that is essentially procedural? The BlueJ team discovered that this approach only confuses students, who must also learn about arrays right from the start. They found that it was better to first focus on classes and objects, and introduce the main()method, input/output, and arrays after the student becomes more comfortable with Java.

    BlueJ is easy to use; students can begin working with BlueJ without needing a lengthy introduction to the environment. BlueJ lets students visually and interactively create classes and interconnect them. Students can then instantiate objects from those classes, invoke methods, specify arguments to those methods via dialogs, view return values via dialogs, and visually inspect object state. This product is freely available, a benefit to students who cannot afford costly licenses (BlueJ cannot be sold for profit).

    BlueJ originated at Monash University in Melbourne, Australia. It is currently being maintained as a joint project among Deakin University, the University of Kent, and the University of Southern Denmark.

    Installing BlueJ

    BlueJ is available for Windows, the Mac OS, Linux/Unix, and other operating systems. Regardless of the operating system, J2SE 1.4 or higher must be installed. Because BlueJ relies on tools made available via the J2SE SDK, installing only the J2SE JRE is not sufficient.

    For Windows platforms, the BlueJ distribution is contained in file bluejsetup-xxx.exe, wherexxx is a version number. For example, the BlueJ version 2.0.4 distribution is contained inbluejsetup-204.exe.

    The installer portion of the Windows BlueJ distribution lets you select the directory into which to install BlueJ. It also presents the option to install a shortcut into the Start menu and on the desktop. When the installer completes, you'll findbluej.exe in the installation directory. This program starts BlueJ.

    When BlueJ first runs, it searches for a J2SE 1.4 or higher SDK. If it finds more than one version, BlueJ presents its BlueJ Launcher dialog box, which lets you select the desired SDK. If BlueJ isn't able to find a suitable SDK, this dialog box lets you search for the SDK.

    After installing BlueJ with a specific J2SE SDK, you can change to another SDK version by including bluej.exe's/select command-line option the next time you run that program. In response, the BlueJ Launcher dialog box appears.

    Note: You can install different versions of BlueJ and associate a different installed version of the J2SE SDK with each BlueJ version. For example, you can associate BlueJ 2.0.1 with J2SE 1.4.2 and associate BlueJ 2.0.4 with J2SE 5.0.

    Touring the GUI

    BlueJ manages Java-based projects. The current project is revealed in its main window. In Figure 1, the main window presentspeople--an example project that ships with BlueJ--as the current project.

    BlueJ's main window identifies the people project
    Figure 1: BlueJ's main window identifies thepeople project

    The main window divides into five sections: menu bar, project tool bar, class diagram, object bench, and message area. The menu bar offers Project, Edit, Tools, View, and Help menus:

    • Project provides menu items that create a new project, open an existing project, save the current project, quit BlueJ, and more. For example, I selected Open Project... to open the examplepeople project shown in Figure 1.
    • Edit provides menu items that introduce new classes into the current project, introduce new dependencies between classes, remove classes and dependencies, and more.
    • Tools provides menu items that compile all uncompiled classes in the current project, compile only the selected class, set preferences, and so on.
    • View provides menu items that show or hide dependencies, show or hide the debugger, and more.
    • Help provides menu items that show an about box, check for a new version of BlueJ, take you to a BlueJ tutorial, and so forth.

    The project tool bar, located on the left side of the main window and just below the menu bar, consists of four buttons that, respectively, introduce new classes into the current project, introduce "extends" or "implements" dependencies between classes, introduce "uses" dependencies between classes (for example, aLibrary class uses a Book class by implementing an array of Book objects), and compile the entire project.

    The class diagram, on the right side of the project tool bar, graphically displays the current project. It presents a project description note icon, class icons, and dependency arrows:

    • The project description note icon (in the upper-left corner) describes the current project. When creating a new project, double-click the icon to enter information about the project, including its author and how to run the project. This helps others understand your project and how to work with it.
    • Class icons identify classes and interfaces (which BlueJ regards as a special kind of class). The upper portion of the icon presents the class name. Abstract classes and interfaces are revealed by <<abstract>> or<<interface>> just above the name. The icon of the current class (that is, the class that will be compiled when you choose Compile Selected from the Tools menu) is identified with a darker border and a pair of diagonal stripes in the lower-right corner of its icon. If a class has not been compiled, the entire lower-right area consists of diagonal stripes.
    • Dependency arrows reveal relationships between classes. Solid lines with hollow arrow heads indicate either "extends" relationships (where the arrow points to the superclass) or "implements" relationships (where the arrow points to the interface). In Figure 1, two solid lines reveal "extends" relationships between Staff and Person, and between Student and Person.Person is the superclass. Dashed lines indicate "uses" relationships. Each class pointed to by the arrow is used by the class on the other end of the dashed line. For example, Figure 1 shows that Person is used by Database. In other words, Database references Personin its source code.

    Right-click the mouse on a class icon and a pop-up menu appears. This menu offers various options, including compilation. If a class's source code has not been compiled, you can compile that source code by choosing Compile from the pop-up menu.

    The object bench, toward the bottom of the main window, identifies various objects that have been created. Objects are created by right-clicking a compiled class's icon, selecting one of the "new" constructor menu items from the pop-up menu, and responding to dialogs that let you name the object and (if appropriate) pass arguments to the constructor. Figure 1 shows a single staff1 object icon on the object bench. The object represented by that icon was created by choosing the top menu item from the pop-up menu.

    A single-line message area appears below the object bench. As you work with BlueJ, various messages appear in this area.

    BlueJ by Example

    Let's use BlueJ to construct a simple payroll application. This application introduces several BlueJ features and will get us comfortable working in this Java environment.

    Our payroll application will consist of the abstract classEmployee, the concrete subclasses CEO andSalesperson, and the concrete driver classRunPayroll. Although this latter class provides amain() method for generating a payroll, we'll create and interact with CEO and Salespersonobjects prior to looking at RunPayroll.

    Start BlueJ. Before we introduce classes, we need a project. From the Project menu, select New Project. A New Project dialog box appears. Choose an appropriate directory that will contain the project directory, and enter payroll as the project/directory name.

    The main window's title bar identifies payroll as the current project. Except for the project description note icon, the class diagram is empty. If you examine the payrolldirectory, you will find two files: bluej.pkg andREADME.TXT. The first file contains project settings and the second file contains a template for documenting the project.

    We should document the project, to assist people wanting to use our project, before introducing any classes. That way, we won't forget to do so later. Double-click the project description note icon and, via the resulting editor window, enter the project title, project purpose, project version or date, instructions for starting the project, project authors, and additional user instructions. Figure 2 reveals the documentation I've chosen.

    Document a project to help others learn about and use that project
    Figure 2: Document a project to help others learn about and use that project

    The editor window presents a changed/saved indicator in the lower-right corner. This indicator lets you know if there are changes that need to be saved. You can periodically save changes (while performing a lengthy edit) by selecting Save from the Class menu. For now, exit the editor by selecting Close from the Class menu, or by clicking the X button on the right side of the title bar. In response, the editor automatically saves changes.

    We're ready to introduce our first class: Employee. Click the New Class... button on the project tool bar. A Create New Class dialog box appears. Enter Employee in the dialog box's Class Name field. Also, select the Abstract Class radio button in the Class Type group. Figure 3 presents this dialog box with our choices.

    The Create New Class dialog box lets you choose a class name and a class type
    Figure 3. The Create New Class dialog box lets you choose a class name and a class type

    After clicking the OK button, an Employee icon, with<<abstract>> above its name, appears in the class diagram. Because we next need to enter source code into the Employee class, right-click this icon and select Open Editor from the pop-up menu, or double-click that icon. Either way, Figure 4 shows the resulting editor window with a class template for Employee.

    Class templates provide skeletal source code for classes
    Figure 4. Class templates provide skeletal source code for classes

    Employee's class template provides skeletal source code that must be modified. Key in the source code below (making appropriate changes to the skeletal source code) and then exit the editor.

     
    /** * Abstract class Employee - the superclass for * CEO, Salesperson, and so on. * * @author (Jeff Friesen) * @version (1.0) */ public abstract class Employee { // employee name private String name; /** * Construct an employee. * * @param name employee name */ public Employee (String name) { this.name = name; } /** * Retrieve the employee's name. * * @return employee's first and last names */ public String getName () { return name; } /** * Calculate employee's payment. * * @return payment owed to employee */ public abstract double payment (); }
    
     

    For our purposes, an Employee is nothing more than a name. This class is abstract to reflect the abstractpayment() method: different kinds of employees can be paid in different ways (weekly, weekly plus commission, and so on).

    Right-click the Employee icon and select Compile from the pop-up menu. A Compiling... message appears in the message area. If a syntax error is detected, the editor window appears, that window highlights the line containing the syntax error, and the syntax error is identified in the editor window's status area (at the bottom of the window). For example, if I lowercaseString in private String name;, I receive the syntax error shown in Figure 5.

    A class named string does not exist
    Figure 5: A class named string does not exist

    Students learning Java will probably have trouble understanding syntax errors. To help them in this situation, BlueJ's editor window provides a "?" button. Click that button and a Message dialog box appears. That dialog box provides further information about the nature of the syntax error. The Message dialog box in Figure 6 suggests that a class name may have been incorrectly spelled.

    The Message dialog box helps students more quickly discover the cause of a syntax error
    Figure 6: The Message dialog box helps students more quickly discover the cause of a syntax error

    Fix the error, close the editor, and recompile. If there are no more errors, a "Compiling...Done" message appears in the message area. Furthermore, the diagonal stripes (apart from the two diagonal stripes that indicate the current class) disappear from the lower half of the compiled class's icon.

    There's not much we can do with an abstract class. Therefore, we'll create a CEO class and connect it toEmployee:

    • Click the project tool bar's New Class... button. From the Create New Class dialog box, enter CEO in the Class Name text field. Make sure the default Class radio button is selected prior to clicking OK. A CEO class icon appears to the right of the Employee class icon in the class diagram.
    • Select CEO and drag it belowEmployee. Then click the project tool bar's solid arrow button. The message area tells you to select the subclass. Click CEO. The message area next tells you to select the superclass. Click Employee. A solid arrow pointing from the CEO subclass to the Employeesuperclass appears.

    After drawing the arrow, BlueJ makes this connection inCEO's source code, as shown in Figure 7.

    Employee CEO class hierarchy
    Figure 7. The Employee/CEO class hierarchy has been established through extends Employee

    As with Employee, CEO's class template provides skeletal source code that must be modified. Double-click the CEO icon, key in the source code below (making the appropriate changes to the skeletal source code), and then exit the editor.

     
    /** * CEO describes a chief executive officer. This * employee receives a salary based on a weekly * rate. * * @author (Jeff Friesen) * @version (1.0) */ public class CEO extends Employee { // CEO weekly salary private double weeklySalary; /** * Construct a CEO. * * @param name CEO's name * @param weeklySalary CEO's weekly salary */ public CEO (String name, double weeklySalary) { super (name); setWeeklySalary (weeklySalary); } /** * Establish the CEO's weekly salary. * * @param weeklySalary payment owed to CEO each * week */ public void setWeeklySalary (double weeklySalary) { this.weeklySalary = weeklySalary; } /** * Calculate CEO's payment. * * @return payment owed to CEO each week */ public double payment () { return weeklySalary; } }
    
     

    Compile this class's source code. Assuming compilation succeeds, let's create a CEO object from our compiledCEO class. We can then test its methods to make sure that everything works. Right-click the CEO icon and select the "new CEO(String name, double weeklySalary)" constructor menu item, shown in Figure 8.

    A compiled class's constructors appear at the top of its pop-up menu
    Figure 8. A compiled class's constructors appear at the top of its pop-up menu

    In response to that menu item, the Create Object dialog box appears. Enter everything shown in Figure 9 (including the double quotes around John Doe) and click OK.

    The Create Object dialog box lets you name an object and specify arguments for its constructor
    Figure 9: The Create Object dialog box lets you name an object and specify arguments for its constructor

    A theBoss object icon appears on the object bench. Right-click that icon. Figure 10 reveals a menu from which you can invoke inherited methods, invoke CEO'spayment() and setWeeklySalary() methods, inspect object state, and remove the object.

    An object icon's pop-up menu lets you invoke that object's methods, inspect its state, and more
    Figure 10. An object icon's pop-up menu lets you invoke that object's methods, inspect its state, and more

    Let's invoke the payment() method, by selecting the "double payment()" menu item. BlueJ runs that method and displays its return value in a Method Result dialog box. As Figure 11 illustrates, that value is 2000--the weekly salary.

    The Method Result dialog box displays a method's return value
    Figure 11. The Method Result dialog box displays a method's return value

    The Method Result dialog box presents Inspect and Get buttons for inspecting a returned object and getting a new object, based on the returned object's type to the object bench. Both buttons are disabled because they make no sense in relation to primitive types, such as double. Close the dialog box.

    Select the "inherited from Employee" menu item (see Figure 10) followed by the "String getName()" menu item from the resulting submenu. This executes the getName() method in theEmployee portion of our theBoss object. Figure 12 reveals the expected "John Doe" string.

    The Method Result dialog box no longer disables the Inspect and Get buttons
    Figure 12. The Method Result dialog box no longer disables the Inspect and Get buttons

    Unlike in the previous Method Result dialog box, the Inspect and Get buttons are enabled. We can use them to inspect or get a new"John Doe" String object. Let's inspect the object by clicking Inspect. Figure 13 shows the resulting Object Inspector dialog box.

    The Object Inspector dialog box displays the values in an object's instance fields
    Figure 13. The Object Inspector dialog box displays the values in an object's instance fields

    In addition to presenting instance field values, the Object Inspector dialog box provides a "Show static fields" button. Click this button to view the values of a class's static fields (which are shared by all objects created from that class). BecauseString contains no static fields, don't count on seeing them.

    The Object Inspector dialog box presents reference field values differently than the values of primitive type fields: curved arrows indicate references. Double-click the arrow or click the Inspect button (assuming that private char [] value is highlighted) to inspect the array of characters object. Figure 14 presents a partial view of that object.

    A partial view of the array of characters object
    Figure 14. A partial view of the array of characters object

    Finally, let's take a look at the state of ourtheBoss object. Select the Inspect menu item from the pop-up menu previously shown in Figure 10. Figure 15's Object Inspector dialog box reveals the contents of theBoss's instance fields.

    The complete state of our theBoss object
    Figure 15. The complete state of our theBossobject

    Now that we've constructed the Employee andCEO portions of our payroll application, let's turn our attention to Salesperson. Introduce aSalesperson icon into the class diagram and connect that icon to the Employee icon. You've already seen how to do this with the CEO icon. Now open the editor by double-clicking the Salesperson icon and enter the source code below:

     
    /** * Salesperson describes an employee that sells * the company's products. This employee receives * a salary based on a weekly rate and a * commission for each sold product. * * @author (Jeff Friesen) * @version (1.0) */ public class Salesperson extends Employee { // salesperson weekly salary private double weeklySalary; // salesperson commission private double commission; // number of sold products private int numProductsSold; /** * Construct a Salesperson. * * @param name salesperson's name * @param weeklySalary salesperson's weekly * salary * @param com salesperson's commission for * each sold product * @param nsp number of sold products */ public Salesperson (String name, double weeklySalary, double com, int nsp) { super (name); setWeeklySalary (weeklySalary); setCommission (com); setNumSoldProducts (nsp); } /** * Establish the salesperson's weekly salary. * * @param weeklySalary payment owed to * salesperson each week */ public void setWeeklySalary (double weeklySalary) { this.weeklySalary = weeklySalary; } /** * Establish the salesperson's commission. * * @param com amount of additional money * salesperson receives for each sold * item */ public void setCommission (double com) { commission = com; } /** * Establish the number of sold products. * * @param nsp number of sold products */ public void setNumSoldProducts (int nsp) { numProductsSold = nsp; } /** * Calculate salesperson's payment. * * @return payment owed to salesperson each * week */ public double payment () { return weeklySalary + commission * numProductsSold; } }
    

    Compile Salesperson, create an object from this class, invoke methods, and inspect object state. This exercise will reinforce what you've previously learned.

    We have almost everything we need for our payroll application. The final piece is a RunPayroll class whosemain() method drives the application. That class's source code appears below.

     
    /** * Generate the weekly payroll for all employees. * * @author (Jeff Friesen) * @version (1.0) */ public class RunPayroll { public static void main (String [] args) { Employee [] employees = { new CEO ("John Doe", 2000), new Salesperson ("Jane Doe", 600, 50, 20) }; for (int i = 0; i < employees.length; i++) System.out.println (employees [i]. getName () + " makes " + employees [i]. payment () + " this week."); } }
    

    RunPayroll references Employee,CEO, and Salesperson. This suggests a "uses" relationship between RunPayroll and these classes. After creating a RunPayroll icon, employ the dashed-arrow button on the project tool bar to introduce three separate dashed arrows into the class diagram, where each arrow points from RunPayroll to each of the other class icons. Enter the above source code into RunPayroll and compile that class. Figure 16 shows the resulting class diagram.

    Dashed arrows identify RunPayroll's referenced classes
    Figure 16. Dashed arrows identify RunPayroll's referenced classes

    Figure 16 also shows a pop-up menu resulting from a right-click on the RunPayroll icon. From that menu, select the "void main(String [] args)" menu item. You are greeted by Figure 17's Method Call dialog box.

    The Method Call dialog box lets you pass arguments to methods
    Figure 17. The Method Call dialog box lets you pass arguments to methods

    We don't have any String arguments to pass to themain() method. If we did, we would specify those arguments as a comma-delimited list between the brace characters. Click the OK button instead. BlueJ's terminal window appears. According to Figure 18, that window reveals our payroll application's output.

    BlueJ's terminal window displays payroll output
    Figure 18. BlueJ's terminal window displays payroll output

    Conclusion

    Are you planning to teach Java? Consider using BlueJ. This integrated Java environment has been designed to teach object orientation with the Java language. BlueJ emphasizes classes and objects right from the start; it doesn't confuse students by first focusing on the procedural main() method, arrays, and input/output.

    BlueJ is easy to install and run. It requires an installed J2SE SDK (version 1.4 or higher). If you ever need to switch from one SDK version to another version, include bluej.exe's/select command-line option when starting BlueJ.

    BlueJ offers a simple yet capable GUI divided into menu bar, project tool bar, class diagram, object bench, and message area. We made extensive use of this GUI as we developed and tested an example payroll application.

    I have some homework for you to accomplish:

    • Use BlueJ to add a FactoryWorker class that subclasses Employee. Factory workers receive a payment based on a fixed amount per item they create. For example, a worker receives five dollars for each created item. If the worker creates 100 items in a week, the worker's payment is 500 dollars. ExtendRunPayroll to include FactoryWorker.

    Next time, "Java Tech" completes this series by investigating BlueJ's debugging, documentation generation, and JAR-packaging capabilities. You also learn how to configure BlueJ and discover a useful feature known as the code pad.

    Resources

    Answers to Previous Homework

    The previous "Java Tech" article presented you with some challenging homework on language lessons. Let's revisit that homework and investigate solutions.

    1. Is it okay for the clone() method to invoke an overridable method?

      It is not okay for the clone() method to invoke an overridable method, because the overriding method might modify object state while the clone() method executes, and these changes could damage either the object being cloned, the cloned object, or both objects. Let us see how this damage might occur, beginning with an examination of the classes below:

       
      class Parent implements Cloneable { public Parent clone () throws CloneNotSupportedException { System.out.println ("Superclass clone() " + "method invoked"); someMethod (); return (Parent) super.clone (); } void someMethod () { System.out.println ("parent someMethod() " + "invoked"); } } class Child extends Parent { ArrayList<String> al; Child () { al = new ArrayList<String> (); al.add ("One string"); } public Child clone () throws CloneNotSupportedException { System.out.println ("Subclass clone() " + "method invoked"); System.out.println ("ArrayList size " + "before " + "super.clone() = " + al.size ()); Child c = (Child) super.clone (); System.out.println ("ArrayList size " + "after " + "super.clone() = " + al.size ()); return c; } void someMethod () { System.out.println ("child someMethod() " + "invoked -- clearing " + "array"); al.clear (); } }
      

      Child's clone() method outputs the size of an ArrayList, invokessuper.clone(), and then outputs theArrayList's size once more. Each output operation symbolizes work needed to create a clone. Thesuper.clone() method call invokesParent's clone() method. In turn, that method invokes the overridable someMethod().Child's version of that method clears theArrayList. If we were to execute Child c1 = new Child ();, followed by Child c2 = c1.clone ();, we would see the output below. This output indicates thatChild's state has changed, as a result of thesuper.clone() method call.

       
      Subclass clone() method invoked ArrayList size before super.clone() = 1 Superclass clone() method invoked child someMethod() invoked -- clearing array ArrayList size after super.clone() = 0
      

      This example is trivial. Perhaps you might share your own experiences with failure caused when a superclassclone() method invokes an overridable method.

    2. Should interfaces be used to only export constants (i.e., no methods are part of such interfaces, only constants)? Although I didn't discuss constant interfaces in this article, think of it as another lesson that you should know.

      Interfaces should not be used to only export constants, because that usage violates the purpose for interfaces--they are types that describe auxiliary capabilities of the classes that implement them. For example, java.util.Iterator is an interface type whose implementing classes serve as iterators, in addition to their main reasons for existence. Constant interfaces have nothing to do with types; they exist to save time entering source code. Fewer keystrokes are needed to refer to an interface-exported constant (only the constant name needs to be entered, after implementing the interface once) than a class-exported constant (the class name, a period character, and the constant name need to be entered each time the constant must be specified).

      Dependence on constant interfaces can lead to maintenance problems. As time passes, a class will evolve; one or more of the interface's constants may no longer be required. However, the class still needs to implement the interface (including all of the constants), to maintain binary compatibility. This can lead to confusion. Also, we end up polluting the class's namespace and the namespaces of any subclasses with the constants. This gets really bad if we create a single interface that conveniently declares all of our constants in one place. Imagine hundreds of constant names polluting the namespace.

      J2SE 5.0 provides a better alternative to constant interfaces: static imports. This language feature lets you refer to the static members of a class without having to qualify those members with the class name. Consider the following static imports:

       
      import static java.lang.Math.*; // import all static members // or, to import specific members only import static java.lang.Math.PI; // import static member PI only import static java.lang.Math.cos(); // import static member cos() only
      

      You can now specify sin() instead ofMath.sin(), PI instead ofMath.PI, and cos() instead ofMath.cos(). Constant interfaces have gone the way of the dinosaur.

      
    http://today.java.net/im/a.gif