Java for Humans {Methods & Dot Notation}

Lincoln W Daniel
Jan 9, 2016 · 10 min read
View Table of Contents | Download Supporting Code | Subscribe to ModernNerd Youtube Channel for Coding Videos | By Lincoln W Daniel

From the Classes and Objects chapter, you’ve learned that methods are used in Java to provide functionality to our classes and their instances. In this chapter, we will dive deeper into methods to learn how we create them, how we access them, and why they are important to Java programming. There’s a good deal to learn and this will be one of the longer chapters of the book, so take it slowly and calmly.

Why Methods are Important & Useful

Remember that in Java, everything revolves around objects. Objects are to Java programs as nouns are to English sentences. If objects are so important, they’d be really boring if all we could do is store information in them. Fields of classes are awesome for holding information about instances of our classes, but they aren’t much fun on their own. They can’t do any cool tricks. All they do is sit there and take up space in our programs. Imagine bringing home a new dog and naming it, memorizing its color, age and height, but not being able to do anything with it. Your excitement about your new dog wouldn’t last too long if that was the case. You’d want it to be able to actually do cool tricks instead of simply standing there and taking up space in your living room. That’s why Java and other programming languages decided to include the notion of methods.

With methods, not only can we manipulate the data in our fields, we can manipulate other data provided to us in order to create new information for our users to consume. Methods, although incredibly powerful, are easy to work with. We can give our classes a virtually unlimited amount of methods for their instances to perform.

The Main Method

Some methods, as you’ve learned about static methods, don’t even need to be called by an instance of their class. We’ve been working with one of those static methods since the first program we ran in the “Hello World” chapter. In the class that we ran the program from, we wrote our code in its main method. The main method of your program’s main class is static and the computer calls it to run our program. From there, the rest of our code runs in order from top to bottom. We can call the main class anything we want, but we must call the main method “main”. Only your main class needs to have the main method to run your program, but it must be present in at least one class in your program:

public class Main {

/**
* Your code is executed in order,
* top to bottom, starting from here.
*
*
@param args arguments the computer
* provides to this method when it calls it.
*/
public static void main(String[] args){
System.out.println("Hello, World!");
}
}

Method Syntax

Remember that methods are named the same way we name variables, but they require a bit more information to make them work. When we make a method, we must provide five, most of the time its only four, main points of information in the signature of our method. It is important to remember that no two methods can have the same signature, but two methods can have the same name although this is usually not a good idea.

After the signature, we create the body of our method between a single set of opening and closing curly brackets. The signature of our method and its body are the scope of our method. The scope simply defines the lifetime of variables declared in it. Every opening curly bracket starts a new scope and every closing curly bracket ends the last open scope:

{scope 1 {scope 2 {scope 3}} {scope 4 {scope 5 {scope 6}}}}

Variables declared in a scope live, are accessible, until that scope ends. Thus, a variable declared in scope one is accessible from all of the scopes within scope one, but a variable declared in scope three is only available to scope two, and a variable declared in scope six is only available to scope five and four as illustrated above. In Java, while you can put as many methods as you desire in the scope of a class, it is not legal to embed a method inside of another method’s scope.

Method Signature

First, we need to provide an access modifier to tell the compiler that executes our code where our method can be accessed from. Next, we need to say whether or not it’s static; by default, methods are not static, so we can simply omit the static keyword. After that, we need to tell the compiler what kind of data, or the datatype, our method returns; most of the time, this is either going to be a class type or a primitive type, and other times we can return data structures. Then, we need to give our method a lower camel case name that is usually unique — you’ll learn when it’s not unique later. Finally, we need to declare a list of the parameters that must be provided to our method as arguments when it’s called. When we provide all of that information, we can start the body of our method with a opening curly bracket { and end it with a closing closing curly bracket }:

public //access modifier
static //says if the method is static
int //return type
add //name
(int num1, int num2) //parameters
{ //start body, scope
//body: write fun code here

}//end body, scope

Method Access Modifiers

A public method can be accessed from anywhere in our program, but private methods can only be accessed from within the class it belongs to. A protected method can be accessed from any class within the same package as the class the method belongs to. Those access modifiers work the same on both instance and static methods of a class.

Intuitively, a method can only be accessed from the parts of a program where the method’s class can be accessed.

Method Return Types

A method must specify a return type in its signature. A return type tells the compiler what datatype will be returned by the method. If the method will not return anything, we can specify void as the return type. Void means that the method will do what it has to do and return nothing to the caller. Otherwise, we must specify a datatype to be returned. We can return Java primitives, datatypes provided by Java, including a String, and custom datatypes, such as classes we create. Further, we can return data structures like arrays, LinkedLists, and HashMaps. We will learn more about data structures soon, but for now, know that they are simply datatypes that hold a set of data of the same type.

Method Parameters

Remember that methods are powerful in that they can manipulate data available in our class or instances of our class, but sometimes we need them to do more. Sometimes they need some data from outside of our class or instances of our class to complete the job. A good example of this is when you are in gym class and the instructor asks you to jump. Some people would start jumping mindlessly, but the wise thing to do would be to ask the instructor how high he wants you to jump and for how long. Next time the instructor invokes, or calls, your jump method, he will know he has to provide you a height to jump to and the amount of time to continue jumping for. Soon, we will use that same idea to teach our new pet dog how to jump.

We can provide as many parameters as we want to our methods, and when someone calls one of our methods, they will have to pass in all of the parameters we require as arguments. Our methods can then use the parameters as variables in their body. It is often wise to check if the parameter provided to our method is not empty by checking that it’s not null because users may misuse our methods.

A null object is one that has no data in it and, therefore, has no type. Such an object cannot be used. Consequently, if we try to call a method on a null object, our program will break. We can use a if statements to check if a parameter is null in our method’s body before we use it by comparing the parameter to null with the not-equal-to equality operator !=. The good news is primitives cannot be null because they have default values. However, remember that a string is an instance of the String class provided by Java, so it is not a primitive and, like other class instances, should always be checked against null.

Modeling Our New Pet Dog

Let’s make a dog class to model our new pet dog. We will give our dog functionality by adding methods to its class that will allow it to do cool tricks. Our class will be called CoolDog because any instance of it will be able to do cool tricks unlike our boring dog from earlier. All instances of our CoolDog class will have a name, an age, a height in inches, a Human owner, and a unique id that is final — cannot be changed after it’s set. Our CoolDog class will also have a static field to keep track of how many cool dogs have been instantiated in our program. Finally, all cool dogs will be able to bark, roll over, and jump. We will also have a Human class that we will use to define a field in our CoolDog class, but that code can only be found in the supporting code for this chapter.

package methodsAndDotNotation;

/**
* Created by lwdthe1 on 1/8/2016.
*/
public class CoolDog {
...

public CoolDog(String name, int age, int height) {
this.name = name;
this.age = age;
this.height = height;

id = ++numCoolDogs;
}

public String getName() { return name; }
public int getAge() { return age; }
public int getHeight() { return height; }
public Human getOwner(){ return owner; }
public void setOwner(Human owner) { this.owner = owner; }
private boolean hasOwner() {
return owner != null;
}

public void jump(int howHigh, int howLong) {
if(hasOwner()) {
System.out.println("Jumping " + howHigh
+ " inches high for " + howLong + " seconds.");
} else { bark(); }
}

public void rollOver() {
if(hasOwner()) {
System.out.println("Rolling over for " + owner.getName() + ".");
} else { bark(); }
}

public void bark() {
System.out.println("Wolf! WOLF!!");
}

public static int getNumCoolDogsInWorld(){
return numCoolDogs;
}
}

We have once again left some of the code out of this code snippet, and that is denoted by the ellipses (…). Notice that our CoolDog class has four instance methods that return the values of an instance’s instance fields. The return type of the getName() method is a String, the getAge() method returns data of type int, and the getHuman() method returns the owner, a type of Human. A cool dog will bark whenever the bark() method is called, but a cool dog can only roll over or jump if it has a owner who has taught it how to. In the cases where a cool dog does not have a Human owner, it will bark when asked to roll over or jump.

The numCoolDogs static field is incremented each time the constructor of our CoolDog class is invoked to maintain an accurate count of how many instances exist of the class. If at any point we want to know how many CoolDog instances exist in our program, we can call the static getNumCoolDogsInWorld() method to return to us an int, numCoolDogs, that represents how many instances of our CoolDog class have been constructed.

Notice that the hasOwner() instance method is private because only the dog needs to know if it has a owner. We won’t be able to call that method from outside of the CoolDog class, not even on an instance of the class. Finally, observe that many of the methods, such as rollOver(), in the CoolDog class do not have parameters. This is simply because they don’t need data from the caller to do their job; they use the data available in the instance to do what they have to.

Dot Notation

Notice that, in this chapter as well as previous chapters, whenever we’ve wanted to access a field or call a method from a class or an instance of a class, we’ve had to write a dot (.) after the name of the class or its instance followed by the name of the field or method. This is called dot notation:

Human person = new Human("Lucy");
CoolDog coolDog = new CoolDog("Buddy", 4, 30);
person.setPetDog(coolDog);

There, we used dot notation to call the setPetDog() method of the Human instance and we passed that method the required argument of a CoolDog instance.

We can also employ chaining with dot notation to optimize field accesses and method calls. Imagine if we want to get the petDog field of the Human instance, person, and make that CoolDog instance jump ten inches in the air for five seconds. We can save the returned CoolDog instance to a variable and then call jump on that variable like so:

CoolDog petDog = person.getPetDog();
petDog.jump(10, 5);

Sometimes, a more efficient way to do the same thing may be to use chain dot notation. When the person returns its instance of a CoolDog to us, the caller, we can immediately make it jump as we wish without saving the returned CoolDog to a variable first:

person.getPetDog().jump(10, 10);

That method of using chain dot notation saves us from writing more code and it saves space in our computer’s memory because we aren’t allocating another variable in memory.

Well there it is! You are past the stage of not knowing how to code now. You are on to the stage of becoming a better programmer. Soon, you’ll learn about looping, data structures to store sets of data for later use, and how to get user input, which you’ve already seen in action.


ModernNerd Code

Learn to Code Life. Subscribe to Video Tutorials on Youtube

Lincoln W Daniel

Written by

My passion is in developing software to enable people to accomplish their goals more efficiently. Author @JavaForHumans.com. Creator of @Smedian.com

ModernNerd Code

Learn to Code Life. Subscribe to Video Tutorials on Youtube

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade