Skip to main content

4. Methods in Java

 

Class Members

  • Methods and instance (non-local) variables are collectively known as members.
  • We can modify a member with both access and non-access modifiers.

Access Modifiers

Whereas a class can use just two of the four access control levels (default or public), members can use all four:

  1. public
  2. protected
  3. default
  4. private

Default protection is what we get when we don't type an access modifier in the member declaration.

Member access comes in two different forms:

  1. Whether method code in one class can access a member of another class.
  2. Whether a subclass can inherit a member of its superclass.

Public Members

  • When a method or variable member is declared public, it means all other classes, regardless of the package they belong to, can access the member (assuming the class itself is visible).
  • For a subclass, if a member of its superclass is declared public, the subclass inherits that member regardless of whether both classes are in the same package.

Default Members

  • A default member may be accessed only if the class accessing the member belongs to the same package.

Protected Member

  • Members marked protected can be accessed by all the classes if the class belongs to the same package.
  • For a subclass outside the package, the protected member can be accessed only through inheritance.

Private Members

  • Members marked private can't be accessed by code in any class other than the class in which the private member was declared.
  • When a member is declared private, a subclass can't inherit it. However, we can declare a matching method in the subclass, but it is not an overriding method.
Visibility Public Protected Default Private
Same Class Yes Yes Yes Yes
Other class in Same package Yes Yes Yes No
Class in different package Yes Yes, but only subclass No No

Also we can't define a method inside a method.

Non-Access Member Modifiers

Instead of access modifiers, we can also use non-access modifiers with members, which are:

  1. transient
  2. synchronized
  3. native
  4. strictfp
  5. static
  6. volatile
  7. final

Final Methods

  • The final keyword prevents a method from being overridden in a subclass, and is often use to enforce the API functionality of a method.
  • isAlive() method inside the Thread class is an example of final method.

Abstract Methods

  • An abstract method is a method that's been declared (as abstract) but not implemented.
  • It is illegal to have even a single abstract method in a class that is not explicitly declared abstract.
  • However, we can have an abstract class with no abstract methods.
  • The first concrete (non-abstract) subclass of an abstract class must implement all abstract methods of the superclass.
  • A method can never ever be marked as both abstract and final.
  • Also, the abstract modifier can never be combined with the static modifier.

Synchronized Methods

  • The synchronized keyword indicates that a method can be accessed by only one thread at a time.
  • The synchronized modifier can be applied only to methods, not variables, not classes.
  • The synchronized modifier can be matched with any of the four access control levels.

Native Methods

  • The native modifier indicates that a method is implemented in platform-dependent code, often in C.
  • Native can be applied only to methods, not classes, not variables.
  • A native method's body must be a semicolon (;), indicating that the implementation is omitted.

Strictfp Methods

  • If we don't declare a class as strictfp, we can still declare an individual method as strictfp.
  • strictfp forces floating points (and any floating-point operations) to adhere to the IEEE 754 standard.
  • With strictfp, we can predict how our floating points will behave regardless of the underlying platform the JVM is running on.
  • It can modify a class or method declaration, but a variables can never be declared strictfp.

Methods with var-args

  • As of Java 5, methods can declare a parameter that accepts from zero to many arguments, a so-called var-arg method.
  • A var-arg parameter is declared with the syntax: type... name;
  • A var-arg method can have only one var-arg parameter.
  • In methods with normal parameters and a var-arg, the var-arg must come last.

Return Types

  • We can return null in a method with an object reference return type.
  • class A {
        A func() {
            return null;
        }
    }
    • An array is a perfectly legal return type.
    class A {
        int[] func() {
            return new int[] { 1, 2, 3 };
        }
    }
  • In a method with a primitive return type, we can return any value or variable that can be implicitly converted to a declared type.
  • class A {
        int func() {
            char c = 'D';
            return c; // char is compatible with int
        }
    }
    • In a method with a primitive return type, we can return any value or variable that can be explicitly cast to the declared return type.
    class A {
        int func() {
            float var = 6.2F;
            return (int) var;
        }
    }
  • We must not return anything from a method with a void return type. But we're allowed to simply say return, in any method with a void return type, to bust out of a method early.
  • class A {
        void func() {
            return;
        }
    }
  • In a method with an object reference type, we can return any object type that can be implicitly cast to the declared return type.
  • class Animal {
    }

    class Dog extends Animal {
        Animal func() {
            return new Dog();
        }
    }
  • In a method with an object reference type, we can return any object type that can be explicitly cast to the declared return type.
  • class Animal {
    }

    class Dog extends Animal {
        Dog func() {
            return (Dog) new Animal();
        }
    }

Passing Variables into Methods

  • Methods can be declared to take primitives and/or object references.
  • Java is actually pass-by-value for all variables running within a single VM.
  • It makes no difference if we're passing primitive or reference variables, we are always passing a copy of the bits in the variable.
  • The called method can't change the caller's variable, although for object reference variables, the called method can change the object the variable is referred to.
  • Shadowing occurs when two variables with different scopes share the same name.

Passing Object Reference Variable

Both the caller and the caller method will have identical copies of the reference, and thus both will refer to the same exact (not a copy) object on the heap.

import java.awt.Dimension;

class ShellClass {
    public static void main(String[] args) {
        Dimension sq = new Dimension(10, 10);
        System.out.println("Before modify(): " + sq);
        modify(sq);
        System.out.println("After modify(): " + sq);
    }

    static void modify(Dimension shape) {
        shape.height++;
        shape.width++;
        System.out.println("Height: " + shape.getHeight() + "\tWeight: " + shape.getWidth());
    }
}

Passing Primitive Variables

When a primitive variable is passed to a method, it is passed by value, which means pass-by-copy-of-the-bits in the variable.

class ShellClass {
    public static void main(String[] args) {
        int a = 10;
        System.out.println("Before modify(): " + a);
        modify(a);
        System.out.println("After modify(): " + a);
    }

    static void modify(int a) {
        a++;
        System.out.println("a: " + a);
    }
}

Prev Next

Comments