Java Methods
A method is a block of code defined inside a class that performs a specific operation or behaviour. We use methods mainly to reuse logic, avoid code duplication, and keep the code modular and maintainable.
A method can have parameters, a return type, and an access modifier like public, protected, or private. It can be an instance method or a static method. Methods can also be overloaded, and in inheritance they can be overridden to achieve runtime polymorphism.
Get Omkar Bhavare’s stories in your inbox
Join Medium for free to get updates from this writer.
For example, public int add(int a, int b) has public as the access modifier, int as the return type, add as the method name, and a and b as parameters.
1. Method Signature & Overloading
What is a method signature in Java?
“So basically, a method signature in Java consists of the method name and the parameter list — meaning the number, type, and order of parameters.
For method overloading, Java uses the method name and parameter list to determine whether two methods are different. The return type, access modifier,
static,final, and parameter names are not part of the method signature.For example,
add(int, int)andadd(double, double)have different signatures, so they can be overloaded. Butadd(int, int)with only a different return type is not valid overloading.
Can two methods have the same name and parameters but different return types?
No, Java does not allow this as method overloading. If two methods have the same method name and same parameter list, Java considers them the same method signature. The return type is not part of the method signature, so changing only the return type doesn’t create a new method.
The reason is that when we call a method, Java identifies the method using the method name and arguments, not the return type. For example, if both
add(int, int)returnintanddouble, the calladd(10, 20)would be ambiguous from the method-selection point of view.
int add(int a, int b) {
return a + b;
}
double add(int a, int b) { // ❌ Compile-time error
return a + b;
}Can methods be overloaded by changing only parameter names, access modifiers, static, final, or return type?
No. For method overloading, the parameter list must be different. That means we need to change the number, type, or order of parameters.
Just changing the parameter name, access modifier,
static,final, or return type is not enough because these are not part of the method signature.For example,
staticchanges the method from an instance method to a class-level method, andfinalprevents overriding. Similarly,publicandprivatecontrol accessibility, while the return type defines what the method returns. But none of these changes the method signature.
1. METHOD OVERLOADING
---------------------
Method overloading means:
- Same method name
- Different parameter list
- Usually happens inside the same class
- Return type / Access Modifier CANNOT create overloading
void add(int a, int b) {}
void add(int x, int y) {} // ❌ Not overloaded
void m1(int a) {}
public void m1(int a) { } // ❌ Not overloaded
void m2(){}
void m2(int a){} // over loadedCan a method be overloaded by changing parameter types, parameter count, or parameter order?
“Yes, these are the three main ways we create method overloading in Java. The method name remains the same, but the parameter list changes.
1. Different parameter type:
void add(int a) {}
void add(double a) {} // ✅
2. Different parameter count:
void add(int a) {}
void add(int a, int b) {} // ✅
3. Different parameter order:
void add(int a, double b) {}
void add(double a, int b) {} // ✅Can main() be overloaded, and if yes, which main() method will JVM execute?
“Yes,
main()can be overloaded because it is a normal static method, so we can create multiplemain()methods with different parameter lists.But the
main(String[] args)method is the entry point and JVM executes that method first. [ Basically, the JVM needs a predefined method signature to know where the Java application should start execution. By Java specification, the launcher looks for apublic static mainmethod with aString[]parameter.]The overloaded
main(int)will execute only when we explicitly call it from the program.
class Main {
public static void main(String[] args) {
System.out.println("JVM main");
main(10);
}
public static void main(int number) {
System.out.println("Overloaded main");
}
}When multiple overloaded methods are available, how does Java decide which method to call?
“Basically, Java decides which overloaded method to call at compile time, based on the arguments we pass. It looks at the method name and tries to find the most specific applicable parameter list.
If an exact match is not available, Java can consider widening conversions, boxing/unboxing, and then varargs according to overload-resolution rules.
void test(int x) {
System.out.println("int");
}
void test(double x) {
System.out.println("double");
}
test(10);
void test1(long x) {
System.out.println("long");
}
void test1(double x) {
System.out.println("double");
}
test1(10); // test1(long)If overloaded methods involve exact match, widening, boxing/unboxing, and varargs, which one gets priority?
“Java generally chooses the least costly conversion for the arguments. So the priority is:
1. Exact match → 2. Widening → 3. Boxing/Unboxing → 4. Varargs
void test(int x) {
System.out.println("int");
}
void test(long x) {
System.out.println("long");
}
void test(Integer x) {
System.out.println("Integer");
}
void test(int... x) {
System.out.println("varargs");
}
test(10);What happens when overloaded methods become ambiguous?
Basically, when Java finds multiple overloaded methods that are equally applicable and cannot decide which one is more specific, it gives a compile-time error called an ambiguous method call.
For example, if one method needs widening on the first argument and another method needs widening on the second argument, both methods may be equally valid. Java cannot prefer either one.
void test(int a, double b) {
System.out.println("int, double");
}
void test(double a, int b) {
System.out.println("double, int");
}
test(10, 10);
Here 10 is an int. Java can widen either argument:
test(int, double) → second int → double
test(double, int) → first int → double
Both methods require the same level of conversion, so Java cannot decide which one is better.
Therefore:
❌ Compile-time error: reference to test is ambiguous
We can resolve it by making the call more specific, for example:
test(10, 10.0); // calls test(int, double)How does Java choose between byte, short, int, long, Integer, Number, Object, and varargs?
“Java resolves overloaded methods in phases. It first tries to find a method without boxing or varargs. So if an exact primitive match is available, that gets priority. If there is no exact match, Java can use primitive widening. Only after that does it consider boxing and reference widening, and finally varargs.
Note: In Java Integer literals are
intby default. Java doesn’t automatically select the smallest data type based on the value. Therefore, test(10)selects theintoverload as an exact match.
void test(byte x) { System.out.println("byte"); }
void test(short x) { System.out.println("short"); }
void test(int x) { System.out.println("int"); }
void test(long x) { System.out.println("long"); }
void test(Integer x) { System.out.println("Integer"); }
void test(Number x) { System.out.println("Number"); }
void test(Object x) { System.out.println("Object"); }
void test(int... x) { System.out.println("varargs"); }
test(10); // int
// If test(int) is removed: test(long) is selected because widening is considered before boxing.Can autoboxing/unboxing and widening together affect overloaded method selection?
Yes. Autoboxing, unboxing, and widening can affect overload resolution, but Java follows specific conversion phases. Java first prefers methods that can be called without boxing/unboxing, and only then considers boxing or unboxing.
void test(long x) {
System.out.println("long");
}
void test(Integer x) {
System.out.println("Integer");
}
Integer value = 10;
test(value); // Integer
because it doesn't need unboxing and widening.
=============================================================================
void test1(long x) {
System.out.println("long");
}
void test1(Integer x) {
System.out.println("Integer");
}
test1(10); // long Java considers widening before boxing, so test(long) is selected.
Java can use:
int → long // primitive widening
int → Integer // boxingWhat is the difference between method overloading and method overriding, and when does each happen?
“Basically, overloading means having multiple methods with the same name but a different parameter list, usually within the same class. Java decides which overloaded method to call at compile time, based on the arguments passed.
Overriding happens when a child class provides its own implementation of a parent class method with the same method signature. The actual method to execute is decided at runtime, based on the actual object.
class Calculator {
void add(int a, int b) {}
void add(double a, double b) {} // Overloading
double add(double a, double b) {} // Compile time Error
}
=================================================================
class Animal {
void sound() {
System.out.println("Animal");
}
}
class Dog extends Animal {
@Override
void sound() { // Overriding
System.out.println("Dog");
}
}
Animal a = new Dog();
a.sound(); // DogCan a method call involve both overloading and overriding?
Yes. This can happen when we have inheritance plus overloaded methods. Java basically works in two steps: first, the compiler selects the overloaded method using the reference type and compile-time argument types. Then, at runtime, if that selected method is overridden, Java chooses the implementation based on the actual object type.
class Parent {
void test(int x) {
System.out.println("Parent int");
}
void test(String x) {
System.out.println("Parent String");
}
}
class Child extends Parent {
@Override
void test(int x) {
System.out.println("Child int");
}
}
Parent p = new Child();
p.test(10);
First, overloading is resolved at compile time:
p.test(10)
↓
argument = int
↓
test(int) selected
Then overriding is resolved at runtime:
actual object = Child
↓
Child.test(int)
↓
"Child int"
So the flow is:
Compile time → select overloaded method → Runtime → select overridden implementationCan an overriding method change the return type, and what is a covariant return type?
Yes, an overriding method can change its return type, but only under a specific rule. The return type can be covariant, which means the child method can return a subtype of the parent’s return type.
Can an overriding method change the access modifier?
An overriding method cannot reduce the parent method’s visibility because the child object should be usable wherever the parent object is expected. If the child reduces the access, code that could access the parent method may no longer be able to access the child method. This breaks substitutability and violates the parent class contract.
If the parent method is public, any caller can use it. If the child changes it to protected, that caller loses access when working with the child object. That is why Java does not allow reducing visibility.
Reducing visibility would break the parent contract. This would break polymorphism and the Liskov Substitution Principle (LSP).
class Parent {
protected void show() {
System.out.println("Parent");
}
}
class Child1 extends Parent {
@Override
public void show() { // ✅ visibility increased
System.out.println("Child");
}
}
class Child2 extends Parent {
@Override
private void show() { // ❌ cannot reduce visibility
}
}
protected → public
is allowed because public is more accessible.
Public>protected>pCan an overriding method change the throws clause?
Yes, an overriding method can change the
throwsclause, but there are rules, especially for checked exceptions.
For checked exceptions, the child method cannot throw a new or broader checked exception than the parent method. It can throw the same exception, a narrower subclass, or no exception at all.
class Parent {
void read() throws IOException {
System.out.println("Parent");
}
}
class Child1 extends Parent {
@Override
void read() throws FileNotFoundException { // ✅ narrower exception
System.out.println("Child");
}
}
// Here FileNotFoundException is a subclass of IOException, so it is allowed.
class Child2 extends Parent { //
@Override
void read() { // ✅ no checked exception.We can also remove the exception
System.out.println("Child");
}
}
class Child3 extends Parent {
@Override
void read() throws IOException { ✅ // Same Exception is also fine
System.out.println("Child");
}
}
class Child4 extends Parent {
@Override
void read() throws Exception { // ❌ broader checked exception
}
}Can a child method have a different parameter list and still be considered overriding?
No. For method overriding, the child method must have the same method signature as the parent method — meaning the same method name and the same parameter types in the same order.
If the parameter list changes, Java treats it as a different method, so it becomes method overloading, not overriding.
Can constructors be overridden, and why?
No, constructors cannot be overridden. Overriding requires inheritance and a method with the same signature, but constructors are not inherited by the child class.
A constructor is specifically used to initialize an object of its own class, and it has the same name as the class with no return type.
Can static, final, and private methods be overridden, and how does Java treat each one?
No,
static,final, andprivatemethods cannot be overridden, but Java treats each differently.
finalmethod: A final method cannot be overridden becausefinalexplicitly tells Java that the method's implementation must not be changed by subclasses
class Parent {
final void show() {}
}
class Child extends Parent {
// void show() {} // ❌ Cannot override final method
}
staticmethod: Cannot be overridden because static methods belong to the class, not the object. If the child defines a static method with the same signature, it is called method hiding, not overriding.
class Parent {
static void show() {
System.out.println("Parent");
}
}
class Child extends Parent {
static void show() {
System.out.println("Child");
}
}
Parent p = new Child();
p.show(); // Parent
privatemethod: private method is not inherited by the child class, so it cannot be overridden. If the child declares a method with the same name and parameters, it is simply a new, unrelated seperated method.
class Parent {
private void show() {}
}
class Child extends Parent {
private void show() {} // ✅ New method, not overriding
}If parent and child classes have the same static method, which one executes?
Static methods are resolved based on the reference type, not the actual object type. Therefore, the method belonging to the reference type executes.
It depends on the reference type, because static methods are resolved at compile time.
If the reference is
Parent, the Parent static method executes.If the reference is
Child, the Child static method executes.This is called method hiding, not method overriding.
class Parent {
static void show() {
System.out.println("Parent");
}
}
class Child extends Parent {
static void show() {
System.out.println("Child");
}
}
Parent p = new Child();
p.show(); // Parent
Child c = new Child();
c.show(); // ChildWhat is method hiding, and how is it different from method overriding?
Basically, method hiding happens when a child class declares a
staticmethod with the same signature as astaticmethod in the parent class. Since static methods belong to the class, Java doesn't use runtime polymorphism for them. The method is selected based on the reference type at compile time.Method overriding, on the other hand, happens with instance methods. The child provides its own implementation of the parent’s method, and Java selects the implementation at runtime based on the actual object.
class Parent {
static void show() {
System.out.println("Parent static");
}
static void m1() {
System.out.println("Parent M1 static");
}
void display() {
System.out.println("Parent instance");
}
}
class Child extends Parent {
static void show() {
System.out.println("Child static"); // Method hiding
}
void m1() { // ❌ Compilation Error It method should be static if in parent it is mentioned as static
System.out.println("Child M1 static"); //
}
@Override
void display() {
System.out.println("Child instance"); // Method overriding
}
}
Parent p = new Child();
p.show(); // Parent static
p.display(); // Child instanceCan static, final, and private methods still be overloaded?
Yes.
static,final, andprivatemethods can all be overloaded. The important thing is that overloading depends only on having the same method name with a different parameter list. These keywords affect other aspects of the method, but they don't prevent overloading.
Why can’t a method be abstract with final, private, or static?
An abstract method requires a subclass implementation.
finalprevents overriding,privateprevents inheritance, andstaticdoesn't participate in runtime overriding. Since each conflicts with the purpose of an abstract method, Java doesn't allow these combinations.










