Methods
Navigate Language Fundamentals topic: ) |
[edit] Method Definition
A method is an operation on a particular object. An object is an instance of a class. When we define a class we define its member variables and its methods. For each method we need to give a name, we need to define its input parameters and we need to define its return type. We also need to set its visibility(private, package, or public). If the method throws an Exception, that needs to be declared as well. The syntax of method definition is:
class
MyClass { ...public
ReturnType methodName( ParamOneType param1, ParamTwoType param2 )throws
ExceptionName { ReturnType retType; ...return
retType; } ... }
We can declare that the method does not return anything using the void
java keyword. For example:
private
void
methodName(String
param1,String
param2 ) { ...return
; }
When the method returns nothing, the return
keyword at the end of the method is optional. The return
keyword can be used anywhere in the method, when the executation flow reach the return
keyword, the method execution is stopped and the execution flow returns to the caller method.
[edit] Method Overloading
For the same class we can define two methods with the same name. However the parameter types and/or the number of parameters must be different for those two methods. In the java terminology, this is called method overloading. It is useful to use method overloading when we need to do something different based on a parameter type. For example we may have the operation : runAroundThe. We can define two methods with the same name, but different input parameter type:
public
void
runAroundThe( Building block ) { ... }public
void
runAroundThe( Park park ) { ... }
Related terminology is the method signature. In java the method signature contains method name and the input parameter types. The java compiler takes the signature for each method and makes sure that each method signature is unique for a class. For example the following two method definitions are valid:
public
void
logIt(String
param, Error err ) { ... }public
void
logIt( Error err,String
param ) { ... }
Because the type order is different. If both input parameters were type String, that would be a problem since the compiler would not be able to distinguish between the two:
public
void
logIt(String
param,String
err ) { ... }public
void
logIt(String
err,String
param ) { ... }
The compiler would give an error for the following method definitions as well:
public
void
logIt(String
param ) { ... }public
String
logIt(String
param ) {String
retType; ...return
retValue; }
Note, the return type is not part of the unique signature. Why not? The reason is that a method can be called without assigning its return value to a variable. This feature came from C and C++. So for the call:
{ logIt( msg ); }
the compiler would not know which method to call.
[edit] Method Overriding
Obviously a method signature has to be unique inside a class. The same method signature can be defined in different classes. If we define a method that exist in the super class then we override the super class method. The terminology for this is method overriding. This is different from method overloading. Method overloading happens with methods with the same name different signature. Method overriding happens with same name, same signature between inherited classes.
The return type can cause the same problem we saw above. When we override a super class method the return type also must be the same. In fact if that is not the same, the compiler will give you an error.
Method overriding is related dynamic linking, or runtime binding. In order for the Method Overriding to work, the method call that is going to be called can not be determined at compilation time. It will be decided at runtime, and will be looked up in a table.
{ 1 MyClass obj =new
SubOfMyClass(); 2 3 MyClass obj =new
MyClass(); 4 5 obj.myMethod(); // -- During compilation, it is not known what reference the 'obj' has, MyClass or SubOfMyClass }
In the above example 'obj' reference has the type MyClass on both line 1 and line 3. However the 'obj' reference points two different objects. On line 1 it references SubOfMyClass object, on line 3 it references MyClass object. So on line 5 which method will be called, method define in MyClass, or the method that defined in its subclasses. Because the 'obj' reference can point to object and all its sub object, and that will be known only at runtime, a table needs to be kept with all the possible method address to be called.
Also another rule is that when you do an override, the visibility of the new method that overrides the super class method can not be reduced. The visibility can be increased, however. So if the super class method visibility is public, the override method can not be package, or private.
In the case of the exception the override method may throw can be the same as the super class or it can be one of that exception inherited class. So the common rule is that the override method must throw the same exception or it is any of its subclasses.
NOTE: A common mistake to think that if we can override methods, we could also override member variables. This is not the case, as member variables are not overriden.
{ 1 MyClass obj =new
SubOfMyClass(); 2 3 MyClass obj =new
MyClass(); 4 5 String var = obj.myMemberVar; // -- The myMemberVar is defined in the MyClass object }
In the above example, it does not count what object the 'obj' reference points to, because it was declared MyClass type on both line 1 and line 3, the variable in the MyClass object will be referenced. In real examples we rarely use public variables, but if you do keep in mind that Java does not support variable overriding.
[edit] Parameter Passing
We can pass in all the primitive data types or any object references to a method. An object cannot be passed to a method, only its references. All parameters (those are primitive types and object references) are passed by value. In other words if you change the passed in parameter values inside the method, that will have no effect on the original variable that was passed in. When you pass in an object reference to a method and then you change that inside the method, that will have no effect on the original object reference. However if you modify the object itself, that will stay after the method returns. Think about the object reference as a pointer to an object. If you change the object the reference points at, that will be permanent. For example:
1 { 2int
var1 = 10; 3int
var2 = 20; 4 ... 5 myMethod( var1, var2 ); 6 ... 7 System.out.println( "var1="+var1 +"var2="+var2 ); // -- The variable values did not change 8 } 9 ... 10void
myMethod(int
var1,int
var2 ) 11 { 12 ... 13 var1 = 0; 14 var2 = 0; 15 ... 16 }
On line 7 the value of var1 is 10 and the value of var2 is 20. When the variables were passed in to the methods their values were copied. This is called passing the parameter by value. In java we do not represent an object directly, we represent an object throught an object reference. You can think of an object reference as a variable having the address of the object. So the object reference passed in by value, but the object itself is not. For example:
1 {
2 MyObjOne obj = new MyObjOne();
3 obj.setName("Christin");
4 ...
5 myMethod( obj );
6 String name = obj.getName(); // --- The name attribute was changed to 'Susan' inside the method
7 }
8 void
myMethod( MyObjOne obj )
9 {
10 obj.setName("Susan");
11 ...
12 obj = new MyObjOne();
13 obj.setName("Sonya");
14 ...
15 }
On line 2, we created an object, on line 3 we set its name property to 'Christin'. On line 5 we called the myMethod( obj )
. Inside the method, we changed the name to 'Susan' through the passed in object reference. So that change will stay. Note however that after we reassigned the obj reference to a new object, that is no effect whatsoever on the passed in object.
[edit] Functions
In java, functions (methods really) are just like in C++ except that they must be declared inside a class and objects are passed by reference automatically. You cannot create pointers to a function but Java has events which really are function pointers under the hood for when you need that type of functionality.
int a_function(double d) { return (int)d; }
[edit] Return Parameter
So as we can see, a method may or may not return a value. If the method does not return a value we use the void
java keyword. Same as the parameter passing, the method can return a primitive type or an object reference. So a method can return only one value. What if you want to return more than one value from a method. You can always pass in an object reference to the method, and let the method modify the object properties. The modified values can be considered as an output value from the method. However it is a better and cleaner option if you create an Object array inside the method, assign the return values and return the array to the caller. You could have a problem however, if you want to mix primitive data types and object references as the output values from the method. There is a better approach. Defines special return object with the needed return values. Create that object inside the method, assign the values and return the reference to this object. This special object is "bound" to this method and used only for returning values, so do not use a public class. The best way is to use a nested class, see example below:
public
class
MyObject { ... /** Nested object is for return values from 'getPersonInfoById' method */public
static
class
ReturnObj {private
int
age;private
String
name;public
void
setAge(int
val ) {this
.age = val; }public
int
getAge() {return
age; }public
void
setName(String
val ) { name = val; }public
String
getName() {return
name; } } // --- End of nested class defination --- /** Method using the nested class to return values */public
ReturnObj getPersonInfoById(int
ID ) { int age; String name; ... // --- Get the name and age based on the ID from the database --- ... ReturnObj ret = new ReturnObj(); ret.setAge( age ); ret.setName( name );return
ret; } }
In the above example the 'getPersonInfoById' method returns an object reference that contains both values the name and age. See below how you may use that object:
{ ... MyObject obj = new MyObject(); MyObject.ReturnObj person = obj.getPersonInfoById( 102 ); System.out.println( "Person Name=" + person.getName() ); System.out.println( "Person Age =" + person.getAge() ); ... }
[edit] Special method, the Constructor
There is a special method for each class that will be executed each time an object is created from that class. That is the Constructor. Constructor does not have a return value and its name is the same as the class name. The Constructor can be overloaded; you can define more than one constructor with different parameters. For example:
public
class
MyClass { private String memberField; /** * MyClass Constructor, there is no input parameter */public
MyClass() { ... } /** * MyClass Constructor, there is one input parameter */public
MyClass( String param1 ) { memberField = param1; ... } }
In the above example we defined two constructors, one with no input parameter, and one with one input parameter. You may ask which constructor will be called. Its depends how the object is created with the new
keyword. See below:
{ ... MyClass obj1 =new
MyClass(); // The constructor with no input parameter will be called MyClass obj2 =new
MyClass("Init Value"); // The constructor with one input param. will be called ... }
In the above example we created two objects from the same class, or we can also say that obj1 and obj2 both have the same type. The difference between the two is that in the first one the memberField
field is not initialized, in the second one that is initialized to 'Init Value'. obj1, and obj2 contains the reference to the object. Each class must have a constructor. If we do not define one, the compiler will create a default so called empty constructor automatically.
public
class
MyClass { /** * MyClass Empty Constructor */public
MyClass() { } }
The Constructor is called automatically when an object is created with the new
keyword. A constructor may also be called from an other constructor, see below:
public
class
MyClass { private String memberField; /** * MyClass Constructor, there is no input parameter */public
MyClass() { MyClass("Default Value"); } /** * MyClass Constructor, there is one input parameter */public
MyClass( String param1 ) { memberField = param1; ... } }
In the above example, the constructor with no input parameter calls the other constructor with the default initial value. This gives an option to the user, to create the object with the default value or create the object with a specified value.
[edit] Static Methods
We defined methods above as operations on an object. Static methods are defined inside a class, but they are not an operation on an object. No object needs to be created to execute a static method, they are simply global functions, with input parameters and a return value.
public
class
MyObject {static
public
String
myStaticMethod() { ... return("I am a static method"); } }
Static methods can be referenced anywhere prefixed by the class name. See below:
{ ... // --- Call myStaticMethod --- System.out.println( "Output from the myStaticMethod:" + MyObject.myStaticMethod() ); ... }
You can write a non object oriented program by using only static methods in java. Because java evolved from the C programming language, static methods are left over from a non object oriented language.
You write static methods the same way you do normal methods, the only difference is that you cannot reference any member variables or any object methods. Static methods can reference only static variables and call only other static methods. However you can create an object and use it inside a static method.
public
class
MyObject {public
String
memberVar;static
private
String
memberStaticVar;static
public
String
myStaticMethod() { memberVar = "Value"; --> ERROR Cannot reference member var. memberStaticVar = "Value"; // --- This is okay, static vars. can be used // --- Create an object --- MyObject obj = new MyObject(); obj.memberVar = "Value"; // --- This is okay since an object is created -- ... return("I am a static method"); } }