Writing Java Code
Now that you've seen how to create and navigate Java resources, let's get to the real cool stuff, writing Java. The Java editor provides a wealth of functions to help you write Java code more efficiently with greater productivity, and, quite frankly, while having more fun. Among the capabilities provided by the Java editor are content assist for Java expression completion, code generation, real time-error detection, quick-fix remedies for coding errors, the ability to work with different JREs, and Javadoc generation.
The organization of the Java editor pane is straightforward and similar to other editors (see Figure 3.5). On the left border is the marker bar, which shows tasks, bookmarks, compiler errors, and quick fixes. The right margin is the overview ruler, which shows error indicators to help you quickly scroll to errors that are currently not visible. On the left of the bottom margin is the message area; on the right are three fields. From left to right these fields indicate if the file is writable or read-only, the toggle status of the Insert key, and the line and column number of your position in the editor.
Figure 3.5 Java Editor
The editor is, as you would expect, completely integrated. This means Java views, such as Type Hierarchy and Outline, update in realtime as you type in the editor. It allows a great deal of customization. The behavior of the editor is specified in your Java preferences under the Editor, Code Generation, Code Formatter, and Refactoring pages.
The editor provides unlimited Undo/Redo through Edit > Undo and Edit > Redo, or Ctrl+Z and Ctrl+Y. View the other keyboard shortcuts by selecting Window > Keyboard Shortcuts. Format your code by selecting Source > Format, or by pressing Ctrl+Shift+F. You can double-click on the editor title bar to maximize it.
Position your cursor in the parameters for a method invocation and then press Ctrl+Shift+Space to see parameter hints (see Figure 3.6). If there are multiple parameters, the editor will highlight the type of the parameter you are editing.
Figure 3.6 Parameter Hints
Many of the code generation and refactoring operations require a valid Java expression to be selected. To do so, select Edit > Expand Selection To, with the options Enclosing Element, Next Element, Previous Element, and Restore Last Selection. To select an expression using keyboard shortcuts, press Alt+Shift and then an arrow key (Up, Right, Left, and Down respectively).
To reference Java elements declared outside your current project, you need to set your project's build path to include their declarations. We'll see how to do this later in this chapter in the section "Creating Java Projects." You will know that you need to do this, for example, when you attempt to add an import statement and the type or package you want to import does not appear in the dialog.
As you edit Java code, you can press Ctrl+Space to see phrases that complete what you were typing. This is done based on an ongoing analysis of your Java code as you edit it. You can do this for both Java source and Javadoc. For example, to quickly enter a reference to class ArrayIndexOutOfBoundsException, type arr, press Ctrl+Space, then continue typing ayi to narrow the list to that class and press Enter. The complete reference is inserted. Content assist can also be activated automatically by setting this preference on the Code Assist page of the Java Editor preferences. Automatic invocation works based on a character activation trigger and a delay. The default activation trigger for Java is the period (.), and for Javadoc it's the "at" sign (@). If you type the activation trigger character as you are entering Java source or Javadoc and then pause, content assist will display suggestions (see Figure 3.7).
Figure 3.7 Content Assist Prompt
If you have trouble using content assist, be sure to check your preferences, specifically the Java Code Generation page and the Java Editor Code Assist page, to verify it isn't disabled.
The content assist pop-up lists matching templates and Java references on the left along with their respective icons (class, interface, and method); on the right is the proposed code. These suggestions come from two places: Java references based on an analysis of your code and your defined code templates. Your defined code templates are part of your Java preferences under Templates. We'll see how to edit these later in this chapter in the section "Using Code Templates." Code templates match what you are typing by template name. Pressing Enter will insert the selected proposal.
In some cases, you can save typing if you have an idea what you want next or what the suggestion should be. Keep typing with the content assist prompt displayed and you will see the list narrowed to match your typing. At any point, select an entry and press Enter. Or, continue typing and when no suggestions apply, the content assist prompt will disappear. This is useful when you have auto content assist enabled, since you can choose to ignore prompts that come up by simply continuing to type what you had been typing.
You can use content assist in a variety of situations. Figure 3.7 shows generation of a stub for a for loop from a template. You can also generate public method templates, while loops, and try/catch expressions. Take a look at the templates in your Java preferences to see what's available. In addition, content assist works for the following.
Overriding Inherited Methods. Position the insertion cursor within a class definition, but outside any method, and activate content assist. You'll see a list of methods this class can override or must define based on an interface implementation (see Figure 3.8).
Figure 3.8 Content Assist Override Method
Import Statements. Type in a Java reference that is unresolved and then activate content assist. As shown in Figure 3.9, you'll see a list of applicable types. Select one and it completes the reference and includes the required import statement.
Figure 3.9 Content Assist Import Statement
You can also type import and begin typing the name of a package or type, and then activate content assist to see a list of types and packages.
Variable References. Begin to type the name of a variable or field in an expression and then activate content assist. It provides a list of possible references, including variables within the scope of the expression (see Figure 3.10).
Figure 3.10 Content Assist Variable Reference
Anonymous Inner Classes. Activate content assist within the body of an anonymous inner class and it will present a list of methods to define (see Figure 3.11).
Figure 3.11 Content Assist Anonymous Inner Class
Parameter Hints. Content assist provides another way to see information about parameter types for a method invocation, in addition to Ctrl+Shift+Space. Position the insertion cursor in the parameters of a method invocation and activate content assist. It displays the parameter types. As you enter parameters or move your cursor over them, it highlights the type of the parameter (see Figure 3.12).
Figure 3.12 Content Assist Parameter Hints
Javadoc. Activate content assist in Javadoc. You can add Javadoc HTML tags and keywords. What's slick about this is that content assist can make smart suggestions based on an understanding of your code. For example, typing @param and then activating content assist will display a list of method argument names. Typing @exception and then activating content assist will display a list of exceptions a method throws.
In addition to content assist, JDT provides other code generation capabilities. These are options available under the Source menu item or from the editor's context menu.
Code Comments. You can quickly add and remove comments in a Java expression with Source > Comment (or Ctrl+/) and Source > Uncomment (Ctrl+\). Adding comments generates line comments, which are prefaced by two backslashes (//) on the lines with the selected expression.
Import Statements. To clean up unresolved references, select Source > Organize Imports to add import statements and remove unneeded ones. You can also select an unresolved reference and use Source > Add Import to add an import statement for that reference only. The keyboard equivalents are Ctrl+Shift+O and Ctrl+Shift+M, respectively.
Method Stubs. You can create a stub for an existing method by dragging it from one class to another. You can also select Source > Override Methods... to see a list of methods to override. Select one or more to have stubs generated.
Getters and Setters. A quick way to create getter and setter methods is to select a field and then select Source > Generate Getter and Setter.... Figure 3.13 shows the Generate Getter and Setter dialog.
Figure 3.13 Generating Getter and Setter Methods
try/catch statements. If you select an expression and then Source > Surround with try/catch, the code is analyzed to see if any exceptions are thrown within the scope of the selection and try / catch blocks are inserted for each. This works well with the Alt+Shift+Up and Alt+Shift+Down expression selection actions to accurately select the code to which you want to apply try/catch blocks.
Javadoc Comments. You can generate Javadoc comments for classes and methods with Source > Add Javadoc Comment. The Javadoc is generated based on template definitions in your Java Templates preferences. Customize these by modifying the typecomment or filecomment template. For more information on this, refer to the section "Using Code Templates" later in this chapter.
Superclass constructor. When you create a class, you have the option to generate constructors from its superclass. If you elect not to do this, you can come back later and add the superclass constructors with Source > Add Constructor from Superclass.
Navigating Java Errors and Warnings
JDT displays two types of errors in your Java code. The first are errors and warnings resulting from compiling your code. These are shown as entries in the Tasks view, as markers on the marker bar, and as label decorations in the views (refer back to Figure 3.5). The second are errors detected as you edit Java code, before it's compiled. These are shown as error clues (red underlining) in the source and on the overview ruler on the right border (small red rectangles). A quick fix icon is displayed for errors for which JDT can suggest a solution. We'll get to quick fix in the section "Fixing Java Errors with Quick Fix" later in this chapter.
Hovering over an error indicator in the marker bar or over text underlined in red displays the error message. Position the text cursor in red underlined text and press F2 to see the error message. Click on an error indicator in the overview ruler to cause the code in error to be selected. Clicking on the error indicator again scrolls the editor to the error and selects the text. You can also select Go to Next Problem (Ctrl+.) or Go to Previous Problem (Ctrl+,) to scroll through and select compiler errors. When you do so, the error message is displayed in the message area.
In the Tasks view, double-click on an error to go to that line in the file with the error. If the file is not open, it is opened in an editor. If the error message is truncated in the Tasks view because of the width of the column, hover over it to display the full message or select the task to see the full text in the message area.
Fixing Java Errors with Quick Fix
For errors having suggested corrections, you will see a quick fix icon on the marker bar. You can use quick fix to correct a wide variety of problems, from spelling errors and missing import statements to declaring local variables and classes. Click on the icon to see a list of possible solutions (see Figure 3.14). You can also position the cursor within the red underlined text and then press Ctrl+1 to display the suggestions. Select an item in the pop-up to see the proposed fix or a description. Press Enter make the correction.
Figure 3.14 Quick Fix Suggestions
If the file you are editing is marked as read-only, quick fix will not work correctly. You'll see the quick fix icon on the marker bar, but clicking on it will not result in any suggested fixes.
Refactoring refers to a class of operations you use to reorganize and make other global changes to your code. You may need to do this in response to API changes, to improve maintainability, or to make naming more consistent. JDT provides state-of-the-art Java refactoring capability that allows you to make changes and update references, including string literals and Javadoc comments. This includes the ability to do the following.
You can move Java elements and, optionally, modify references to the element being moved. This can be used for fields, methods, classes, interfaces, packages, source files, and folders.
You can rename Java elements and, optionally, modify references to the element being renamed. This can be used for fields, variables, methods, method parameters, classes, interfaces, packages, source files, and folders.
This moves a field or method to a superclass.
This creates a new method from the selected expressions.
This lets you change parameter names and order and update all references to the method being modified.
Extract Local Variable
This creates a new variable from the selected expression and replaces all occurrences of the expression with a reference to the variable within the scope of the enclosing method.
Inline Local Variable
This does the opposite of Extract Local Variable. You can use a variable's initialization expression to replace references to it.
You can replace references to a field with calls to its getter and setter methods. This refactoring operation assumes the getter and setter methods do not yet exist.
To refactor your code, select a Java element in one of the views (or the name of an element in the editor) or an expression in the editor, then select Refactor > from the context menu or the main menu. You can also refactor by dragging and dropping Java elements in the Java views, for example, dragging a type from one package to another in the Package Explorer view, or dragging a type onto another class to create a nested type. Some of the refactoring operations require a valid expression to be selected. The Expand Selection To > menu choices and Alt+Shift keyboard shortcuts we discussed earlier at the beginning of the "Writing Java Code" section make this easy.
When you request a refactoring operation, the Refactoring wizard appears (see Figure 3.15). The first page displays the minimum information needed to complete the operation. Typically this is a new name or destination and options, for example, to update references to the changed element. Specify this information and select Finish to perform the refactoring, or select Next > for more options.
Figure 3.15 Refactoring Wizard
Selecting Next displays a list of warnings and potential errors that will occur if you apply the proposed changes to your code. If you select Finish, this list of warnings and potential errors will only be displayed if your code contains an error or warning of greater severity than you've specified in your Java Refactoring preferences. The page after that, shown in Figure 3.16, shows each of the changes and a before-and-after view of the code. You can select to apply none, some, or all of the changes. Expand the elements in the top pane and select an element or subelement to see only the source code for that element.
Figure 3.16 Previewing Refactoring Changes
To undo or redo a refactoring operation, use Refactor > Undo and Refactor > Redo. These operations are different from Edit > Undo and Edit > Redo. The refactoring undo is aware of all of the changes made across all projects; the edit undo is aware only of changes made as a result of the refactoring operation in the active editor.
When you drag and drop elements in the views to affect refactoring, the Refactor > Undo and Redo actions are not available.
There are several ways to browse Javadoc. In the editor, position the cursor in a Java element and then select Edit > Show Tooltip Description or press F2. A small pop-up displays the Javadoc for the selected element, as shown in Figure 3.17. With Show Text Hover selected (the default), move your mouse over a Java element to see its Javadoc.
Figure 3.17 Displaying Javadoc
You can display the Javadoc for a Java element in a browser by selecting a Java element in the editor and then selecting Navigate > Open External Javadoc or by pressing Shift+F2.
To browse Javadoc from the editor, you need to provide JDT with a starting point. To point to Javadoc for a JRE, use your Java Installed JREs preferences as shown in Figure 3.18. Edit an Installed JRE entry and specify the Javadoc URL. You can use a file: URL to point to Javadoc on your file system or an http: URL to point to Javadoc on another machine. This should point to the root folder containing the Javadoc; that is, the folder containing the java, javax, and org folders.
Figure 3.18 Specifying Javadoc for a JRE
To specify the Javadoc location for code in a Java project, from the Navigator context menu, open the Properties dialog on the project. Set the Javadoc location property for the project. If you are referencing declarations in Java code in a JAR file, set the Javadoc location in the properties on the JAR file. This approach also works for the JRE rt.jar file.
Using Code Templates
Templates are code outlines for common Java code or Javadoc patterns. Templates allow you to quickly insert and edit code expressions with a minimum number of keystrokes. They help ensure more consistent code. Templates can contain Java or Javadoc source, variables that are substituted when the template is inserted in the Java code, and a specification of where the cursor should be positioned when editing of the template is complete. JDT suggests variable substitutions based on the template, your Java source, and where in your Java source you are inserting the template. For example, if you select to insert the template to use a for statement to iterate over an array, and your method has an array as a local variable or parameter, JDT will assume this local variable or parameter is the array to use and substitute its name for the template variable.
You insert a template in your Java source through content assist, that is, by pressing Ctrl+Space. Based on what you had just typed and your context (whether you're in a Java code or Javadoc section of the file), you will get a list of possibilities for completing what you had been typing. If what you had just typed matches the name of a template, the template appears as a choice. The Code Assist page of the Java Editor preferences lists several options for code generation such as Insert single proposals automatically and Enable auto activation (see Figure 3.19).
Figure 3.19 Java Editor Code Assist Preferences
Code Assist is the term used in Eclipse 2.0. The Eclipse team plans to change this to Content Assist in 2.1, as this is the more commonly used term.
After you insert a template, if there were variables in the template, the first one is selected to allow you to modify the variable. Use the Tab key to navigate to the next variable in the template. After you navigate through the variables, another Tab will place the cursor in what the template designer believed to be the next logical place where you'd want the cursor in order to continue coding. For example, in the for template, the cursor will be placed in the body of the for statement.
It's easy to create your own templates or to modify those provided. For instance, you might want to change the filecomment or typecomment template to add a copyright or legal notice or add your own template for a try/catch block to invoke a special error handling routine. You do this in your Java preferences under Templates.
In Figure 3.20 you can see a list of templates that come with Eclipse. Select a template to preview it in the bottom pane. Templates can be enabled and disabled. Disabling a template will cause it not to appear as a suggestion in the content assist prompt. To share templates with your team, use the Import... and Export... buttons on the Java Templates preferences page to read and write templates as *.xml files. The Use Code Formatter option indicates you wish to format your code after the template has been inserted according to your Code Formatter preferences.
Figure 3.20 Java Templates Preferences
You can create and edit templates in the Edit Template dialog, shown in Figure 3.21, by selecting New... or Edit.... Name is mandatory, and Description is optional, though useful. Both appear in the content assist prompt. Context indicates whether the template is for Java or Javadoc generation and affects when a template appears in the content assist prompt. To insert a variable, use the Insert Variable... button on the dialog, or press Ctrl+Space in the Pattern field to see a list of possible variables. $(cursor) is the variable that indicates where the cursor is placed after the user has tabbed through the variable fields.
Figure 3.21 Edit Template Dialog
JDT allows you to externalize strings in your Java code, that is, to remove string literals from your Java code to separate files and replace them with references. This is most often done in order to have the strings translated into other languages. The Externalize Strings wizard scans your code for string literals and allows you to indicate which string literals are to be externalized and which are not. JDT also provides support for finding unused and improperly used references to externalized strings. You can use a preference setting to flag strings that have not been externalized as compile errors or warnings. This is on the Errors and Warnings page of the Java Compiler preferences.
To begin the process, select a project, package, or folder and then select Source > Find Strings to Externalize... from the menu to display the Find Strings to Externalize dialog, which shows *.java files containing strings that have not been externalized (see Figure 3.22).
Figure 3.22 Finding Strings to Externalize
Select a file and then Externalize... to go to the Externalize Strings wizard. Alternatively, select a *.java file and then select Source > Externalize Strings... from the menu to display the wizard.
On the first page of the Externalize Strings wizard, shown in Figure 3.23, you specify which strings are to be externalized (for translation) and keys for accessing the strings. Select an entry and then Translate to externalize the string. Select Never Translate if you do not want the string externalized. In each of these cases, JDT annotates your source code with comments indicating your choice. Selecting Skip goes to the next string without taking any action. If you have your preferences set to flag nonexternalized strings as errors or warnings, and you select Translate or Never Translate for the string, it will no longer be flagged as an error or warning. If you select Skip, the error or warning will remain. You can specify a prefix that will be added to the key (when your code is modified, not in the dialog). You can also edit the key to specify a different value by selecting the entry and then clicking on the key. Even if you do not intend to translate a string, it still may by useful to externalize it if you reference the same string value in several places in your code, for example, strings that show up in your user interface. This way, you can be certain they remain the same.
Figure 3.23 Specifying Strings to Externalize
On the second page of the wizard, shown in Figure 3.24, you specify the name and location of the file that contains the externalized strings and a class to access the strings. JDT generates this class and the specified method and adds it to your project.
Figure 3.24 Specifying Location of Externalized Strings
The final page of the wizard is a before-and-after view of your code (see Figure 3.25). In the top pane, you select to apply or not apply changes for each of the proposed modifications. Select Finish to make the changes to your code. This replaces the selected strings with references based on the accessor class, generates the accessor class, and creates the file containing the strings.
Figure 3.25 Externalize Strings Code Changes
To undo string externalizations, select Refactor > Undo. This will also remove the generated accessor class.
You generate Javadoc by exporting it. To do so, you first need to set your Java Javadoc preferences to point to javadoc.exe. This program performs the Javadoc generation. The javadoc.exe program is not shipped as part of Eclipse; it comes with a JDK distribution.
Once you have set the location of javadoc.exe, you can export Javadoc by selecting Export... from the Package Explorer context menu and then selecting Javadoc as the export destination. You have a number of options for generating Javadoc for one or more of your Java projects. Figure 3.26 shows the first page of options. Select Finish to generate the Javadoc or Next > for more options.
Figure 3.26 Generating Javadoc
For the visibility settings, Private generates Javadoc for all members; Package for all default, protected, and public members; Protected for all protected and public members; and Public for only public members. For more information on all the Javadoc generation options, refer to the "Java Preferences" information in the "Reference" section of the Java Development User Guide.
When you generate the Javadoc, you will see a prompt asking if you want to update the Javadoc Location properties of the projects you are generating Javadoc for. You should select to do so. This will enable you to browse the generated Javadoc in the Java editor. Output from the generation shows up in the Console view. You should review this to ensure there were no errors.
Writing Java for Nondefault JREs
Eclipse uses a JRE for two purposes: to run Eclipse itself and to run your Java code. This can be the same JRE or different JREs. The specifications are independent; that is, you can write JRE 1.4 dependent code in an Eclipse running on a 1.3 JRE and vice versa. However, by default the JRE you use to run Eclipse is the same one the JDT uses to run your Java code. If you want to develop Java code that uses a different JRE from the one that runs Eclipse, you need to reconfigure Eclipse to define the JRE you are going to use and to set your JDK compliance preferences.
You specify the JRE your code needs in the Installed JREs preferences under Java (see Figure 3.27). Set the default JRE (with the associated check box) to be the one you just installed. This specifies the JRE used when you develop Java code. It does not affect the JRE used to run Eclipse.
Figure 3.27 Setting Installed JREs Preferences
Set your Compiler compliance level setting, on the JDK Compliance page of the Java Compiler preferences, to either 1.3 or 1.4, depending on what your code requires (see Figure 3.28). This is a global preference that applies to all projects. We do not recommend attempting to manage JRE 1.3 dependent code and JRE 1.4 dependent code in the same workspace. See the section "Multiple JREs, Differing JDK Level" later in this chapter for more information.
Figure 3.28 Java Compiler JDK Compliance Preferences
Each Java project maintains its own classpath. JDT sets a Java project's classpath based on the project's Java Build Path properties, which includes a JRE. If you have multiple projects that depend on different JREs, you have several configuration options. Your options depend primarily on the JDK level of the JREs your code requires.
Multiple JREs, Same JDK Level
You can have multiple Java projects that require different JREs, but the JREs are the same JDK compliance level, either 1.3 or 1.4. You have two options: You can configure to run multiple workspaces, one for each different JRE your code requires, or you can configure to run one workspace containing code requiring different JREs. We recommend the multiple workspace approach because it is simpler and less error prone.
To configure to run with multiple workspaces, use the following procedure.
- Use the data command line parameter to specify a different workspace for each different JRE. Create scripts and/or shortcuts to invoke Eclipse with your different workspaces.
- In each of your workspaces, if the JRE your code needs is not the one Eclipse is running on, specify the required JRE in your Installed JREs preferences. Set the default JRE (with the associated check box) to be the one you installed.
- In each of your workspaces, set the Compiler compliance level setting in your Java Compiler preferences.
To configure to run with multiple JREs in one workspace, do the following.
- Install all JREs required by the code you plan to develop in your workspace in your Installed JREs preferences.
- Set the Compiler compliance level setting in your Java Compiler preferences.
- For each project, set the project's build path to use the correct JRE through the Java Project Properties dialog by selecting Properties from the Package Explorer view context menu. Select Java Build Path and then the Libraries page. Remove the existing JRE entry (rt.jar file). Select Add External Jars... or Add Variable... to add the rt.jar of the JRE you want to use.
Multiple JREs, Differing JDK Levels
If you need to work in one workspace on code that requires different JREs at different JDK levels, practically speaking, you only have one choice. You need to separate the code into different workspaces, according to the steps outlined above. Given that the Compiler compliance level preference is global, and that each project maintains its own build path and classpath information, changing from 1.3 JDK compliance to 1.4 or vice versa will cause all open Java projects to be recompiled. If the compliance is set to JDK 1.4 level and your 1.3 dependent projects are rebuilt, your files may compile, but the generated .class files will not run with a 1.3 JRE (more precisely, be understood by a 1.3 JVM). If the compliance is set to JDK 1.3 level and your 1.4 JRE dependent projects are rebuilt, the compiler will not understand 1.4-specific syntax and you will not be able to produce 1.4 format .class files.