C H A P T E R  1

image

Getting Started with Java 7

The Java language has been around for quite some time now. It has been labeled a “legacy language,” and some say that Java will become outdated and a language of the past. Those who advocate languages that do not run on the Java Virtual Machine (JVM) make these statements, and they are untrue. With each release, the Java language gains new features, adding new capabilities to help developers of the JVM become more productive.

The first major release of Java was distributed in 1996, and since then the language has undergone many changes. Over the years, the language has added features such as inner classes, JavaBeans, regular expressions, generics, enumerations, and so on. With each release, the Java language changes the way in which applications are built and used. The last major update of Java was Java 1.6 (Java 6 Tiger), which was released in late 2006. That release featured updates that offered new features to the Java language, as well as other languages on the JVM. Scripting language support with JSR223 paved the road for integration between Java and other languages to integrate with one another.

The Java 7 release marks one of the most monumental updates to the language in years. Not only does Java 7 offer more features but it also enhances the ability to write other languages for the JVM. Constructs such as the try-with-resources and the diamond operator add productivity to the language. Invoke Dynamic increases the language’s ability to offer support for dynamic languages. The new I/O library enhances platform independence and makes I/O easier to use. New graphics features have been added along with new Swing components to make graphical user interfaces (GUIs) better. All these features and more offer one of the largest updates to the Java language in years. The language is better than ever, and it has a user community that rivals any other.

This chapter will introduce newcomers to the Java language. It will help those who are unfamiliar with the language to get started. You will learn how to install Java and configure it for your environment. You will learn basics of Java such as how to create a class and how to accept keyboard input. Documentation is often overlooked, but in this chapter you will quickly learn how to create great documentation for your Java code. In the end, you will quickly get up and started developing with Java 7.

1-1. Downloading and Installing Java 7

Problem

You want to install the Java 7 Development Kit (JDK 7) on your computer workstation or laptop.

Solution

Download the requisite Java 7 distribution for your platform, or download and build OpenJDK. Once downloaded and/or built, run installation scripts as necessary.

To download the binary distribution of the JDK, please visit the Oracle downloads page and choose the correct binary Java SE release for your platform of choice.

images Note If you are working on Mac OS X, you have a couple of options for working with OpenJDK. To download sources for OpenJDK, please visit http://openjdk.java.net and build the sources on your workstation or laptop, or go to the Google Source project openjdk-osx-build and download an installer.

How It Works

The JDK is distributed in a binary format via the Oracle Corporation. If interested in obtaining the most recent build of the latest JDK, go to the OpenJDK site, download, and build the sources. Since the binary installer contains an installation wizard, I will not cover the wizard installation in detail. However, there are a few key things to note regarding the installation process. Be sure that you download the JDK and not the Java Runtime Environment (JRE) because you will want to develop with Java. The JRE does not include the tools that are required to develop and compile Java code. Instead, the JRE merely provides the runtime required to load and execute Java applications on the JVM.

When you initiate the installation wizard, you will be presented with a number of different features that can be installed. Specifically, you will be given the choice to install Development Tools, Demos and Samples, and Source Code. I recommend installing everything because you will benefit from looking at the demos and samples, and you may also benefit from looking at the JDK sources. You can specify a default installation location for the JDK. By default, the wizard will want to install to the Program Files area on a Windows machine. I recommend changing this location to another directory that contains no spaces in its name and is made at the root of your OS drive. This will alleviate CLASSPATH issues in the future. I recommend installing to C:Javajdk1.7.0 on a Windows machine. If you have multiple drives, you can install to any of them, although it is not recommended to install the JDK on an external drive.

On all platforms, you can have more than one JDK installed. This allows you to run older Java programs that rely on deprecated or removed Java tools, and at the same time provides the ability to work with the most recent Java platform. Hence, it is a smart choice to install the JDK into a directory containing the JDK release number. In our case, we are installing into the directory jdk1.7.0.

If you are working on a Solaris or Linux platform, you will have the same type of wizard that is provided for use with Microsoft Windows. However, if you are working on a Mac OS X platform, you may not be provided with such a wizard. The JDK 7 Developer Preview from Oracle is bundled as a disk image, and the installation involves opening the disk image and dragging the JDK bundle to the designated location within the OS. You also have the option of going to the OpenJDK site and downloading the sources so that they can be built and installed on your operating system. There is also a dmg (disk image) available for the latest builds of OpenJDK for OS X hosted on the Google Code repository. Since this is the easier route to take, we choose to install from the disk image.

Go to the openjdk-osx-build project on Google Code (http://code.google.com/p/openjdk-osx-build/) and download the most recent OpenJDK disk image. You will want to install the universal disk image if it is available. Once downloaded, you can open the disk image, and run the Installation.pkg file. Once you run the installer, a standard OS X installation wizard will begin. Unlike the Microsoft Windows installation wizard, you cannot select the installation path. Once the installation completes, you can go to the Java Preferences utility and see the OpenJDK 7 listed as one of the options. Drag it to the top of the list to ensure that Java 7 will be the default runtime.

images Note If you are running Java applications that are not compatible with Java 7 on OS X, you can use the Java Preferences utility to drag the JDK of your choice to the top of the list of available JDK installations to set as default.

1-2. Configuring the CLASSPATH

Problem

You want to execute a Java program or include an external Java library in the application you are executing.

images Note Would you like to run a “Hello, World” program now that you’ve installed the JDK as described in the previous recipe? Not to worry. That’s the very next recipe. First though, you should configure your CLASSPATH.

Solution

Set the CLASSPATH equal to the directory location of the user-defined Java classes or Java Archive (JAR) files that you need to have access to for executing your application.

images Note It is a good idea to organize your code; it is also good to organize where you place your code on the computer. A good practice is to place all your Java projects within the same directory; it can become your workspace. Place all the Java libraries that are contained in JAR files into the same directory for easier management.

Let’s say that you have a directory named JAVA_DEV located at the root of your OS drive, and all the files that you need to have access to are located in this directory. If this is the case then you would do the following at the command line or terminal:

  • Setting CLASSPATH on a Microsoft Windows platform:
set CLASSPATH=C:JAVA_DEVsome-jar.jar
  • Setting CLASSPATH on a UNIX platform:
export CLASSPATH=/JAVA_DEV/some-jar.jar

Alternately, the javac tool provides an option for specifying resources that need to be loaded for an application. On all platforms, setting the CLASSPATH using this technique can be done as follows:

javac –classpath /JAVA_DEV/some-jar.jar

Of course, on Microsoft Windows machines the file path will use the backslash () instead.

How It Works

In order for the JVM to find the resources that are needed to execute Java applications, there needs to be a specified search path that can be used to find associated files. That being said, the CLASSPATH can be used by the JVM in order to find and load any Java sources or JAR files that may be required. The CLASSPATH is a parameter that tells the JVM where to look for classes and packages, and it can be set using an environment variable or command-line argument.

When executing Java programs, the JVM finds and loads classes as needed using the following search order:

  • The classes that are fundamental to the Java Platform and are contained in the Java installation directory
  • Any packages or JAR files that are located within the extension directory of the JDK
  • Packages, classes, JAR files, and libraries that are loaded somewhere on the specified CLASSPATH

images Note JAR files are a used to package applications and Java libraries into a distributable format.

You may need to load more than one directory or JAR file into the CLASSPATH for an application. This could be the case if your dependencies are located in more than one location. To do so, simply use the delimiter for your operating system (either ; or :) as a separator between the locations specified for the CLASSPATH as such (on UNIX):

export CLASSPATH=/JAVA_DEV/some-jar.jar:/JAVA_LIB/myjar.jar

or

javac –classpath /JAVA_DEV/some-jar.jar:/JAVA_LIB/myjar.jar

When loading the resources for a Java application, the JVM loads all the classes and packages that are specified in the first location, followed by the second, and so on. This is important because the order of loading may make a difference in some instances.

In order to add all the JAR files within a specified directory, use the wildcard character (*) after the directory containing the files. You can do so as follows when using the –classpath option of the javac tool:

javac –classpath /JAVA_DEV/*:/JAVA_LIB/myjar.jar

Specifying a wildcard will tell the JVM that it should be loading JAR files only. It will not load class files that are located in the directory specified with the wildcard character. In order to include Java class files that are located in a directory, do not specify the wildcard. For example, if you want to load all JAR files and class files within the /JAVA_DEV directory, you would specify the following:

javac –classpath /JAVA_DEV/*:/JAVA_DEV

Subdirectories contained within the CLASSPATH would not be loaded. In order to load files that are contained within subdirectories, those directories and/or files must be explicitly listed in the CLASSPATH. However, Java packages that are equivalent to the subdirectory structure will be loaded. Therefore, any Java classes that reside within a Java package that is equivalent to the subdirectory structure will be loaded.

1-3. Writing an Executable Java Class

Problem

You want to develop an executable Java program that can be run from the command line or terminal.

Solution

Create a Java class that includes a main() method. A class containing a main() method is executable because this method will be loaded when the application is executed. In the following Java class, a “Hello World” message will be printed at the command line when executed.

public class MainTest {

public static void main(String[] args) {
    System.out.println("Hello World");
    }
}

How It Works

To make a Java class executable, simply add a main() method somewhere within the class that will be executed when the class is run. The main() method should take care of any application setup or instantiations in order to run the program. The main() method is comparable to the “driver” for the application. It should always be specified using the same definition, including the static modifier so that it can be invoked without creating an instance of the class first. The return type of the method should always be void, meaning that nothing will be returned from the method. Lastly, the signature of the main() method should include a String array as an argument. This String array allows arguments to be passed to the program at runtime. Zero or more arguments can be passed to the program using a space to separate them.

In the following example class, the main() method is printing each of the arguments that are passed to the program at runtime:

public class MainTestArguments {
    public static void main(String[] args){
        if(args. length > 0){
            System.out.println("Arguments that were passed to the program: ");
            for (String arg:args){
                System.out.println(arg);
            }
        } else {
            System.out.println("No arguments passed to the program.");
        }
    }
}

First, the length of the args String array is tested to see whether it is greater than zero. If it is, the method will loop through each of the arguments in the String array using a for loop, printing each out along the way. If there are no arguments passed to the program, the length of the args String array will be zero, and a message indicating as such will be printed.

To learn how to execute this program and pass arguments via the command line or terminal, please see Recipe 1-4.

1-4. Compiling and Executing Java Class

Problem

You have written a Java class and you want to compile and execute it.

Solution

First, if you are planning to make use of the CLASSPATH environment variable, set up your CLASSPATH to include all the required resources to run your Java class. For more information on doing this, please see Recipe 1-2. Next, compile your Java class using the javac tool that ships with the JDK. For example, to compile the class named MainTestArguments.java that was created in Recipe 1-3, use the following syntax from the command line or terminal:

javac MainTestArguments.java

images Note In order to compile Java sources, you must be located in the same directory containing the sources, or specify the full path to the sources when issuing the javac command. So using the command line enables you to change directories until you are within the same directory that contains the code you want to compile.

As a result of using the javac utility, you will see a file named MainTestArguments.class that is created in the same directory. In order to execute this class, use the java tool that also ships with the JDK:

java –cp .org/java7recipes/chapter1/recipe1_03/MainTestArguments

Note that you do not include the .java suffix after the class name when executing the class. Similarly, you do not include a .class suffix after the class name. However, you do append the Java package directory structure to the front of the class name, and use the –cp flag to set the CLASSPATH. The preceding command will execute the MainTestArguments class, and you should receive the following output when executing this application:

No arguments passed to the program.

How It Works

In order to compile a Java class, all required classes and libraries must be in the CLASSPATH. This can be accomplished either by setting the CLASSPATH environment variable or by using the -classpath option of the javac tool, as demonstrated in Recipe 1-2. Once all the dependent resources are specified in the CLASSPATH, use the javac tool to compile the sources into class files. To use the javac tool, you must either be working from within the command line or terminal unless you are working within an integrated development environment (IDE). The command can be issued from within the directory in which the Java source file resides; otherwise, the entire path to where the source is located must be specified along with the file name. For instance, if the MainTestArguments.java source file resides within the path /JAVA_DEV/org/java7recipes/chapter1/recipe1_03, you must either change directories (cd) to that location, or specify the entire path along with the file name as follows:

javac /JAVA_DEV/org/java7recipes/chapter1/recipe1_03/MainTestArguments.java

Once the javac tool compiles the code, another file with the same name and a .class suffix will be generated. This resulting file can be run on the JVM by use of the java command. To run any executable Java class file that has already been compiled, issue the java command, followed by the name of the class as you see here:

java –cp /JAVA_DEV/org/java7recipes/chapter1/recipe1_03/MainTestArguments

To maintain consistency throughout the examples, the command shown here runs the compiled Java class file from a directory different from the one in which it resides. The same rules apply for the java command as with the javac utility, in that you can use the java command from within the same directory of a Java class file if the Java class is not contained within any Java packages or from another directory, and use the –cp flag to include the entire path to the file along with the file name (or the path to the file from the directory in which you are currently located). The –cp flag will set the CLASSPATH for the java command.

As demonstrated in the preceding example, using the java command can become a bit trickier when Java packages are introduced. A Java package is basically a directory that can contain a Java source file. Most Java applications use packages for organization of code, and packages are often nested within each other to form an organized file system of code. Because packages are directories, you may think that it is possible to traverse within them in order to get to the same package containing your Java source to issue the java command, but that is not correct. In order to run a Java class that is contained within a Java package, you must traverse to the root of the application source structure (outside of the outermost package) and specify the package path along with the file name. Another option is to include the parent directory of the outermost package within the CLASSPATH, as demonstrated by the example using the –cp flag. To learn more about packages, please see Recipe 1-12.

1-5. Printing Output

Problem

You want to print output from a Java program to the command line or terminal.

Solution

Pass the output in String format to System.out.println() from anywhere within the class. For example, suppose that you would like to display the message “I love Java 7” for those running your program. To do so, make use of the System.out.println() utility by doing the following:

System.out.println("I love Java 7");

How It Works

The System class acts as a utility for Java application developers. It cannot be instantiated, and it contains a myriad of fields and methods to assist developers in performing commonly used tasks. As such, printing to the command line is a very common way of displaying messages to application users, or printing error codes and messages for debugging purposes.

System.out is the standard output stream for the Java language. It is already open by default, so it can be used right away without any setup. What is actually occurring when System.out.println() is invoked is that a PrintStream object is used, and the println() method of that PrintStream object displays the text passed into the object.

Using the System.out stream to print messages to the command line is essential for any command line–based application. However, often Java applications are not used from within the command line. In such cases, the System.out stream is not visible to the user unless the application has been coded so that the stream is presented to the application display. In any case, System.out can still be useful for displaying messages because any message sent to it will be printed in the server log for web applications. As for Swing, JavaFX, or other GUI–based applications, System.out can still be handy for a myriad of tasks including debugging.

1-6. Passing Arguments via the Command Line

Problem

You want to pass arguments to a Java application via the command line or terminal.

Solution

Run the application using the java command-line tool and specify the arguments that you want to pass into it after the application name. For example, suppose you want to pass the arguments "one" and "two" to the MainTestArguments class that we created in Recipe 1-3. To do so, you should first traverse into the directory containing the outermost package org and then issue the command as follows:

java org/java7recipes/chapter1/recipe1_03/MainTestArguments one two

You should see the following output:

Arguments that were passed to the program:
one
two

How It Works

As you know by now, all Java classes that are executable from the command line or terminal contain a main() method. If you look at the signature for the main() method, you can see that it accepts the String[] argument. In other words, you can pass an array of String values into the main() method. Therefore, since the main() method is the first piece of code that is executed when running a Java class, any arguments that you pass to the class will go into this String array so that they can be used from within the application.

Commonly a series of Strings or numbers is passed into an executable Java class, and then the method iterates through the elements of the String array and performs some processing. In the case of the class that was used in the Solution to this recipe, two String values were passed into the main() method and printed out. Much more complex work can be performed with the arguments that are passed in as well. What happens if you try to pass a number into the main() method? It will convert the number to a String automatically and it will be treated as a string of numeric characters rather than as a numeric value. If you attempt to pass the numbers 1, 2, 3, and 4 to the MainTestArguments class, it will simply print those numbers back out. Anything that is passed into the main() method is treated as a String. If you need to work with number values for calculation purposes, String-to-Integer conversions can be performed. You can read more about converting Strings to number values in Recipe 2-6.

1-7. Obtaining and Setting Environment Variable Values

Problem

The application you are developing needs to make use of some OS environment variables. You are also interested in setting the values of environment variables from within the Java application.

Solution

Make use of the Java System class to retrieve any OS environment variable values. The System class has a method getenv(), which accepts a String argument corresponding to the name of a system environment variable. It will then return the value of the given variable. If no matching environment variable exists, a NULL value will be returned.

In the following example, the Java class EnvVars accepts an environment variable name and prints out its value. As noted previously, if there is not a matching variable name, a NULL value will be returned and an error message will be displayed:

public class EnvVars {

public static void main(String[] args) {
        if (args.length > 0) {
            String value = System.getenv(args[0]);
            if (value != null) {
                System.out.println(args[0].toUpperCase() + " = " + value);
            } else {
                System.out.println("No such environment variable exists");
            }
        } else {
            System.out.println("No arguments passed");
        }
    }
}

If you are interested in retrieving the entire list of environment variables that is defined on a system, do not pass any arguments to the System.getenv() method. Once you have obtained the Map of variables, you can iterate through them. This technique is demonstrated in the example below. Once the Map of variables is obtained, the program iterates through each of the variables and prints the corresponding value:

public class EnvVarsAll {

    public static void main(String[] args){
        if(args.length > 0){
            String value = System.getenv(args[0]);
        if (value != null) {
            System.out.println(args[0].toUpperCase() + " = " + value);
        } else {
            System.out.println("No such environment variable exists");
        }
        } else {
            Map<String, String> vars = System.getenv();
            for(String var : vars.keySet()){
                System.out.println(var + " = " + vars.get(var));
            }
        }
    }

}

How It Works

The System class contains many different utilities that can aid in application development. One of those is the getenv() method, which will return a value for a given system environment variable. Environment variables are stored in a Map, a collection of name/value pairs; the getenv() method is used to pass the name of an environment variable, and it will return that variable’s value. If there is no environment variable name that matches the one passed to getenv(), a NULL value is returned.

If you want to obtain an entire list of all environment variables, do not pass any String value to System.getenv(). When no value is passed to System.getenv(), a Map of all system environment variables is returned. Such a Map can be traversed so that the name/value pairs can be read, displayed, and used as necessary.

1-8. Documenting Code with Javadoc

Problem

You want to document some of your Java classes to assist in future maintenance.

Solution

Use Javadoc to place comments before any of the classes, method, and fields that you want to document. To begin the comment, use the characters /** and then begin each subsequent line that you want to add to the comment with an asterisk (*). Lastly, to end the Javadoc comment, close it with the characters */ at the end. The following method is commented with Javadoc:

    /**
     * Accepts an unlimited number of values and
     * returns the sum.
     *
     * @param nums
     * @return Sum of numbers
     */
    public static BigInteger addNumbers(BigInteger[] nums){
        BigInteger result = new BigInteger("0");
        for (BigInteger num:nums){
            result = result.add(num);
        }

        return result;
    }

Such comments can be added to the beginning of classes and fields the same way. Not only does this assist when looking through the code but it also provides a standard documentation set in HTML format. The JDK provides another useful tool named Javadoc that parses the named Java source file and formulates HTML documentation based upon the defined class elements and Javadoc comments. If no Javadoc comments exist within the source, some default documentation will be produced automatically. The following command will create the Javadoc for a Java source file named DeprecationExample.java. Keep in mind that the same rules apply when using the Javadoc tool as with using javac. You must reside within the same directory as the source file or prepend the name of the file with the path to where it is located.

javadoc java7recipes/chapter1/recipe1_08/DeprecationExample.java

This command will produce several HTML files containing the documentation for the class, methods, and fields.

How It Works

Generating documentation for applications can be quite tedious. Maintaining documentation can be even more troublesome. The JDK comes packaged with an extensive system for documentation known as Javadoc. Placing some special comments throughout the code source and running a simple command-line tool makes it easy to generate useful documentation and keep it current. Moreover, even if some of the classes, methods, or fields in an application are not commented specifically for the Javadoc utility, default documentation will be recorded for such elements.

To create Javadoc comments, begin the comment line with the characters (/**). Although optional since Java 1.4, a common practice is to include an asterisk as the first character of every line within the comment. Another good practice is to indent the comment so that it aligns with the code that is being documented. Lastly, close the comment with the characters (*/).

Javadoc comments should begin with a short description of the class or method. Fields are rarely commented using Javadoc. The comment can be several lines in length and can even contain more than one paragraph. If you want to break comments into paragraphs, then separate them using the <p> tag. Comments can include several tags that indicate various details regarding the method or class that is being commented. Javadoc tags begin with an asterisk (@), and some of the common tags are as follows:

  • @param: Name and description of a parameter
  • @return: What is returned from the method
  • @see: Reference to another piece of code

You may also include inline links within Javadoc to reference different URLs. To include an inline link, use the tag {@link My Link}, where link is the actual URL that you want to point at and My Link is the text that you want to have appear. There are also many other tags that can be used within Javadoc comments including {@literal}, {@code}, {@value org}, and many others. For a complete listing, please see the Javadoc reference on the Oracle site.

As mentioned in the solution to this recipe, the Javadoc utility is used to create the actual documentation set for a given class. This utility ships along with the JDK and resides within the bin directory of your JDK install. Running the Javadoc utility is much like running javac in that you must either reside within the same directory as the sources you want to run the utility against or prepend the name with the full path to the sources. Once initiated, Javadoc will produce several HTML files that will document all features of the given class. The utility is smart enough to provide some default documentation for each class, method, and field without any Javadoc comments being manually provided. However, it is highly recommended to include Javadoc comments before each class and method to indicate a description of functionality.

The Javadoc tool can also be run against entire packages or source. To do this, simply pass the entire package name to the Javadoc tool rather than individual source file names. For instance, if an application includes a package named org.juneau.beans, all source files within that package can be documented by running the tool as follows:

javadoc org.juneau.beans

To generate Javadoc for more than one package at a time, separate the package names with spaces as follows:

javadoc org.juneau.beans org.juneau.entity

Another option is to specify the path to the source files using the –sourcepath flag as follows:

javadoc –sourcepath /java/src

One thing to note is that by default, the Javadoc tool will generate the HTML and place it into the same packages as the code itself. This can become a cluttered nightmare if you like to have source files separate from documentation like I do. You can set up a destination for the generated documentation by passing the –d flag to the Javadoc tool. There are also a number of other flags that can be passed to the tool in order to customize your documentation. Some of the most commonly used flags are listed in Table 1-1. For a complete listing of the flags, you can issue the Javadoc –help command.

images

The Javadoc tool contains many options, but it is a great way to document application sources. The best part is that if a change is made to the sources, the Javadoc tool can simply be run again to update the documentation. This recipe only touches upon the many options available for use with Javadoc. If you are interested in learning more, please look at the documentation available on Oracle’s web site.

1-9. Marking Features as Deprecated

Problem

You want to mark a method in your Java class as deprecated because a newer version of the method has been created, and the older version will be going away in a future release.

Solution

Use the @Deprecated annotation to signify that the method has been deprecated and may be taken out of future versions of your class. Also make sure that you use the @Deprecated Javadoc tag to mark the method as deprecated within the documentation. In the following class, the addNumbers() methods is deprecated in lieu of a newer, more robust application programming interface (API) that has been put into place. The code marks the method as deprecated, and its Javadoc makes use of the @Deprecated tag to inform users that the new API should now be used:

public class DeprecationExample {

    public static void main(String[] args){
        BigInteger[] arr = new BigInteger[2];
        arr[0] = new BigInteger("1");
        arr[1] = new BigInteger("25");
// Use the older, deprecated method
        System.out.println(addNumbers(1, 25));
        // Use the newer, non-deprecated method
        System.out.println(addNumbers(arr));
    }

    /**
     * Accepts two values and returns their sum.
     *
     * @param x
     * @param y
     * @return
     * @deprecated The newer, more robust addNumbers(BigInteger[]) should
     *             now be used
     */
    @Deprecated
    public static int addNumbers(int x, int y){
        return x + y;
    }

    /**
     * Newer, better method that accepts an unlimited number of values and
     * returns the sum.
     *
     * @param nums
     * @return
     */
    public static BigInteger addNumbers(BigInteger[] nums){
        BigInteger result = new BigInteger("0");
        for (BigInteger num:nums){
            result = result.add(num);
        }

        return result;
    }

}

How It Works

The word deprecated has a few different meanings. It can mean that a specified class, method, or field is no longer important and should not be used. It can also mean that the specified item contains a poor programming practice, is insecure, contains bugs, or is highly inefficient. Any feature that has been designated as deprecated may or may not be available in a future release.

There are a couple of different ways to designate a class, method, or field as deprecated. First, the @Deprecated annotation was added to the Java language in release 1.5. This annotation can be placed before the signature of a class, method, or field. When the compiler uses a program element marked with the @Deprecated annotation, a warning will be issued. This warning will indicate to the developer that said program element should no longer be used. In the solution to this recipe, you saw that the @Deprecated annotation was used as follows:

    @Deprecated
    public static int addNumbers(int x, int y){
        return x + y;
    }

When the addNumbers(int x, int y) method is called, the compiler will issue a warning. Many IDEs (integrated development environments) will place a line through the element if a developer tries to use it. Another way to indicate that a class, method, or field is deprecated would be to mark it with the @deprecated Javadoc tag. By doing so, the Javadoc will add special HTML to any tagged elements so that they can be easily identified. When marking Javadoc with the @Deprecated tag, a space or newline should follow the tag, and a paragraph should be used to explain why the element has been deprecated and what new functionality has been added to replace it. Again, the example in the solution to this recipe showed how this was done:

    /**
     * Accepts two values and returns their sum.
     *
     * @param x
     * @param y
     * @return
     * @Deprecated The newer, more robust addNumbers(BigInteger[]) should
     *             now be used
     */

Using the @Deprecated annotation will cause a compiler warning if you are compiling a class that calls a deprecated method, and it also automatically marks Javadoc for the element as deprecated. Therefore, it is the preferred method of marking an element as deprecated. The ability to deprecate adds functionality to code in that it allows for a smooth transition to newly developed code in order to phase out older code. It also warns all developers using deprecated code to begin learning the updated API, rather than simply removing functionality and leaving the developer stranded to learn on their own.

1-10. Creating Methods in a Class

Problem

You want to encapsulate some functionality that is contained within a Java class so that it can be reused in other places.

Solution

Abstract the functionality that you want to encapsulate and place it into a method so that it can be reused. Methods reside within Java classes and they encompass a body of code that is used to perform a task. They can accept zero or more parameters, and they may or may not return a value. In the following Java class, the functionality for adding two numbers and displaying the result has been placed inside a method named addNumbers(). Similarly, the functionality for multiplying the same two numbers has been placed inside of a method named multiplyNumbers(). These two methods are called from the main() method.

public class CalculationExampleOne {

    static int num1 = 0;
    static int num2 = 4;

    public static void main(String[] args){
        if (args.length > 1){
            num1 = Integer.valueOf(args[0]);
            num2 = Integer.valueOf(args[1]);
        }
        // Call the addNumbers method
        addNumbers();
        // Call the multiplyNumbers method
        multiplyNumbers();

    }

    /**
     * Adds num1 and num2, then prints the sum.
     */
    public static void addNumbers(){
        int sum = num1 + num2;
        System.err.println("The sum of num1 and num2 is " + sum);
    }

    /**
     * Multiplies num1 and num2 then prints the product.
     */
    public static void multiplyNumbers(){
        int product = num1 * num2;
        System.out.println("The product of num1 and num2 is " + product);
    }

}

As you can see, both methods encapsulate some mathematical functionality, produce a result, and print a value. If the numbers 5 and 6 are passed to the program, the following result will be displayed:

The sum of num1 and num2 is 11
The product of num1 and num2 is 30

How It Works

Java methods are another one of the fundamental building blocks of a Java application. Any Java application will contain at least one method. In fact, a Java desktop application cannot execute without the main() method. Methods encapsulate functionality so that it can be reused. Methods can be made public, protected, or private depending on the level of access that is required. If a method has a private modifier, it can be invoked only from within the same class in which it is contained. If a method has a protected modifier, any class within the same package can invoke it. Any methods designated with a public modifier are accessible to all classes in the application. Methods can return a value if needed, but they do not have to do so. Methods can accept zero or more arguments, and the data type of each argument that is passed must be denoted within the method signature.

The method signature consists of the access modifier, return value, method name, and argument list. Following are two examples:

public static void multiplyNumbers()

private int divideBy(int divisor, int dividend)

The first example demonstrates a method that has a public modifier. The method with this signature can be invoked without instantiating its containing class because it is marked as static. This method is called multiplyNumbers and it accepts no arguments. The second example demonstrates a private method signature. The method with a signature like the one in the second example is named divideBy, it returns an int value, and it accepts two arguments with int types.

In the solution to this recipe, two class fields with the int data type are declared. When the class is executed, two numbers will be accepted and stored into the class fields. The main() method then calls each method implemented in the class separately to perform calculations on the numbers that are stored within the class fields. As you can see, to invoke a method simply call it by name and pass any arguments that it requires within the parentheses at the end of the name. If no arguments are required, place an empty set of parentheses at the end of the name, as demonstrated by the Solution to this recipe.

addNumbers();

Methods can accept arguments, such as the divideBy() method that was discussed previously in this section. To learn more about passing arguments to a method, please see Recipe 1-11. Likewise, methods have the ability to return values. Please see Recipe 1-11 for more information on returning values from methods.

1-11. Passing Arguments to Methods and Returning Values

Problem

You want to create a method that accepts arguments and returns a result.

Solution

Declare any method(s) that will accept arguments by naming the specific number of arguments and the data types of the arguments within the method signature. Once declared, only those specified argument types will be acceptable as input for that method. If the method will return a value, list the returning value data type within the method signature prior to the method name. The following class contains the same functionality as the one listed in the solution for Recipe 1-10. However, instead of the program declaring class fields that will hold the value of the integers, two fields are declared within the main() method and then passed to each method when they are called:

public class CalculationExampleTwo {

    public static void main(String[] args){
        int num1  = 0, num2 = 0;

        if (args.length > 1){
            num1 = Integer.valueOf(args[0]);
            num2 = Integer.valueOf(args[1]);
        }
        // Call the addNumbers method
        addNumbers(num1, num2);
        // Call the multiplyNumbers method
        System.out.println("The product of num1 and num2 is " +
                multiplyNumbers(num1, num2));

    }

    /**
     * Adds num1 and num2, then prints the sum.
     */
    public static void addNumbers(int num1, int num2){
        int sum = num1 + num2;
        System.err.println("The sum of num1 and num2 is " + sum);
    }

    /**
     * Multiplies num1 and num2 then prints the product.
     */
    public static int multiplyNumbers(int num1, int num2){
        int product = num1 * num2;
        return product;
    }
}

Running this class will yield the same result as the class in Recipe 1-10, but instead of each method using global variables, they will use the int arguments that are passed instead.

How It Works

Methods can be very useful for encapsulating logic that performs tasks. This encapsulation can help to make code more readable and reusable. For instance, if you were to code a calculation operation such as one that is demonstrated in the Solution to this Recipe, it makes sense to place it into a separate method. Otherwise, you would have to rewrite that calculation logic each time you wanted to use it.

This Recipe discusses two of the major strengths that methods provide: the ability to accept arguments and to return a value. The ability to accept arguments allows methods to become reusable. If you had to rely on using global variables for work within methods, they would be useful only for the purpose of working with the same data each time they were called. Using the logic of passing arguments allows methods to be coded in a generic manner, so that they can work on the data that has been passed into them instead.

Consider the multiplyNumbers() method demonstrated in the Solution to this recipe. If it were not able to accept parameters then it would only be able to calculate variables that were globally defined within its containing class, such as demonstrated in Recipe 1-10. However, by affording this method the opportunity to accept arguments, it has become a method that can be reused anytime and in any location in order to perform the task of multiplying two values.

The ability to return a value allows for reusability as well. Often methods will need to return a value to the caller so the value can be used by the application in some way. If methods were not allowed to return values, they would be made much less reusable because they’d have to rely on storing any results in the global declaration of some variable within the containing class. The type of any value being returned must match the return type in the method’s signature. The following piece of code demonstrates the ability to assign a value of a variable based upon the result that is returned from a method:

int multValue = multiplyNumbers(5,4);

Any nontrivial Java application will contain methods that can be reused. They are an important part of the language, and they help to promote object-oriented capability in an application codebase.

1-12. Organizing Code with Packages

Problem

Your application consists of a set of Java classes, interfaces, and other types. You want to organize these source files to make them easier to maintain and avoid potential class-naming conflicts.

Solution

Create Java packages and place source files within them much like a filing system. Java packages can be used to organize logical groups of source files within an application. Packages can help to organize code, reduce naming conflicts among different classes and other Java type files, and provide access control. To create a package, simply create a directory within the root of your application source folder and name it. Packages are usually nested within each other and conform to a standard naming convention. For the purposes of this recipe, assume that my organization is named Juneau and that my organization makes widgets. To organize all the code for the widget application, create a group of nested packages conforming to the following directory structure:

/org/juneau

Any source files that are placed within a package must contain the package statement as the first line in the source. The package statement lists the name of the package in which the source file is contained. For instance, suppose that the main class for the widget application is named JuneauWidgets.java. To place this class into a package named org.juneau, physically move the source file into a directory named juneau, which resides within the org directory, which in turn resides within the root of the source folder for the application. The directory structure should look like the following:

/org/juneau/JuneauWidgets.java

The source for JuneauWidgets.java is as follows:

package org.juneau;

/**
 * The main class for the Juneau Widgets application.
 * @author juneau
 */
public class JuneauWidgets {
    public static void main(String[] args){
        System.out println("Welcome to my app!");
    }
}

Note that the first line in the source contains the package statement, which lists the name of the package that the source file is located within. The entire package path is listed in the statement, and each package name is separated by a dot.

images Note A package statement must be the first statement listed within the Java source. However, there may be a comment or Javadoc listed before the package statement.

An application can consist of any number of packages. If the widget application contains a few classes that represent widget objects, they could be placed within the org.juneau.widget package. The application may have interfaces that can be used to interact with the widget objects. In this case, a package named org.juneau.interfaces may also exist to contain any such interfaces.

How It Works

Java packages are useful for organizing source files, controlling access to different classes, and ensuring that there are no naming conflicts.

images Note When a class resides within a Java package, it is no longer referenced by only the class name, but instead the package name is prepended to the class name, which is known as the fully qualified name. For instance, because the class that resides within the file JuneauWidgets.java is contained within the org.juneau package, the class is referenced using org.juneau.JuneauWidgets, not simply JuneauWidgets. An identically named class can reside within a different package (for instance, org.java7recipes.JuneauWidgets).

Packages are represented by a series of physical directories on a file system, and they can contain any number of Java source files. Each source file must contain a package statement before any other statements in the file. This package statement lists the name of the package in which the source file resides. In the solution to this recipe, the source included the following package statement:

package org.juneau;

This package statement indicates that the source file resides within a directory named juneau, and that directory resides within another directory named org. Package-naming conventions can vary by company or organization. However, it is important that Java keywords are in lowercase so they do not conflict with any Java class or other type file names. Many companies will use the reverse of their domain name for package naming. However, if a domain name includes hyphens, underscores should be used instead.

Packages are very useful for establishing levels of security as well as organization. By default, different classes that reside within the same package have access to each other. If a source file resides within a different package than another file that it needs to use, an import statement must be declared at the top of the source file (underneath the package statement) to import that other file for use; otherwise, the fully qualified package.class name must be used within the code. Classes may be imported separately, as demonstrated in the following import statement:

import org.juneau.JuneauWidgets;

However, it is often likely that all classes and type files that reside within a package need to be used. A single import statement utilizing a wildcard character (*) can import all files within a named package as follows:

import org.juneau.*;

Although it is possible to import all files, it is not recommended unless absolutely necessary. As a matter of fact, it is considered a poor programming practice to include many import statements that use the wildcard. Instead, classes and type files should be imported individually.

Type file organization by package can prove to be very helpful. Suppose that the widget application that was described in the Solution to this Recipe includes different Java classes for each different widget object. Each of the widget classes could be grouped into a single package named org.juneau.widgets. Similarly, each of the widgets could extend some Java type or interface. All such interfaces could be organized into a package named org.juneau.interfaces.

Any substantial Java application will include packages. Any Java library or API that you use includes packages. When you import classes or types from those libraries, you are listing packages that are contained in the library.

1-13. Accepting Keyboard Input from the Command Line

Problem

You are interested in writing a command line or terminal application that will accept user input from the keyboard.

Solution

Make use of the java.io.BufferedReader and java.io.InputStreamReader classes to read keyboard entry and store it into local variables. In the following example, the user is prompted to enter a username when they run the program. With the help of the aforementioned classes, when users type their usernames into the keyboard, they are saved into a local variable and then printed out:

package org.java7recipes.chapter1.recipe1_13;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

/**
 *  Read keyboard entry and print it back out.
 * @author juneau
 */
public class GreetingMessage {
    public static void main(String[] args){
        BufferedReader readIn = new BufferedReader(new InputStreamReader(System.in));
        String username = "";
        System.out.println("Please enter your username: ");
        try{
            username = readIn.readLine();
            System.out.println("Your username is " + username);
        } catch (IOException ex){
            System.out.println(ex);
        }

    }

}

After the user is finished typing the username into the command line or terminal, it is read into the program and saved into a BufferedReader type variable. Later, that variable is parsed and printed. The output should reflect the entry that was made.

How It Works

Quite often, our applications need to accept user input of some kind. Granted, most applications are not used from the command line or terminal nowadays, but having the ability to create an application that reads input from the command line or terminal helps to lay a good foundation. It can also be useful for developing administrative applications that you or a system administrator may use. The two helper classes that were used in the solution to this recipe are java.io.BufferedReader, and java.io.InputStreamReader. As you can see from the example, System.in is passed into a new instance of the InputStreamReader, which is then passed into a new instance of the BufferedReader. This stacking of statements is very common in Java development.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.213.27