What are Methods?
Types of Methods
Java methods are an integral part of the Java program, falling into a few categories like instance methods, class methods, helper methods, and constructors.Many technical conversations about a Java program concern methods in some way. This focus is not overstated: all Java programs contain at least one method, the main method. All methods contain a heading and a block of code, and many receive and use parameters of some type.
Yet the methods available to the Java programmer falls into several descriptive categories: instance methods, class methods, helper methods, and constructors. All methods can also be organized according to whether or not they return a result from their operations.
Instance Method
When an object is instantiated, it is created based on its class definition. This object typically has instance fields, its own copied set of the standard fields of its class definition. Likewise, an instance method is associated with an object of a class rather than a class itself. For example:
System.out.println(“This is text.”);
Println is here an instance method associated with the out object that has been instantiated. The out object belongs to the System class; note that the more names tacked on to the right of the class name (System.out.println versus System.out) the more specific the reference becomes.
Class Methods
A method that belongs to its class rather than to an object of that class, as described above, is a class method. While an instance method has access to both instance fields and class fields, a class method has access only to the class fields. A class method is declared with a modifier, like so:
public static void methodName(){}
The static keyword sticks the method to the class rather than to objects of that class. When the class method is called, its name is tacked next to the class name rather than to an object of that name:
class.classMethod();
Class methods are useful for creating constants and class fields that need to be used throughout a program.
Helper Methods
Helper methods are exclusive to a class; only other methods in the same class can call this type of method. They are made exclusive with another use of declaring modifiers. Rather than the typical method heading of:
public void methodName(){}
Helper methods use the private keyword:
private void methodName(){}
Furthermore, a call to a helper method does not involve sticking the method name to a class name or object name as with instance methods and class methods. Rather than System.methodName();, a call to a helper method would simply be methodName();
Since the private method is in the same class and can only be used by methods in that class, there's no point in using the hierarchical referencing when calling these methods. Helper methods are typically used in complex classes that need careful organization to make sense to the programmer, or to perform tasks that are needed only in that class.
Constructor Methods
Constructor methods are unique among methods, sharing little similarities and many differences with typical methods. First of all, constructor methods exist only to instantiate a class, not to execute code. Second, constructor methods have no return type at all, not even void, and have only one modifier in their heading.
While constructor methods are not required, a blank one is automatically loaded if none is present and multiple constructor methods with the same name can be written in a process known as overloading.
Special method for creating new instance of a class. Must have the same name as the class it constructs. Below (line 4) is the constructor for Cat.
Accessor Methods
Methods that return variables. The accessor method name should start with "get". Below (line 8) is the accessor named getCatsColor.
Mutator Methods
Methods that alter variables. The mutator method name should start with "set". Below (line 12) is the accessor named setCatsColor.1 class Cat { 2 private static String animalType = "feline"; 3 private String catColor; 4 Cat(String colorIn) 5 { 6 setCatsColor(colorIn); 7 } 8 public String getCatsColor() 9 { 10 return this.catColor; 11 } 12 public String setCatsColor() 13 { 14 this.catColor; 15 } 16 17 public static void main (String[] argsIn) { 18 Cat patches = new Cat("calico"); 19 } 20 }Signature or Method Signature
What variable types and in what order they are passed to a method. The return type is not a part of the signature. In the folowing method "String, double" is the signature:public int returnAnInt(String stringIn, double doubleIn) { int intToReturn = 1; if (stringIn.equals(String.valueOf(doubleIn)) { intToReturn = 2; } return intToReturn; }Overloaded Methods
Two or more methods with same name, different signature, return types can vary - but do not have to.public int returnOneNoMatterWhat(String stringIn, double doubleIn) { int intToReturn = 1; return intToReturn; }
public int returnOneNoMatterWhat(int intIn) { int intToReturn = 1; return intToReturn; }Summary
Methods, like many parts of Java, are a complex topic requiring a bit of time and study to understand completely.
Calling a Method
A method is a set of code which is referred to by name and can be called (invoked) at any point in a program simply by utilizing the method's name. Think of a method as a subprogram that acts on data and often returns a value.Each method has its own name. When that name is encountered in a program, the execution of the program branches to the body of that method. When the method is finished, execution returns to the area of the program code from which it was called, and the program continues on to the next line of code.
Good programmers write in a modular fashion which allows for several programmers to work independently on separate concepts which can be assembled at a later date to create the entire project. The use of methods will be our first step in the direction of modular programming.
Methods are time savers, in that they allow for the repetition of sections of code without retyping the code. In addition, methods can be saved and utilized again and again in newly developed programs.
You are using methods when you use
System.out.print( ) and System.out.println( ).There are two basic types of methods:
Built-in: Build-in methods are part of the compiler package, such as System.out.println( ) and System.exit(0).
User-defined: User-defined methods are created by you, the programmer. These methods take-on names that you assign to them and perform tasks that you create. How to invoke (call) a method (method invocation):
When a method is invoked (called), a request is made to perform some action, such as setting a value, printing statements, returning an answer, etc. The code to invoke the method contains the name of the method to be executed and any needed data that the receiving method requires. The required data for a method are specified in the method's parameter list.
Consider this method that we have already been using from Breezy;
int number = Console.readInt("Enter a number"); //returns a value
The method name is "readInt" which is defined in the class "Console". Since the method is defined in the class Console, the word Console becomes the calling object. This particular method returns an integer value which is assigned to an integer variable named number.
You invoke (call) a method by writing down the calling object followed by a dot, then the name of the method, and finally a set of parentheses that may (or may not) have information for the method.
Defining Methods
Here is an example of a typical method declaration:
public double calculateAnswer(double wingSpan, int numberOfEngines, double length, double grossTons) { //do the calculation here }The only required elements of a method declaration are the method's return type, name, a pair of parentheses,
()
, and a body between braces,{}
.More generally, method declarations have six components, in order:
- Modifierssuch as
public
,private
, and others you will learn about later.- The return typethe data type of the value returned by the method, or
void
if the method does not return a value.- The method namethe rules for field names apply to method names as well, but the convention is a little different.
- The parameter list in parenthesisa comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses,
()
. If there are no parameters, you must use empty parentheses.- An exception listto be discussed later.
- The method body, enclosed between bracesthe method's code, including the declaration of local variables, goes here.
Modifiers, return types, and parameters will be discussed later in this lesson. Exceptions are discussed in a later lesson.
Definition:Two of the components of a method declaration comprise the method signaturethe method's name and the parameter types.
The signature of the method declared above is:
calculateAnswer(double, int, double, double)Naming a Method
Although a method name can be any legal identifier, code conventions restrict method names. By convention, method names should be a verb in lowercase or a multi-word name that begins with a verb in lowercase, followed by adjectives, nouns, etc. In multi-word names, the first letter of each of the second and following words should be capitalized. Here are some examples:
run runFast getBackground getFinalData compareTo setX isEmptyTypically, a method has a unique name within its class. However, a method might have the same name as other methods due to method overloading.
Method Parameters - Passing Information to a Method or a Constructor
The declaration for a method or a constructor declares the number and the type of the arguments for that method or constructor. For example, the following is a method that computes the monthly payments for a home loan, based on the amount of the loan, the interest rate, the length of the loan (the number of periods), and the future value of the loan:
public double computePayment( double loanAmt, double rate, double futureValue, int numPeriods) { double interest = rate / 100.0; double partial1 = Math.pow((1 + interest), -numPeriods); double denominator = (1 - partial1) / interest; double answer = (-loanAmt / denominator) - ((futureValue * partial1) / denominator); return answer; }This method has four parameters: the loan amount, the interest rate, the future value and the number of periods. The first three are double-precision floating point numbers, and the fourth is an integer. The parameters are used in the method body and at runtime will take on the values of the arguments that are passed in.
Note:Parameters refers to the list of variables in a method declaration. Arguments are the actual values that are passed in when the method is invoked. When you invoke a method, the arguments used must match the declaration's parameters in type and order.
Parameter Types
You can use any data type for a parameter of a method or a constructor. This includes primitive data types, such as doubles, floats, and integers, as you saw in the
computePayment
method, and reference data types, such as objects and arrays.Here's an example of a method that accepts an array as an argument. In this example, the method creates a new
Polygon
object and initializes it from an array ofPoint
objects (assume thatPoint
is a class that represents an x, y coordinate):public Polygon polygonFrom(Point[] corners) { // method body goes here }
Note:The Java programming language doesn't let you pass methods into methods. But you can pass an object into a method and then invoke the object's methods.
Arbitrary Number of Arguments
You can use a construct called varargs to pass an arbitrary number of values to a method. You use varargs when you don't know how many of a particular type of argument will be passed to the method. It's a shortcut to creating an array manually (the previous method could have used varargs rather than an array).
To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name. The method can then be called with any number of that parameter, including none.
public Polygon polygonFrom(Point... corners) { int numberOfSides = corners.length; double squareOfSide1, lengthOfSide1; squareOfSide1 = (corners[1].x - corners[0].x)*(corners[1].x - corners[0].x) + (corners[1].y - corners[0].y)*(corners[1].y - corners[0].y) ; lengthOfSide1 = Math.sqrt(squareOfSide1); // more method body code follows // that creates and returns a // polygon connecting the Points }You can see that, inside the method,
corners
is treated like an array. The method can be called either with an array or with a sequence of arguments. The code in the method body will treat the parameter as an array in either case.You will most commonly see varargs with the printing methods; for example, this
printf
method:public PrintStream printf(String format, Object... args)allows you to print an arbitrary number of objects. It can be called like this:
System.out.printf("%s: %d, %s%n", name, idnum, address);or like this
System.out.printf("%s: %d, %s, %s, %s%n", name, idnum, address, phone, email);or with yet a different number of arguments.
Parameter Names
When you declare a parameter to a method or a constructor, you provide a name for that parameter. This name is used within the method body to refer to the passed-in argument.
The name of a parameter must be unique in its scope. It cannot be the same as the name of another parameter for the same method or constructor, and it cannot be the name of a local variable within the method or constructor.
A parameter can have the same name as one of the class's fields. If this is the case, the parameter is said to shadow the field. Shadowing fields can make your code difficult to read and is conventionally used only within constructors and methods that set a particular field. For example, consider the following
Circle
class and itssetOrigin
method:public class Circle { private int x, y, radius; public void setOrigin(int x, int y) { ... } }The
Circle
class has three fields:x
,y
, andradius
. ThesetOrigin
method has two parameters, each of which has the same name as one of the fields. Each method parameter shadows the field that shares its name. So using the simple namesx
ory
within the body of the method refers to the parameter, not to the field. To access the field, you must use a qualified name. This will be discussed later in this lesson in the section titled "Using thethis
Keyword."Passing Primitive Data Type Arguments
Primitive arguments, such as an
int
or adouble
, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost. Here is an example:public class PassPrimitiveByValue { public static void main(String[] args) { int x = 3; // invoke passMethod() with // x as argument passMethod(x); // print x to see if its // value has changed System.out.println("After invoking passMethod, x = " + x); } // change parameter in passMethod() public static void passMethod(int p) { p = 10; } }When you run this program, the output is:
After invoking passMethod, x = 3Passing Reference Data Type Arguments
Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.
For example, consider a method in an arbitrary class that moves
Circle
objects:public void moveCircle(Circle circle, int deltaX, int deltaY) { // code to move origin of // circle to x+deltaX, y+deltaY circle.setX(circle.getX() + deltaX); circle.setY(circle.getY() + deltaY); // code to assign a new // reference to circle circle = new Circle(0, 0); }Let the method be invoked with these arguments:
moveCircle(myCircle, 23, 56)Inside the method,
circle
initially refers tomyCircle
. The method changes the x and y coordinates of the object thatcircle
references (i.e.,myCircle
) by 23 and 56, respectively. These changes will persist when the method returns. Thencircle
is assigned a reference to a newCircle
object withx = y = 0
. This reassignment has no permanence, however, because the reference was passed in by value and cannot change. Within the method, the object pointed to bycircle
has changed, but, when the method returns,myCircle
still references the sameCircle
object as before the method was called.Method Scope - Declarations and Access Control
- names are used to identify entities declared in a program ie classes, methods, variables, parameters, etc
- each name or identifier occupies a particular namespace
- every declaration has a scope; the areas of a program from which it can be accessed by its simple name
Declaration Scope (accessible from) package all compilation units within the package import all the classes and interfaces within the compilation unit (source code file) class or interface all other declarations within the same file label the statements immeadiately enclosed by the labeled statement ie if a loop is labelled, everything declared within the loop-construct has access to the label member the body of the class and anything declared within the class parameter the body of the method or constructor local variable the code block in which the declaration occurs local class the enclosing block including the local class body local variable in a for-loop initializer the body of the for-loop parameter in a catch clause the body of the catch clause Order of searching for an identifier
- when a name (identifier) is used; the meaning, or scope, of it's name is searched for based on where it appears in the code starting with:
- if used in a code block, for-loop, or in a catch clause, search is for a local variable within the enclosing construct
- if in a method or constructor, searches for a matching parameter
- search continues for a class or interface member, including inherited members
- if its a nested type, searches enclosing block or class. If its a static type, only static members of enclosing blocks or classes are searched.
- explicitly named imported types
- other types declared in the same package
- implicitly named imported types
- packages on the host system
Shadowing
- Because of the way identifiers are looked up; shadowing declarations can occur
- For example, a field declaration can be shadowed by a local variable declaration
class TestShadowing { static int x = 1; // field variable public static void main(String[] args) { int x = 0; // local variable System.out.println("x = " + x); System.out.println("TestShadowing.x = " + TestShadowing.x) } } Output: x = 0 TestShadowing.x = 1
- because the identifier x is used within a code block main() a search is made for a declaration of x within the body of main(). As one is found, int x = 0, the simple identifier name x is assumed to be within scope as a local variable
- to access the field variable x, you must use its fully-qualified name TestShadowing.x
Note
- it was not necessary to instantiate an instance of the TestShadowing object to access the static field variable. If x had been an instance variable it would have been necessary to create a new instance of TestShadowing and use it's reference to access x
Hiding
- Shadowing is not the same as hiding
- hiding applies to members that would normally be inherited but are not because of a declaration of the same identifier in a subclass
class SuperA { int x = 10; } class SubA extends SuperA { int x = 20; // hides x in superclass }
- a method can hide a method in the superclass by overriding it
static Methods cannot be overridden
- a method cannot override a static method in the superclass; however, it can hide it by using the same declaration
class SuperA { static void method2() { } } class SubA extends SuperA() { void method2() { // declaration causes a compile-error } static void method2() { // compiles ok } }
- static methods are hidden vs overridden as the JLS states they "cannot be overridden" so the compiler never compares subclass method declarations to static superclass method declarations.
- a static method in a subclass cannot hide an instance method in the superclass
class SuperA { void method1() { } } class SubA extends SuperA() { static void method1() { // compile-error } }
- a hidden method can be accessed by using super(), casting to the superclass or using the methods fully qualified name
((SuperA)y).method2(); // cast to access hidden method
- instance variables can hide static and non-static variables in the superclass
Obscuring
- there may be times when a simple name could be interpreted as a variable, a type or a package
- based on the rules, a variable will be chosen before a type, and a type before a package
- in such situations a declaration is said to be obscured
- following naming conventions helps to avoid obscuring