Skip to main content

Methods

Method is mechanism for organizing code. It enables creation of reusable code.

return-type name (typed-parameter-list) {
statements
}

Declare & Call

We can have method call above its declaration.

Command-line arguments

Receives an array as parameter

public static void main(String[] args) { }

Here, Hello and Mary Ann is the args.

java com.example.Main Hello "Mary Ann"

Parameters

Parameter receives a copy of the original value.

Primitive Type Parameters

Primitive types are passed into parameter as copies of values.

So with primitives, you can know that there's nothing changes. But with object, the method could change the object.

Object Parameters

Objects are passed by copies of references.

Changes to the reference are visible within method, not visible outside method. Look at this example:

Flight a = new Flight(10);
Flight b = new Flight(20);
swap(a, b);
System.out.println(a, b); // a: Flight(10), b: Flight(20)

static void swap(Flight i, Flight j) {
Flight k = i;
i = j;
j = k;
}

This is how it works:

a -------> Flight(10) <------ j
b -------> Flight(20) <------ i
k

In the end, we swap references i, j (i points to the one that j originally pointed and vice versa)
When exit function, all copies get cleaned up (i, j, k)

In fact, we want to change members of objects \rightarrow using method, specifically getters, setters

Passing objects as references is actually a good idea. It prevents copying large object from ome place to another.

Flight a = new Flight(10);
Flight b = new Flight(20);
swapNumbers(a, b);
System.out.println(a, b); // a: Flight(20), b: Flight(10)

static void swapNumbers(Flight i, Flight j) { // above code:
int k = i.getFlightNumber(); // Flight k = i;
i.setFlightNumber(j.getFlightNumber()); // i = j;
j.setFlightNumber(k); // j = k;
}

Overloading

Overloading means the class can have multiple methods with the same name, as long as they have a unique signature (which is their parameters).

public void func1(Param a) {}
public void func1(int a, int b) {}
public void func1(Param a, int b) {
func1(10, 20);
}

If there's no exact match overload of method, compiler could do automatically conversion.

Overriding

See more at Inheritance.

Initializations

Summary, initialization work in this order:

  1. Field initializers
  2. Initialization blocks
  3. Constructors

Constructors

Java only automatically provide empty constructor when we don't have any at all. This means if you have other constructor than default constructor, you have to declare it or you cannot use default constructor.

Field initializers

You can set initial field values. Or the default initial state of fields:

  • byte, short, int, long: 0
  • float, double: 0.0
  • char: "\u0000"
  • bolean: false
  • reference types: null

Constructor Visibility

It can be private.

Chaining Constructors

One constructor can call another:

  • must be first line of constructor
  • use this keyword followed by parameter list
class Person {
int age;
int house;
double houseFee;

Person(int house) {
this(house > 1 ? 10.0d : 20.0d);
this.house = house;
}

Person(int house, int age) {
this(house);
this.age = age;
}

Person(double houseFee) {
this.houseFee = houseFee;
}
}

Person jason = new Person(10, 20);

Initialization Blocks

Share code across all constructors:

  • cannot receive parameters
  • place code within brackets outside of any method or constructor

A class can have multiple:

  • all always execute
  • execute in order starting at the top of the source file
public class Flight {
private int passengers, int seats = 150;
private int flightNumber;
private bolean[] isSeatAvailable = new boolean[seats];

public Flight() {
for(int i = 0; i < seats; i++) {
isSeatAvailable[i] = true;
}
}

{
for(int i = 0; i < seats; i++) {
isSeatAvailable[i] = true;
}
}

public Flight(int flightNumber) {
this(); // no more needed
this.flightNumber = fightNumber;
}

// Note that, initialization blocks do not replace the default constructor.
public Flight() {} // so we still need if you want a default constructor
}

Finalizations

Garbage Collector

Java runs on JVM, a virtual machine that can track reference.

If an object has no reference pointing to, it is unreachable. And JVM will release its memory automatically with garbage collector. The garbage collector is unpredictable, makes Java isn't an ideal language for strict runtime computations.

Finalizer

Thanks to garbage collection, there's no need for destructor. But garbage collection is only about memory, not other resources. Finalizer is called before the garbage collection.

class Database {
protected void finalize() { // clean up, close connection for e.g
}
}
warning

Finalizer should be avoided:

  • Crash: we cannot know when a finalizer runs since garbage collection may occur anytime \rightarrow crash when resources run out before clean-up happens
  • Performance: cost is expensive
  • Exception: if a finalizer throws an exception, the finalization process stops, leaving the object in a corrupted state without any notification.

finalize has been deprecated starting with Java 9 – and will eventually be removed.