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 are not methods. But they are quite similar. And there are different kinds of them so I try to list some of them.
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.
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.
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.
For a robust design each method should be final or abstract/empty. This prevents the fragile base class problem.
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.
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.
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).
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”.)
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.).
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
A method without the static keyword is per instance. Only non-static methods can use
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).
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
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.
Any method that returns
this is chainable. This is used in the builder pattern (for example StringBuilder, which is a builder for Strings).
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.
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
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.
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.
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)
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.
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).