Creating and Using Classes - Java eLearning Kit For Dummies (2014)

Java eLearning Kit For Dummies (2014)

Chapter 9. Creating and Using Classes

· Develop an understanding of class structure that helps you create better classes.

· Understand how variable scope affects how and when you use variables in your application.

· Begin writing classes that demonstrate the full capabilities of class construction.

· Design a test application that fully demonstrates how to use a complete class definition.

· Use anonymous classes to perform ad hoc tasks that don’t require the use of formal classes.

· Use lambda expressions to perform tasks using significantly less code than more traditional techniques.

lingo_fmt.tif

1. How does class inheritance affect the way I write my classes?

Inheriting from another class can greatly reduce the amount of work you need to do, as described on page 253

2. When I create new classes and use them in my application, is it possible to access methods, properties, and other features of the superclass?

Java makes it possible for your class to see the features of the superclass, as described on page 254

3. What precisely is a default scope?

The default scope is the visibility of a class feature within a given circumstance without using any special modifiers, as summarized on page 257

4. Why would I ever want to modify the default scope?

Modifying the default scope makes it possible to hide features from prying eyes and makes it possible to create classes that are less likely to fail due to security and reliability concerns, as shown on page 266

5. When would I need to create more than one constructor — the element that allows for use of special variables or performs other setups — for my class?

Using multiple constructors makes it possible to create versions of a class with extended functionality or reduced coding requirements, as defined on page 267

6. Is it possible to get the functionality of a class without going through the trouble of creating one?

Anonymous classes make it possible to create ad hoc classes that you use for a single purpose without defining the class formally, as shown on page 277

7. How can I create a concise anonymous class that has just one method?

Lambda expressions provide the means to define a special kind of anonymous class that has only one functional interface and one method, as described on page 279

You probably realize by now that you’ve been creating classes in every chapter of this book. It’s impossible to create a Java application without creating a class. In fact, you created an example in the “Required error handling” section of Chapter 8, where you accessed the features of a simple class from another Java class. However, the ways in which you’ve used classes so far have been relatively simplistic — Java is capable of considerably more complexity, which is the point of this chapter.

Classes have a specific structure. Just as the blueprints used to create buildings have certain features and follow predefined formats, so do the classes you create. Otherwise, the JRE could never interpret your design and use the class to construct objects within an application.

As part of designing a class, you must also understand how to show and hide data and code elements in your class, which means that this chapter must provide some additional information about scope. Using scope correctly makes your class more secure because you can hide data from prying eyes. A properly scoped variable also makes the class more reliable by making it less likely that someone will be able to fill the variable with incorrect data. Another good reason to employ scope is to make your class easier to use by hiding details that other developers don’t need to see in order to use the class.

Java has had anonymous inner classes (usually shortened to anonymous classes) to create ad hoc classes where a formal class description is unnecessary or overkill. For example, you might use an anonymous class to change the standard behavior of a formal class in just one instance. Using an anonymous class makes your code cleaner, shorter, and easier to understand. It also helps optimize the code in many cases so it conceivably runs faster. Java 8 also includes a new feature called lambda expressions that make the code even shorter. A lambda expression is a special kind of anonymous class that contains just one functional interface and one method, so you can describe what to do with a bare minimum of code. The result is that anyone viewing your code will be able to focus on what the code does rather than the structure around the code.

Understanding the Structure of Classes

A building contractor can understand a blueprint designed by an architect because both of them use the same set of rules and conventions. When you create a class, you’re the architect. The blueprint you create must communicate your ideas to the computer, which plays the role of the builder. For this communication to work, you must both use the same rules and conventions. The following sections describe the rules and conventions for creating classes in Java by dividing the task into functional areas, such as writing a method.


LINGO

A convention is an agreement or a contract between you and the JRE. In fact, when you read other documentation, it may actually use the term contract to express the idea of a convention. No matter what term you use, the convention expresses the responsibilities of each party in defining the class and building it as an object. In some respects, you can also view a convention as a custom — the set of practices that Java developers have created for developing classes. There isn’t a right or wrong about the conventions that Java uses; this set of practices is simply what Java developers have created over time as the most efficient way of defining a class.


Calling methods

You’ve worked with a number of method types in the book. However, you really haven’t seen how methods are put together until now. A method describes an action that the object can perform. Even though most of the class examples to this point have had just one method, a class can have any number of methods that it requires.

In looking at methods, note that every method can have the following parts:

· Modifiers (optional): The modifiers change the way the class behaves. For example, if you make a class private, the method is visible only to other methods within the class. When you create an object from the class, the object’s user can’t access the private method.


EXTRA INFO

You can’t call a non-static method from a static method. The nonstatic method is associated with an object — an instance of the class — while the static method is associated with the class itself. To access the non-static method, you must create an object. You can, however, access a static method from a non-static method. The static method always exists, even before the object is created. Therefore, the static method is always accessible.


remember.eps A method can have more than one modifier attached to it. For example, you can use public and static together to make the method visible outside of the class as part of the class itself, rather than as part of an object created from the class. The main() method found in most of the examples so far in the book is both public and static.

· Return type (required): Every method has a return type. The return type defines the information that the method returns to the caller after it has completed its work. When you don’t have anything to return to the caller, you set the return type as void. For example, the main() method has a return type of void because it doesn’t return anything to the caller.

remember.eps A method can have only one return type, even if that return type is a complex type that can contain multiple values.


EXTRA INFO

Using camelcase is the standard convention for creating methods and variable names, but the Java compiler doesn’t enforce this convention. Camelcase is where you begin each word in a method or variable name with a capital letter, except for the first word. The first word is always lowercase. For example, if you create a method named checkForDoubles(), the convention is to start the first word, check, as lowercase, but to show For and Doubles with initial capitalization. Some developers, including myself, prefer pascalcase, where every word of a method or variable name is capitalized. In this case, CheckForDoubles() would have every word capitalized. Using pascalcase for the methods and variables you create helps differentiate them from methods and variables that are part of the Java Application Programming Interface (API). No matter which casing you use, you must apply it consistently. Remember that Java treats checkForDoubles() as a different method from CheckForDoubles().


· Method name (required): Every method must have a name. Otherwise, you couldn’t call the method. Here are some additional considerations for the method name:

· The method name must begin with a letter — any letter will do.

· You can’t begin a method name with a number or special character.

· Numbers can appear anywhere else in the method name.

· The only special character you can use is the underline (_). For example, a method name can’t include an ampersand (&).

· Argument list (optional): If the method requires information from the caller to perform a task, you can supply one or more arguments (or parameters as some people call them) in a list contained within parentheses. Here are some additional considerations for arguments:

· The argument includes the argument type followed by the argument name. For example, if you want to supply an int value called MyInt, type int MyInt.

· Argument names and types follow the same constraints as any other variable.

· You must separate multiple arguments with commas. For example, if the MyMethod() method requires an int called MyInt and a float called MyFloat, the argument list would be MyMethod(int MyInt, float MyFloat).

· If there are no arguments, the method name must be followed by a pair of empty parentheses.

· Exception list (optional): The exception list defines which exceptions a method is likely to encounter and throw. The exception list begins with the keyword throws, followed by a list of exception classes. You’ve already seen an example of how this feature works in the “Required error handling” section in Chapter 8.

· Method body (required): A method isn’t much use without code that tells what tasks to perform. The method body always appears within curly braces ({}).

Using the preceding rules, the shortest method declaration you can create is one that uses the default scope, is accessible as part of an object, accepts no parameters, returns no values, and contains no code. Even though the following method is completely useless, it will compile, and you can call it in your code:

void MyMethod()
{
}

The sections that follow demonstrate more practical methods than MyMethod(), but it’s important to know the absolute minimum amount of code needed to create a method. The main reason to use methods is to group lines of code together in such a manner that they perform a single defined task. In addition, you should make a method small enough so that the code it contains is easily understood by you and everyone who follows you.

Allocating properties

One of the issues that tends to confuse many new Java developers (and some experienced Java developers as well), is the concept of properties in Java. Some languages have a formal mechanism for working with properties, but Java doesn’t provide this mechanism. In addition, there’s some level of confusion about the terminology that Java uses for specific program elements that are related to properties. This section uses a specific set of terms that reflect the terminology used by the majority of Java developers, but you should expect to see other usages as you look around online.

A property is a value that you can access as part of the class or the object created from the class. You use properties to provide access to a global variable, which is also called a field. The “Long versus long” section in Chapter 3 contains the first example of a global variable in the book. The best practice is to always make fields private and then rely on special getter and setter methods to access them. The combination of field, getter, and setter is a property in Java. Here’s a typical example that uses an int named MyInt.

// Create the MyInt field.
private int MyInt = 0;

// Obtain the current value of MyInt.
public int getMyInt()
{
return MyInt;
}

// Set a new value for MyInt.
public void setMyInt(int MyInt)
{
this.MyInt = MyInt;
}

remember.eps In this example, the code declares a private variable, MyInt, and assigns it a value of 0. The getter, getMyInt(), provides the current value of MyInt to the caller, while the setter, setMyInt(), lets the caller change the value of MyInt. The reason you want to use properties is so that you have better control over how a caller interacts with MyInt. By using setters and getters, you make it possible to do tasks such as verify the range of values that a caller provides and then throw an exception when the input is incorrect in some way.


LINGO

A field is a kind of global variable that holds data that the class or object manages. Some developers extend the term field to include all sorts of other meanings, but this book uses field to specifically mean a globally accessible variable.



LINGO

Getters and setters are special methods that provide access to fields. Using getters and setters helps you control field access and reduces the chance that the field will be used incorrectly.


warning.eps To protect a field from damage, such as receiving incorrect data values, you must declare it as private and rely on getters and setters to access it. The getters and setters must provide any checks required to ensure the caller interacts with the private field correctly.

Considering inheritance

Just as you inherited specific features from your parents, every class you create inherits certain features from a parent or superclass. When you don’t define a specific inheritance for a class, it uses the Object class as its superclass.

Inheritance is important because it helps define the characteristics of any class you create, and using the right class as a parent can save considerable time when you’re creating a new class. In addition, you can access features of the parent class by using the super keyword. The best way to see how inheritance works is to play with it in an example.


LINGO

A superclass is the parent class of the current class. Every class you create has a superclass (parent class). The default superclass is Object, but you can inherit from many other classes in the Java API to produce some amazing results.


In the following example, you create a class that tells you about its class name and the name of its superclass. The purpose of this example is to help you understand how inheritance works by using a simple set of classes.

Files needed: ParentClass.java, SimpleClass.java, and UseSimpleClass.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

// Import the required API classes.
import java.lang.String;

public class ParentClass
{
// Create a method that returns a special string.
public String GetClassName()
{
return "This is the ParentClass";
}
}

The example begins with the parent class, the one that the SimpleClass that you’ll define next inherits from. Notice that ParentClass has just one method, GetClassName(), that returns a String to the caller. As with most of the classes in the book so far, ParentClass inherits fromObject, which is the default inherited class.

3. Using the standard commands of your editor or IDE, save this file as ParentClass.java.

4. In your command prompt, type javac ParentClass.java and press Enter.

The compiler compiles your application and creates a .class file from it.

5. Create a new class named SimpleClass by using the editor or IDE that you’ve chosen to use for this book.

This new class must appear in the same folder as the ParentClass class that you created in Step 2.

6. Type the following code into the editor screen.

// Import the required API classes.
import java.lang.String;

public class SimpleClass extends ParentClass
{
// Override the same method in the parent class and
// output a special string.
public String GetClassName()
{
return "This is the SimpleClass";
}

// Provide the means for getting the string from
// the parent class.
public String GetSuperClass()
{
return super.GetClassName();
}
}

This class inherits all the functionality of ParentClass. Notice the use of the extends keyword in this class declaration. A Java class can inherit from only one parent.

The next thing you should notice is that this class also has a GetClassName() method that returns a String to the caller. The String is different, but otherwise, the method is completely the same. This technique is called overriding the method. You override a method when you want to provide a different behavior for the method in the child class.

remember.eps Now that SimpleClass has an implementation of GetClassName(), you may think it’s impossible to access this method in ParentClass. Fortunately, Java has a way to get around this problem. Look at GetSuperClass() and you see the super keyword used as a means of accessing GetClassName() in ParentClass from SimpleClass.

7. Using the standard commands of your editor or IDE, save this file as SimpleClass.java.

8. In your command prompt, type javac SimpleClass.java and press Enter.

The compiler compiles your application and creates a .class file from it.

9. Create a new class named UseSimpleClass using the editor or IDE that you’ve chosen to use for this book.

This new class must appear in the same folder as the SimpleClass class that you created in Step 6.

10. Type the following code into the editor screen.

// Import the required API classes.
import java.lang.String;

public class UseSimpleClass
{
public static void main(String[] args)
{
// Create an instance of the simple class.
SimpleClass Test = new SimpleClass();

// Display the SimpleClass string.
System.out.println(Test.GetClassName());

// Display the string from the parent class.
System.out.println(Test.GetSuperClass());
}
}

This example simply creates an instance of the SimpleClass class named Test. It then uses Test to access the GetClassName() and GetSuperClass() methods to display the class names from SimpleClass and ParentClass.

remember.eps By following this example carefully, you see how inheritance works at a simple level in Java. The remainder of the book will provide additional examples of inheritance because it’s an important and somewhat complex topic (too complex to discuss in just one example).

11. Save the file, then type javac UseSimpleClass.java in your command prompt and press Enter.

The compiler compiles your application and creates a .class file from it.

12. Type java UseSimpleClass and press Enter.

You see the output shown in Figure 9-1. The application is able to display both the SimpleClass and ParentClass strings by relying on the inheritance features that Java provides.

9781118098783-fg0901.tif

Figure 9-1:

Defining Variable Scope

As your applications become more complex, the need to consider scope becomes ever more important. The main reason is that you can inadvertently introduce a bug into your application by not observing scoping rules. This can result from a field or other member being used incorrectly by the application (such as adding an incorrect data value or accessing a method at the wrong time or with incorrect data). In addition, incorrect scoping can leave the door open for outsiders to interact with your application in unforeseen ways (such as a virus). The following sections assume that you’ve already read the scoping information in the “Long versus long” section in Chapter 3.

Considering default scope

The default scope occurs when you don’t specifically assign a scope to a class element. Because many Java developers have no idea what the default scope is for some elements (and using a default scope means that your code isn’t documented), it isn’t used very often. Even so, you need to know what the default scope is for various elements because some Java developers do rely on it. However, before you can understand the default scope, you need to consider visibility — the measure of which application elements can see a member. Java provides the following levels of visibility (in general order of encapsulation):

· Package: The container used to hold a number of classes. When working with a simple directory structure, as the examples in this book do, the package is a directory that holds a number of .class files.

· Class: A class usually resides in a single .java file that you compile into a .class file. It contains a single class declaration.

· Method: An element can reside in the class or as part of a method. The method acts as a container to hold the element.

· Block: An element can reside within a code block, such as a for loop.

Scope partially depends on the location used to declare an element. For example, a variable that’s defined within a block (such as a for loop) is visible only within that block. When you try to use the variable outside of the block, Java displays an exception. Taking visibility into account, Table 9-1 describes the various levels of scope within the Java environment.

0901

Table 9-1 shows how the default scope fits into the scheme of things. For example, if you declare a method by using the default scope, any method can use it as long as it resides in the same package. In addition, if you create a class that inherits from the class containing the method, the subclass can use the method as long as it resides in the same package. However, if the subclass exists outside the current package, it can’t use the method. In short, the default scope is a little more restrictive than the protected scope but less restrictive than the private scope.

In the following example, you create a parent class that has methods that have a private, default, protected, and public scope. In the same folder, you create a child class that attempts to access these methods. In a different folder, you create another child class that attempts to access these methods as well (so you can see the difference between default and private scoping). Finally, you add an application to test everything.

Files needed: ScopeParent.java, ScopeChild1.java, ScopeChild2.java, and TestScope.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Create a subdirectory in your project folder named inside.

3. Create a .java file in the inside subdirectory named 
ScopeParent.java.

4. Type the following code into the editor screen.

// Define the package for this class.
package inside;

public class ScopeParent
{
// Create a private method.
private void PrivateMethod()
{
System.out.println("The parent's private method.");
}

// Create a default method.
void DefaultMethod()
{
System.out.println("The parent's default method.");
}

// Create a protected method.
protected void ProtectedMethod()
{
System.out.println("The parent's protected method.");
}

// Create a public method.
public void PublicMethod()
{
System.out.println("The parent's public method.");
}
}

This is the first time you’ve seen the package keyword used. In this case, the package keyword tells you that this file exists in the inside subdirectory. As you begin writing more complex Java, you’ll find that you use the package keyword for nearly every class you create to ensure the class resides in a specific package.

The ScopeParent class is defined as public, but you could also define it as a default scope class. Inside this class, you find various methods, each of which relies on a different scope.


LINGO

A package defines a container used to hold multiple .class files in a single location for easier access. The contents of a package are normally related to each other, such as the classes used to manage all the math classes. The simplest form of package is a subdirectory in a directory structure, but Java applications often rely on Java archive (.jar) files to hold the package.


remember.eps Notice that the default scope method, DefaultMethod(), is the only one that doesn’t include a scope keyword. Leaving out the scope keyword always defines an element that uses the default scope.

5. Save this file as ScopeParent.java in the inside directory.

6. In your command prompt, type javac inside/ScopeParent.java and press Enter.

The compiler compiles your application and creates a .class file from it.

7. Create a .java file in the inside subdirectory named ScopeChild1.java by using the editor or IDE that you’ve chosen to use for this book.

8. Type the following code into the editor screen.

// Define the package for this class.
package inside;

public class ScopeChild1 extends ScopeParent
{
// Access the private method.
public void UsePrivate1()
{
super.PrivateMethod();
}

// Access the default method.
public void UseDefault1()
{
super.DefaultMethod();
}

// Access the protected method.
public void UseProtected1()
{
super.ProtectedMethod();
}

// Access the public method.
public void UsePublic1()
{
super.PublicMethod();
}
}

As with the ScopeParent.java file, this class defines itself as belonging to the inside package. The class tries to use each of the methods in the parent class by accessing them with the super keyword.

9. Using the standard commands of your editor or IDE, save this file as ScopeChild1.java in the inside directory.

10. In your command prompt, type javac inside/ScopeChild1.java and press Enter.

At this point, you see an error message telling you that you can’t access the private member, PrivateMethod(), of the ScopeParent class, as shown in Figure 9-2. Java never allows you to access the private members of a superclass from the subclass.

9781118098783-fg0902.tif

Figure 9-2:

11. Edit the ScopeChild1 class to remove the UsePrivate1() method (delete all of the code shown below).

// Access the private method.
public void UsePrivate1()
{
super.PrivateMethod();
}

12. Save the file, then type javac inside/ScopeChild1.java in your command prompt and press Enter.

The compiler compiles your application and creates a .class file from it.

13. Create a subdirectory in your project folder named outside.

14. Create a .java file in the outside subdirectory named ScopeChild2.java by using the editor or IDE that you’ve chosen to use for this book.

15. Type the following code into the editor screen.

// Define the package for this class.
package outside;

//Import the required application classes.
import inside.ScopeParent;

public class ScopeChild2 extends ScopeParent
{
// Access the default method.
public void UseDefault2()
{
super.DefaultMethod();
}

// Access the protected method.
public void UseProtected2()
{
super.ProtectedMethod();
}

// Access the public method.
public void UsePublic2()
{
super.PublicMethod();
}
}

ScopeChild1 and ScopeChild2 have some interesting differences. First, notice that the package declaration defines this particular package as outside, not inside. Second, because this is part of the outside package, you must import ScopeParent before you can use it. ScopeChild2 can’t see ScopeParent until you import it because the two .class files aren’t in the same directory.

The example is essentially the same as ScopeChild1 except that it doesn’t attempt to access the PrivateMethod() of the ScopeParent class. You already know that it isn’t possible to access this method because it isn’t accessible in ScopeChild1.

16. Using the standard commands of your editor or IDE, save this file as ScopeChild2.java.

17. In your command prompt, type javac outside/ScopeChild2.java and press Enter.

You see an error message telling you that you can’t access DefaultMethod() from ScopeChild2, as shown in Figure 9-3. Now you’re seeing the true meaning of the scoping rules in Table 9-1. Even though ScopeClass1 can access DefaultMethod() without problem, this same method is inaccessible outside of the package.

9781118098783-fg0903.tif

Figure 9-3:

18. Edit the ScopeChild2 class to remove the UseDefault2() method (delete all of the code shown below).

// Access the default method.
public void UseDefault2()
{
super.DefaultMethod();
}

19. Save the file and then type javac outside/ScopeChild2.java in your command prompt and press Enter.

The compiler compiles your application and creates a .class file from it.

20. Create a new class named TestScope by using the editor or IDE that you’ve chosen to use for this book.

This new class must appear in the main folder of your application, not in either the inside or outside subdirectories.

21. Type the following code into the editor screen.

// Import the required application classes.
import inside.*;
import outside.ScopeChild2;

public class TestScope
{
public static void main(String[] args)
{
// Create the required objects.
ScopeChild1 Child1 = new ScopeChild1();
ScopeChild2 Child2 = new ScopeChild2();

// Use each of the accessible methods in Child1.
Child1.UseDefault1();
Child1.UseProtected1();
Child1.UsePublic1();

// Use each of the accessible methods in Child2.
Child2.UseProtected2();
Child2.UsePublic2();
}
}

All the classes that this example uses reside in other directories as part of other packages. The application imports all the classes in the inside package by using the asterisk (*) wildcard character. The application specifically imports outside.ScopeChild2.

The example instantiates objects from both ScopeChild1 (Child1) and ScopeChild2 (Child2). The application then calls each of the accessible methods in these two objects.

22. Save the file, then type javac TestScope.java in your command prompt and press Enter.

The compiler compiles your application and creates a .class file from it.

23. Type java TestScope and press Enter.

Figure 9-4 shows the output. As you can see, the scoping rules work as expected to hide some items and make other items accessible. The same principles hold true when you’re working with fields, getters, setters, and other class elements.

9781118098783-fg0904.tif

Figure 9-4:

practice_fmt.eps Set the ScopeParent class to use the default scope by removing the public keyword at the beginning of the class declaration. What happens to the application now that the entire ScopeParent class scope has changed? Feel free to continue experimenting with the three classes in this example to see what happens when you change the scoping rules for each of the classes.

Observing scope within a block

Developers often experience problems figuring out why an application is misbehaving when encountering a block access problem. The basic guideline is that any variable you create within a block is defined only within that block. For example, when you look at the following code, you see a typical block access scenario.

// Create a variable inside a block.
for (int i = 0; i < 10; i++)

// Display the value of that variable.
System.out.println("The value of i is: " + i);

// Access outside the block doesn't work.
System.out.println("The value of i is: " + i);

The example displays the value of i within the for loop (a type of block) without problem. However, trying to access i outside the block isn’t acceptable because the variable isn’t defined. The compiler will catch this error.

Another potential problem occurs when a variable is defined in the application and also within a block. Because this situation is likely to create problems, newer versions of Java won’t allow the sort of code shown here:

public static void main(String[] args)
{
// Define a variable.
int i = 0;

// Create a variable inside a block.
for (int i = 0; i < 10; i++)

// Display the value of that variable.
System.out.println("The value of i is: " + i);

// Access outside the block doesn't work.
System.out.println("The value of i is: " + i);
}

The compiler won’t always prevent you from shooting yourself in the foot. In many situations, the developer does something with the variable and doesn’t understand the consequences. For example, the following code is perfectly legal in Java:

public static void main(String[] args)
{
// Define a variable.
int i = 0;

// Create a variable inside a block.
for (i = 0; i < 10; i++)

// Display the value of that variable.
System.out.println("The value of i is: " + i);

// Access outside the block doesn't work.
System.out.println("The value of i is: " + i);
}

The for loop displays the values 0 through 9 because of the condition within the for loop declaration. The final call to System.out.println() displays a value of 10, not 0 or 9 as some developers might expect. The i++ part of the declaration occurs, and then the condition is evaluated, so the final value of i is 10, not 9 because it has to be 10 in order for the condition to become false. The point of this section is that you must consider how a block works with a variable in order to determine whether you can access the variable and what the value will contain on exit from the block.

Defining a Class with Event Support

You’ve seen a number of classes and class components in the chapter. For example, you’ve already seen how to create methods and properties. The previous sections have also demonstrated the importance of scope to your classes. However, so far you haven’t seen any information about working with events and you really haven’t seen a class of any complexity. The following sections introduce you to a class that uses events and because it uses events, requires a little more complex construction method.

Defining an event


LINGO

An event is an occurrence of a predefined action within a class, such as a button click, that the class must tell outsiders about.


An event is anything that happens within the class that the class must convey to the outside world. For example, when a user clicks a button, the button must tell the outside world that it has been clicked. Knowing that the button has been clicked allows other code to react to that event. The method that performs this task is known as an event handler.

In the following example, you create a class that defines an event. The event isn’t useful by itself — it simply describes an action that can occur within a class. The action need not even be specific — you can create a generic event, as is the case in this example that can define any action.


LINGO

An event handler is a special method that performs tasks based on the occurrence of an event.


Files needed: MyEvent.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

// Import the required API classes.
import java.util.EventObject;

// An event object contains the information required
// to describe the event.
public class MyEvent extends EventObject
{
// The event object must include this special
// constructor that accepts an object with
// the event information in it.
public MyEvent(Object EventArgs)
{
// Your code doesn't actually have to do
// anything with the event; the superclass does.
super(EventArgs);
}
}

Any event definition you create must inherit from EventObject or similar event-based class. Consequently, this class begins by importing java.util.EventObject and then inheriting from it.


LINGO

A constructor is a special method that doesn’t have a return value. It describes how to create an object from the class. Constructors always have the same name as the class.


remember.eps A constructor is a special method that defines how a class should create an object. The default constructor doesn’t do anything other than create the object, and it takes no input arguments. A generic constructor does more than simply create the object (for example, it can initialize variables), but it doesn’t require any input argument either. An event can’t rely on either a default or a generic constructor. This is one case where you must create a special constructor that accepts some sort of input. The example shows the simplest possible implementation — it accepts an Object, EventArgs. Notice that the constructor is the only method that doesn’t require that you provide a return value and it also has precisely the same name as the class.

If you plan for your event to perform some special processing, you’d include it in the constructor or as part of other methods within the class. However, your class need not implement any special behavior to work. The example simply calls the parent class’ constructor with EventArgsto accomplish the work it needs to do.

warning.eps Unless you want to perform a lot of extra coding, your event class must call the parent class’ constructor (as shown in this example) at some point. Otherwise, you need to implement all of the event behaviors in your code (a potentially messy and error-prone process).

3. Using the standard commands of your editor or IDE, save this file as MyEvent.java.

4. In your command prompt, type javac MyEvent.java and press Enter.

The compiler compiles your application and creates a .class file from it.

Creating an event listener interface

When a class generates an event, there must be something to listen and react to the event. Otherwise, when the event is fired, nothing will happen. An event listener waits for an event to happen and then passes this information out to other classes by calling methods that have registered themselves with the event listener.


LINGO

An event listener waits for events to happen. When it detects an event, it tells any class that has registered itself with the event listener about the event. In short, an event listener is a manager that makes it possible to react to events within a class.


Unfortunately, you don’t know precisely how everything is going to work until someone actually creates a class definition that uses the event. Your event requires a listener, but you don’t know how to put it together. In short, you realize that there has to be an interface between the event and an event listener, but you don’t know how to implement that interface. A special sort of class, called an interface, lets you tell Java that something is needed, but you don’t know precisely what.

In the following example, you create an interface that describes the interaction required between a class that defines an event and one that uses the event. The interface doesn’t provide an implementation; it merely describes what must happen.


LINGO

An interface is a class that describes a relationship between a class and the outside world, without providing an implementation (functional code) of that relationship. Without any functional code, an interface can only tell how the relationship should look, not how it actually works.


Files needed: MyEventListener.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

// Import the required API classes.
import java.util.EventListener;

// An event listener listens for an event to occur.
public interface MyEventListener extends EventListener
{
// When the event happens, the event listener tells
// everyone about it.
public void EventHappened(MyEvent Event);
}

Describing what an event listener interface does takes considerably longer than writing the event listener interface code. In this case, MyEventListener inherits from EventListener. It defines a single method, EventHappened(), that specifies a single method used to tell classes that an event has happened.

3. Using the standard commands of your editor or IDE, save this file as MyEventListener.java.

4. In your command prompt, type javac MyEventListener.java and press Enter.

The compiler compiles your application and creates a .class file from it.

Implementing the event as part of a class definition

At this point, you have an event and an event listener description. So, you have the resources for telling everyone that an event has occurred, but you have no mechanism to deliver or manage the event. An event class uses the event and the event interface, along with some management code, to make it possible to fire events (make them happen) and to manage a list of event handlers (classes that want to hear about the event and are listening for it).

In the following example, you create an interface that describes the interaction required between a class that defines an event and one that uses the event. The interface doesn’t provide an implementation; it merely describes what must happen.

Files needed: SampleEventClass.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

// Import the required API classes.
import javax.swing.event.EventListenerList;

// An event class manages the event. It provides the
// means for adding and removing listeners and also
// firing the event when it happens.
public class SampleEventClass
{
// Create a variable to hold a list of listeners,
// which are applications that want to know 

// about the event.
protected EventListenerList ListenerList =
new EventListenerList();

// Add an event listener to the list.
public void AddEventListener(MyEventListener Listener)
{
ListenerList.add(MyEventListener.class, Listener);
}

// Remove an event listener from the list.
public void RemoveEventListener(MyEventListener Listener)
{
ListenerList.remove(MyEventListener.class, Listener);
}

// Fire the event, tell everyone that something has
// happened.
public void FireEvent(MyEvent Event)
{
// The event manager must tell each of the
// listeners in turn, so you need a list of 

// listeners.
Object[] Listeners = ListenerList.getListenerList();

// Process each of the event listeners in turn.
for (int i = 0; i < Listeners.length; i+=2)
{
// An event list could contain any number of
// events,so you need to ensure you
// process only the listeners that want to 

// hear about this particular event.
if (Listeners[i] == MyEventListener.class)
{
// Fire the EventHappened method using the
// event argument supplied by the caller.
((MyEventListener)Listeners[i+1]).EventHappened(Event);
}
}
}
}

More than one method can listen for events generated by your event class. As a result, you need some means of managing a list of these classes. You have a lot of options for performing this task at your disposal, but using javax.swing.event.EventListenerList is the easiest method available.

The example begins by creating an EventListenerList, ListenerList. It then provides methods for adding methods to (AddEventListener()) and removing methods from (RemoveEventListener()) the list. These methods rely on functionality provided as part of the EventListenerListclass — you don’t implement the functionality yourself.

The FireEvent() method is the centerpiece of this class. When this method is called, the caller is saying that an event has happened and that the object created from this call should tell everyone about it. The method takes one input, a MyEvent object, Event. This input argument says that a specific kind of event has happened.

To tell everyone who’s said they want to know about the event, the FireEvent() method begins by obtaining the list of methods that appear in ListenerList. An odd aspect of ListenerList is that the entries appear in every other element. You don’t need to worry about why this is the case — you simply have to know that it is. Consequently, the code creates a for loop that looks at every other element.

The list you create could contain any number of event listeners, each of which is waiting for a different event. The example ensures that the class of the event listener entry is precisely the same as the MyEventListener.class, so that you know it’s the right kind of event listener. When this is the case, the code calls the EventHappened() method within that class to tell it that the event has happened.

3. Using the standard commands of your editor or IDE, save this file as SampleEventClass.java.

4. In your command prompt, type javac SampleEventClass.java and press Enter.

The compiler compiles your application and creates a .class file from it.

Demonstrating use of the event in a class

You now have a means of using an event within a class. The example class isn’t very complex. However, it does incorporate everything you’ve learned to date about creating classes, plus it adds the information you need to know in order to add events to a class. The following example shows a simple class that lets you create an event implementation and then interact with it in a meaningful way.

Files needed: DemoClass.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

public class DemoClass
{
// The event manager class isn't the same as an
// event manager. DoEvents is the object that
// actually manages the event for this class.
private SampleEventClass DoEvents = new SampleEventClass();

public DemoClass()
{
// You must add each object created from this class
// to the event listener list. Each object will
// receive a separate notification.
DoEvents.AddEventListener(new MyEventListener()
{
public void EventHappened(MyEvent Event)
{
if ((int)Event.getSource() >= 4)
System.out.println("Number is too high!");

if ((int)Event.getSource() <= 0)
System.out.println("Number is too low!");
}
});
}

// Create a field to manipulate for this class. The
// field could represent any data.
private int Value = 0;

// Obtain the current value of the field.
public int getValue()
{
return Value;
}

// Set the value of the field directly.
public void setValue(int Value)
{
// Create an event object that contains
// the value that the caller attempted to
// use.
MyEvent Event = new MyEvent(Value);

// When the caller tries to set the value too
// high or too low, the class must fire the
// event. Otherwise, it can change the contents
// of Value.
if ((Value <= 3) & (Value > 0))
this.Value = Value;
else
DoEvents.FireEvent(Event);
}

public void AddOne()
{
// Create an event object containing the
// current contents of Value.
MyEvent Event = new MyEvent(Value);

// Make sure that Value isn't getting too
// high. If so, fire an event.
if (Value <= 3)
Value++;
else
DoEvents.FireEvent(Event);
}

public void SubtractOne()
{
// Create an event object containing the
// current contents of Value.
MyEvent Event = new MyEvent(Value);

// Make sure that Value isn't getting too
// low. If so, fire an event.
if (Value > 0)
Value--;
else
DoEvents.FireEvent(Event);
}
}

The big thing is not to get overwhelmed by this class; take it one element at a time. The code begins by creating a SampleEventClass object, DoEvents, to manage the event that this class generates. You use DoEvents to interact with the events that this class generates in a meaningful way — a way that you’ll discover later on.

The constructor comes next. Notice that this is a generic constructor — one that doesn’t require any input arguments. However, it adds the instance of this class — the object created from DemoClass — to the event listener list by calling DoEvents.AddEventListener(). To make things easy for this example, the event handler appears directly as part of the method call. It’s a call to EventHappened(), which takes an argument of the MyEvent type, Event. When the information contained within the event (obtained by calling getSource()) is greater than or equal to 4, the application displays a message that the number is too high. Likewise, an event value less than or equal to 0 generates a message saying that the number is too low.

This is an actual class that does something other than work with events. The next step is to create an int named Value with an initial value of 0. The class manipulates the data in Value and generates events based on that content. The getValue() and setValue() methods are the getter and setter for Value. Notice that setValue() provides the special feature of checking the input value. When the input value is in the desired range, setValue() lets it pass. However, when the input value is outside of the desired range, rather than set the value, setValue() generates an event by calling DoEvents.FireEvent(). To make this call, setValue() must create a new MyEvent object, Event, that contains the incorrect value, Value. The event handler, EventHappened(), receives this information and displays the appropriate message.

The AddOne() method increments Value, while SubtractOne() decrements Value. Both of these methods also check Value for incorrect information and act accordingly.

3. Using the standard commands of your editor or IDE, save this file as DemoClass.java.

4. In your command prompt, type javac DemoClass.java and press Enter.

The compiler compiles your application and creates a .class file from it.

Using the Class with Events

At this point, you have a class to use. All you need to do is create an application to use it. In the following example, you create an application that exercises DemoClass.

Files needed: UseEvent.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen.

public class UseEvent
{
public static void main(String[] args)
{
// Create a copy of the demonstration class.
DemoClass TestClass = new DemoClass();

// Value will start at 0, so keep adding 1
// until Value should equal 5.
TestClass.AddOne();
System.out.println(TestClass.getValue());
TestClass.AddOne();
System.out.println(TestClass.getValue());
TestClass.AddOne();
System.out.println(TestClass.getValue());
TestClass.AddOne();
System.out.println(TestClass.getValue());
TestClass.AddOne();
System.out.println(TestClass.getValue());

// Now that Value is at 4 (we couldn't make it
// equal 5), keep subtracting 1 until Value
// should equal -1.
TestClass.SubtractOne();
System.out.println(TestClass.getValue());
TestClass.SubtractOne();
System.out.println(TestClass.getValue());
TestClass.SubtractOne();
System.out.println(TestClass.getValue());
TestClass.SubtractOne();
System.out.println(TestClass.getValue());
TestClass.SubtractOne();
System.out.println(TestClass.getValue());

// Try setting the value directly.
TestClass.setValue(3);
System.out.println(TestClass.getValue());
TestClass.setValue(5);
System.out.println(TestClass.getValue());
TestClass.setValue(-5);
System.out.println(TestClass.getValue());
}
}

The application begins by creating a DemoClass object, TestClass. It then exercises the resulting object by testing all of its methods, properties, and events. The application begins by incrementing the value in TestClass until it exceeds the recommended value. Now that TestClass is at its limit, the application decrements the value it contains until it’s too low. Finally, the application tries setting the value in TestClass directly. In short, TestClass demonstrates the implementation of a range check. You can’t take it beyond the anticipated boundaries.

3. Using the standard commands of your editor or IDE, save this file as UseEvent.java.

4. In your command prompt, type javac UseEvent.java and press Enter.

The compiler compiles your application and creates a .class file from it.

5. Type java UseEvent and press Enter.

You see the output shown in Figure 9-5. Notice that the event handler generates a message every time the application tries to exceed the predefined range. In addition, the value remains at the last known good value.

9781118098783-fg0905.tif

Figure 9-5:

Working with Anonymous Inner Classes

Sometimes you don’t really need to create a formal class definition in order to make your application work correctly. For example, it’s possible to add event-handling support to an application without going through all the work you saw earlier in this chapter. An anonymous class can make your code easier to understand and more elegant. The example that follows shows a basic use of an anonymous class when working with an interface.


LINGO

An anonymous inner class, also known simply as an anonymous class, provides a shortcut method for creating classes that have limited functionality when a formal class declaration is unneeded or unwanted. For example, if you normally use the functionality of another class without modification but need to modify that functionality for just one purpose, then an anonymous class can be really helpful.


Files needed: AnonymousClass.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen:

public class AnonymousClass
{
// Create an interface that describes 

// something to do.
interface DoSomething
{
// Specify a method for doing something.
void SaySomething();

// Specify a second method.
void SaySomethingSpecific(String Value);
}

public static void main(String[] args)
{
// Create an instance of the interface using an
// anonymous class.
DoSomething DoIt = new DoSomething()
{
// Define the functionality of the methods
// within the interface.
public void SaySomething()
{
System.out.println("I'm saying something!");
}

public void SaySomethingSpecific(String Value)
{
System.out.println(Value);
}
};

// Actually use the anonymous class.
DoIt.SaySomething();
DoIt.SaySomethingSpecific("I'm saying something specific");
}
}

In this case, the example begins with an interface named DoSomething that contains two methods: SaySomething() and SaySomething
Specific(). An interface doesn’t provide any sort of implementation — it simply states what needs to be done.

The main() method begins by creating an instance of DoSomething that defines the implementation as an anonymous class. Notice that you must define both methods contained in DoSomething, even if you plan to use only one method in your application. The point is that there is a class definition here, but it doesn’t have a name. Notice that the anonymous class declaration ends with a semicolon.

To use the anonymous class functionality, you call one of the methods contained within the DoIt object as shown later in the code. If the example didn’t include the anonymous class, the code wouldn’t compile because you’d only have an interface and it isn’t possible to instantiate an interface.

3. Using the standard commands of your editor or IDE, save this file as AnonymousClass.java.

4. In your command prompt, type javac AnonymousClass.java and press Enter.

The compiler compiles your application and creates a .class file from it.

5. Type java AnonymousClass and press Enter.

You see the output shown in Figure 9-6. As you can see, the code calls each of the anonymous class methods in turn.

9781118098783-fg0906.tif

Figure 9-6:

Working with Lambda Expressions

Many things could be said about lambda expressions — all of them are confusing. The easiest way to think about lambda expressions is as a concise form of anonymous class. You use lambda expressions when an anonymous class would have a single functional interface that has only one method.


LINGO

A lambda expression provides a shortened version of an anonymous class that has just one functional interface and one method. Lambda expressions make it possible to perform tasks extremely fast and with little code. The terseness that lambda expressions provide makes it easier to focus on the purpose of the code rather than the coding structure.


Lambda expressions rely on a shorthand method for defining what task they perform that lends elegance to your application code. You use the arrow operator (->) to define the two parts of a lambda expression. The left side defines any arguments input to the one method in the interface, while the right side contains the interface implementation as defined by that one method. The following example makes things a lot clearer for you as you work through your first lambda expression.

Files needed: LambdaExpression.java

1. Open the editor or IDE that you’ve chosen to use for this book.

2. Type the following code into the editor screen:

public class LambdaExpression
{
// Create an interface that describes 

// something to do.
interface DoSomething
{
// Specify a method for doing something.
void SaySomethingSpecific(String Value);
}

public static void main(String[] args)
{
// Create an instance of the interface using a
// lambda expression.
DoSomething
DoIt = (Value) -> { System.out.println(Value); };

// Actually use the lambda expression.
DoIt.SaySomethingSpecific("Saying something specific!");
}
}

The example begins by creating an interface, just as you would when working with an anonymous class. However, notice that this version of DoSomething contains only one method. If your interface requires two methods, you must use an anonymous class implementation instead.

Creating the lambda expression requires you to complete these four tasks:

· Define the type of the lambda expression (DoSomething in this case), which is the name of the interface you want to use.

· Define the name of the object that will hold the lambda expression (DoIt in this case).

· Specify any input arguments based on the interface definition (Value in this case). Notice that you don’t define the variable type — Java infers the variable type for you.

· Create an expression that implements the interface. Notice that the expression appears on the right side of the arrow operator.

Using the resulting lambda expression is much the same as using an anonymous class. You simply specify the name of the object, the method it contains, and any arguments required for that method.

3. Using the standard commands of your editor or IDE, save this file as LambdaExpression.java.

4. In your command prompt, type javac LambdaExpression.java and press Enter.

The compiler compiles your application and creates a .class file from it.

5. Type java LambdaExpression and press Enter.

You see the output shown in Figure 9-7.

9781118098783-fg0907.tif

Figure 9-7:

summingup_fmt.eps Summing Up

Here are the key points you learned about in this chapter:

· Methods provide the means of telling a class or object to perform a specific task.

· A method declaration includes the method scope, whether it’s static or non-static, the return type, method name, argument list, and method body.

· Properties provide the means of interacting with data inside of a class or object.

· A property declaration includes the property scope, whether it’s static or non-static, type, variable name, and initial value.

· Using getters and setters helps protect the data managed by your class from improper use by the caller.

· Every class you create in Java inherits from a parent class of some sort.

· A class that you create inherits from the Object class.

· Use the private scope to completely hide class elements.

· Use the default scope to hide class elements from access outside the current package.

· Use the protected scope to hide class elements from access outside of subclasses.

· Use public scope to allow access of class elements by anyone.

· A class that relies on events uses an event class to define that event.

· Event listeners wait for events to happen and then react to them.

· An implementation of an event as part of a class requires that you provide a means to register and unregister event handlers.

· You must provide a means of firing the event.

· Anonymous classes make it possible to express tasks by using significantly less code than would otherwise be needed when using more traditional techniques.

· Lambda expressions provide a shortcut method for creating specialized versions of anonymous classes that have just one functional interface and one method.

Try-it-yourself lab

For more practice with the features covered in this chapter, try the following exercise on your own:

1. Open the ParentClass.java file supplied with the source code for this book.

2. Add a new method named AnotherString() and have it return “This is another string” to the caller.

Use the GetClassName() method as an example of how you should create the new method.

3. Open the UseSimpleClass application.

4. Add a call to System.out.println(Test.AnotherString()); at the end of the main() method.

Adding this call will test the new AnotherString() method.

5. Compile the application.

6. Run the application.

What happens when you run the application? What does this result tell you about inheritance?

Know this tech talk

· anonymous inner class: A special kind of unnamed class that contains one or more interfaces and one or more methods. You use an anonymous class when a formal class declaration is unneeded or unwanted. Because an anonymous class has no name, you can’t reference it outside the class in which it exists.

· constructor: A special type of method used to create an object from a class. Every class comes with at least one constructor, the default constructor.

· event: A special occurrence within a class that the class makes outsiders aware of.

· event handler: A special method that’s designed to react to events generated by another class.

· event listener: A special class that’s designed to listen for events that occur within another class.

· field: A variable that’s defined as part of a class or an object.

· interface: A class that defines unimplemented methods. Any class inheriting from an interface must provide implementations of the described methods.

· getter: A special method used to obtain the value of a field and make it accessible outside the class or object.

· lambda expression: An anonymous class that contains just one functional interface and one method. Normally, a lambda expression is designed to perform a task by using the shortest possible code.

· method: The means of telling a class or object to perform a specific task.

· override: To replace the implementation of a method in a parent class with a new implementation in a child class. Often, the parent class supplies a simple method that doesn’t address the requirements of the child class.

· package: A container used to hold multiple classes together. The simplest package relies on a subdirectory of a directory structure. A package is always defined using the package keyword in the .java file.

· property: The means of accessing a value stored by a class or object.

· setter: A special method used to change the value of a field from outside of the class or object.

· superclass: The parent class of the current class. You access the superclass by using the super keyword.