Types of Methods in Java

So in Java there are many kinds of methods. I probably won’t even list half of them but I try to explain how different methods can be.

Note: A method can be static and functional and final. So the following types of methods are not mutually exclusive.

Constructors

Constructors are not methods. But they are quite similar. And there are different kinds of them so I try to list some of them.

Copy Constructor

Takes an instance of the same type and creates a new object that is equal. This usually takes the values of all fields and copies them to the new instance. Note that a factory could do the same.

Default Constructor

This has nothing to do with the default keyword. It  can be called with no arguments and therefore is also known as a no-args constructor. This is often necessary so that a framework can create an object and then set it up by using setters.

Conversion Constructors

Used to convert one type to another. So this takes some object and then copies all data. The created object is mostly equal, but of different structure.

Methods

For a robust design each method should be final or abstract/empty. This prevents the fragile base class problem.

Final Methods

They can’t be overridden or hidden. The implementation of this method is fixed. This could be a “template method” that invokes empty/abstract methods in a certain order. Many methods in predefined classes of the Java library should be final, but are not. All methods used to change a collection (add, put, set) should be final because there would be no reason for a subclass to change that behaviour.

Overloaded Methods

Two names with the same name in the same class (or related classes) are overloaded. Parameters and return type can be completely different. The compiler decides which method to use, so at runtime they are completely distinct methods. Constructors work like overloads too.

Empty/abstract Methods

Some methods are only declared but not implemented. They can be abstract, having no implementation at all, or empty. Subclasses can (if empty) or must (if abstract) override and implement them to make a complete (not abstract) class.

Getter and Setter

A getter returns the value (or a copy of it) of some internal field. Getters start with “get” or “is”. Setters the the opposite: They assign a new value (or a copy of it) to some internal field. The name of a setter always starts with “set”. Indexed getters and setters take an additional parameter for the index and the field is an array or indexed collection (i.e. List).

Record Field Accessor Methods

Since Java 14 we have records. For each field you automatically get an accessor method. You don’t write any code to get that. It’s like a getter, but for some reason they don’t use the getFieldName() schema. Since records are immutable anyway it’s usually ok to just use the generated method.

Sythetic Accessor Methods

Like the automatically generated accessors for record fields you also get them for private fields so that nested types can get access. However, many style guides would argue that this should not be used and instead you should write your own method in this case.

Setter for “Behavioural Object”

This kind of methods accepts some lambda or object that works as a “strategy”. This allows to change the behaviour at runtime. (See “strategy pattern” and “composition over inheritance”.)

Delegate Methods

The method call is forwarded to a method of the same name of some inner object. This is used in all design patterns that use this kind of composition (wrapper, proxy, decorator, adapter etc.).

Default Methods

Since Java 8 the keyword “default” can be used on methods in interfaces, that have a default implementation. But a class could also have some “default” method. This means that there is a non-empty, non-final implementation. They define a simple (often naive) implementation, that is built on other (non-default) methods but invoke them in some specific way (using default parameter values, invoke multiple times, map result to some other form etc.). In an interface you’d actually use “default” as a keyword. In a class you’d explain this in the javadoc. So a subclass can override this method with an optimized implementation, but doesn’t have to. Such methods should not be used internally (invoked as this.somedefaultMethod()).

Non-static Methods

A method without the static keyword is per instance. Only non-static methods can use super and this.

Overriding Methods

A method can override another method. This happens when the same method exists in a superclass or interface. Such methods should be annotated with @java.lang.Override. Any method that overrides another method should do exactly what the supertype(s) specify in the javadoc. If a method is already implemented in a superclass is is even more important to do the exact same (not more, not less).

Static Methods

A static method is per class. They can be overloaded, but should not be hidden. To prevent anyone to hide a static method in a subclass by some other static method of the same name, you can make it a final static method. generally speaking it’s better to make a method static if that is possible (if it does not use this). However, a static method foo(SomeType) should be implemented directly as non-static SomeType.foo().

Hidden and hiding Methods

A static method in a subclass is hiding if a superclass (or interface) has a static method with the same name. Hidden methods can still be invoked by using the fully qualified name, but multiple methods with the same name are confusing. The final keyword can be used to prohibit hiding methods.

Chainable Methods

Any method that returns this is chainable. This is used in the builder pattern (for example StringBuilder, which is a builder for Strings).

Blocking Methods

A method is blocking if blocks the executing thread until there operation is finished. Then it returns a result or just returns (void) or an exception is thrown. This is the opposite of an asynchronous method.

Asynchronous Methods

A method is asynchronous if it returns before the operation is completed. Note that a method itself could be blocking but it is invoked in some asynchronous way  (asynchronous method call). The invocation then doesn’t block the calling thread while waiting for a result. Instead the result might be processed at a later time or in another thread. In Java a method could create a new thread or pass the work unit to an thread pool. There’s no async keyword in Java as there is in C#, but you can use the predefined methods in CompletableFuture, such as runAsync(Runnable) and supplyAsync(Supplier<U>).

Functions

In Java there are methods that can be considered to be functions (as defined in mathematics) and then there are interfaces that are annotated as @FunctionalInterface, containing a single abstract method. And then there are higher order functions. See this blog entry about functions: Functions in Java

Non-static methods aren’t strictly functions because they depend on the state of an object that might change. If the type is immutable then the getters and other side-effect-free methods (see below) can be seen as a functions. But Java isn’t functional, so it’s never clear what really qualifies as a function.

Higher-order Functions

If some function takes one or more parameters that are functions or it returns another function then it is a higher order function. Simple as that, but not very common in Java.

Single abstract Methods

Sometimes shortened as “SAM”. That one single method abstract in a functional interface. Only one single method is abstract. There can be more methods, but they can not be abstract.  So the actual code block of a lambda is the implementation of the SAM.

Idempotent Methods

Sometimes it is good to know that invoking some method twice doesn’t do any harm. For example it is desirable that any method used to close something should do nothing if the resource is already closed. A more formal definition (for functions) is this:

f(f(x)) = f(x)

Side-effect-free Methods

A method without any side-effects only returns something, but does not alter any state. For obvious reasons they can’t be void. Most getters are side-effect-free, setters are not. Static methods without side-effects are functions (see above) as they only use the input (all parameters) to get the result, but do not change anything. Most methods in java.lang.Math (abs, atan, cos, round etc.) are side-effect-free/functions.

Design Patterns

Some design patterns are about methods:

  • Template method pattern
  • Factory method pattern
  • Strategy pattern

And probably a lot more. And then there are the mentioned method chaining and higher order functions (both not really patterns).

2 thoughts on “Types of Methods in Java”

Leave a Reply

Your email address will not be published. Required fields are marked *