Last Updated:

Java -  Add a behavior

Accessors

Viewing the contents of our Human object by directly referencing variables was convenient, but it's usually not a good thing when another object might dig into the innards of another in a similar way. This violates the encapsulation principle we talked about earlier and allows one object to interfere with the internal state of another object.

A smarter approach is to allow one object to tell other objects about the values of their instance variables on demand. To do this, use accessors.

Access methods are similar to all other methods, but they usually adhere to special naming conventions. To expose the value of an instance variable to another object, create a method named getVariableName(). In the same way, to allow other objects to set instance variable values, create a method named setVariableName().

In the Java community, these accessors are commonly referred to as getter and setter methods because their names begin with get and set. They are the simplest methods you'll ever see, so they are good candidates for illustrating the basic concepts of the methods. You should know that accessors are a common concept for methods that obtain information about an object. Not all accessors follow naming conventions for the getter and setter methods, as we'll see next.

Here are some common characteristics of the getter and setter methods:

  • The access specifier for the getter and setter methods is usually public .
  • Getter methods typically do not use any parameters.
  • Setter methods typically take parameters and often only one, which is the new value of the instance variable they set.
  • The return data type of the getter method is typically the same as the type of the instance variable whose value it returns.
  • The return data type of the setter method is typically void. This means that they return nothing (they only set the value of the instance variable).

Declaring Access Methods

We can add accessors to the age instance variable of the Human object as follows:

The getAge() method returns the value of the age variable using the return keyword. In methods that do not return a result, the last statement is return void; . In this getter method, we refer to age by its name.

We could also use the return this.age; . The variable this refers to the current object. It is implied when you refer to an instance variable directly. Some OO programmers in the world of Smalltalk prefer to use this whenever they refer to an instance variable, just as they used the self keyword when coding in Smalltalk. I like to do this myself, but Java doesn't require it (and adds more information to the screen), so we won't use this technique in the examples in this tutorial until the code without it is less understandable.

Calling Methods

Now that we have access methods, we must replace the direct access to the age variable in our main() method with a method call. main() should now look like this:

If you run this code again, the results should be the same as before. Note that it is easy to call the object's method. Use the following form:

If the method does not accept parameters (like our getter method), you should still add parentheses after the name of the method being called. If the method accepts parameters (like our setter method), specify them inside parentheses, separated by commas if there is more than one.

A few words about the setter method before continuing: It takes an int parameter named anAge . Then assigns the value of this parameter to the age instance variable. We could call the parameter whatever we wanted. The name doesn't matter, but when you use this parameter inside a method, you must use the name you specify.

Before continuing, let's try using the setter method. Add the following line to the main() method immediately after you create the Human instance:

Now let's execute the code again. The result should be 35. Here's what happened behind the scenes:

  • We passed an integer value to the method as a parameter.
  • The JRE allocated RAM for the parameter and named it anAge.

Methods that are not accessors

Accessors are useful, but we want our Human objects to be able to do anything other than share their data with others, so we have to add other methods. We want our Human object to be able to say something, so let's create the speak() method now:

For now, the syntax should be familiar to you. The method returns a string of characters. Let's use it and clear the main() method. Change the first println() call to:

Repeat the code. You should see the word hello on your console.

Line

We've used a few variables of type String, but so far we haven't covered them. Processing strings in C is laborious because they are arrays of 8-bit characters ending in a null character that you had to control. In Java, strings are first-class String objects that have methods to help you process them. As for strings from the C-world, the most similar Java code is the primitive char data type, which stores a single Unicode character, such as 'a'.

You've already seen how to instantiate a String object and set its value, but there are other ways to do this. Here are some ways to create a String instance with a value of "hello":

Because strings in Java are objects, you can use the new operator to create an instance. Setting a variable of type String will have the same result, because Java creates a String object to store characters, then assigns that object to an instance variable.

You can do a lot with String variables; the class has a large number of useful methods. Even without using the methods, we were already doing something interesting with String variables by joining a pair of strings:

Instead of using + we could call the concat() String method to connect it to another string:

This code may look a bit strange, so let's take a look at it briefly, from left to right:

  • System is a built-in object that allows you to interact with various entities of the system environment (including some of the java platform's own capabilities).
  • out is a class variable in system . This means that it is available without creating a System instance. It represents the console.
  • println() is an out method that takes a String parameter that displays it on the console and completes the display with a newline character.
  • "Name: " is a string of characters. The Java framework treats this literal as a String instance, so we can call its methods directly.
  • concat() is a method of a String instance that takes a String parameter and connects it to the string whose method you called.
  • myHuman is our Human instance.
  • getName() is the accessor for the name of an instance variable.

So, the JRE takes the name of our Human object, calls the concat() method in it, and adds "Bob" to "Name:".

In Eclipse, you can see all the available methods of any object by placing your insertion point after the point that follows the variable containing the instance and then pressing Ctrl-Spacebar. This displays a list of methods for the object to the left of the point. You can scroll through the list (it is collapsed) using the cursor arrows on your keyboard, select the desired method and press Enter to select it. For example, to view all the methods available for String objects, place your insertion point after the point following "Name:" and press Ctrl-Spacebar.

Using strings

Now let's use string joining in our Human class. So far, we've had a variable instance of name. It's a good idea to have a firstname and a lastname, then merge them when someone asks Human for his name. No sweat! Add the following method:

Eclipse had to show red squiggly lines in the method because these instance variables do not yet exist. This means that the code cannot be compiled. Now replace the existing variable of the name instance with the following two (with default values, they make more sense):

Then replace the first println() call with the following call:

Now we have a nicer getter method for our variables. It connects them to create the full name Human. We could also write getName() as follows:

This code does the same, but demonstrates the explicit use of the String method and the construction of a chain of method calls. When we call concat() for the firstname with a character string (space), the method returns a new String object that is a combination of the two. We then immediately call the concat() method of this new object to connect to lastname. As a result, we get a beautifully formatted full name.

Arithmetic and assignment operators

Our Human object can speak (speak method) but cannot move. Let's add behavior to "move."

First, let's add an instance variable to track the number of steps taken by the Human object:

Now let's add a method called walk() :

Our method takes an integer parameter that specifies the number of steps to be taken, updates the progress variable that stores that number of steps, and displays some results on the screen. It would also be good to add a getter method for the progress variable; setter is not needed. Why? Indeed, allowing another object to teleport us forward for a certain number of steps may not be such a good idea. If another object wants to tell us to move, it can call walk(). This is certainly a legitimate challenge, although our example is trivial. In a real project, such application design decisions must be made constantly, and often cannot be foreseen, no matter what object-oriented design (OOD) gurus say.

In our method, we update the progress variable by adding the steps value to it. Again, we save the result to progress. We used the most common assignment operator = to save the result. We used the arithmetic operator + to add values. There are other ways to achieve the same goal. The following code does the same thing:

Applying the += assignment operator is a bit less clunky than using the = operator in our first version. This prevents us from using a reference to the progress variable twice. But the same thing happens: you add a steps value to the progress variable and save the result to progress.

The following table provides a list and brief description of most of the commonly found arithmetic and assignment operators in Java (note that some operators are binary and use two operands, and some are unary and use a single operand).

OperatorUse

Description

+a + bAdds a and b
++aConverts a to type int if this variable was of type byteshort, or char
a — bSubtracts b from a
-aArithmetic negation a
*a * bMultiplies a and b
/a / bDivides a by b
%a % bReturns the remainder of dividing a by b

 

(in other words, it is a modulo take operator)

++a++Increases a by 1 ; uses the value of the variable a to calculate before zooming in
++++aIncreases a by 1 ; uses the value of the variable a after incrementing to calculate
a—Reduces a by 1 ; uses the value of the variable a before reduction to calculate
—aReduces a by 1 ; uses the value of the variable a after reduction to calculate
+=a += bSimilarly a = a + b
-=a -= bSimilarly a = a — b
*=a *= bSimilarly a = a * b
%=a %= bSimilarly a = a % b

We've also seen other notations called operators in the Java language. For example: . (dot), which identifies package names and calls methods; ( params ) , which separates the list of method parameters with commas; new , which, together with the name of the constructor, creates an instance of the object. In the next section, we'll meet a few other operators.