Java Tutorial
🔍

Defining Methods in Java

Defining Methods in Java

A method is a named block of code that performs a specific task. You write it once, call it anywhere the task is needed, and the program jumps to that block, runs it, and returns to where it left off. Every Java program of any practical size is a collection of methods calling other methods.

Understanding how to define methods correctly is not just about syntax — it is about designing code that is readable, reusable, and maintainable. A method that does one thing clearly is worth ten times more than a method that does five things ambiguously.

Anatomy of a Method Definition

A Java method has six parts. Each one communicates something specific to the compiler, the JVM, and the developer reading the code.

access modifier   return type   method name   parameters
      |               |              |              |
   public           double       calculateGst ( double amount )
      |
  [ static ]         — optional — makes it a class-level method
  [ final  ]         — optional — prevents overriding in subclasses
      {
          // method body
          return amount * 0.18;  ← return statement (required if return type != void)
      }

Every part has a purpose:

  • Access modifier — who can call this method
  • Return type — what the method gives back (or void if nothing)
  • Method name — how callers refer to it — camelCase by convention
  • Parameters — what inputs the method receives — zero or more, comma-separated
  • Method body — the code that runs when the method is called
  • Return statement — the value handed back to the caller

Simplest Possible Method

Java
1// File: MethodBasics.java 2 3public class MethodBasics { 4 5 // A method that takes no input and returns nothing 6 public void printWelcome() { 7 System.out.println("Welcome to DevStackFlow!"); 8 } 9 10 // A method that takes input and returns nothing 11 public void greet(String name) { 12 System.out.println("Hello, " + name + "!"); 13 } 14 15 // A method that takes input and returns a value 16 public int add(int a, int b) { 17 return a + b; 18 } 19 20 // A method that returns a value with no parameters 21 public String getVersion() { 22 return "v2.1.0"; 23 } 24 25 public static void main(String[] args) { 26 27 MethodBasics mb = new MethodBasics(); 28 29 mb.printWelcome(); 30 mb.greet("Priya"); 31 System.out.println("Sum: " + mb.add(15, 27)); 32 System.out.println("Version: " + mb.getVersion()); 33 } 34}
Output:
Welcome to DevStackFlow!
Hello, Priya!
Sum: 42
Version: v2.1.0

Each method does exactly one thing. The name describes what it does. The return type tells callers what to expect. The parameters tell callers what to provide. Everything a caller needs to know about a method is visible from its signature — the body is an implementation detail.

Access Modifiers on Methods

The access modifier controls where the method can be called from. Choosing the right modifier is part of encapsulation — exposing only what the outside world needs and hiding everything else.

ModifierAccessible FromWhen to Use
publicAnywhere — same package, different package, subclassesAPI methods, service layer, anything callers need
protectedSame package + subclasses in other packagesMethods subclasses should be able to override or reuse
package-private (no keyword)Same package onlyInternal utility methods not meant to leave the package
privateSame class onlyHelper methods, implementation details
Java
1// File: AccessModifierDemo.java 2 3public class AccessModifierDemo { 4 5 // Public — any class anywhere can call this 6 public double calculateTotal(double price, int quantity) { 7 double subtotal = multiply(price, quantity); // calls private helper 8 return applyDiscount(subtotal); // calls private helper 9 } 10 11 // Private — only this class can call it 12 // Hides the multiplication detail — callers do not need to know about it 13 private double multiply(double price, int quantity) { 14 return price * quantity; 15 } 16 17 // Private — internal business rule, not part of public contract 18 private double applyDiscount(double amount) { 19 return amount > 5000 ? amount * 0.95 : amount; 20 } 21 22 // Protected — subclasses can override or reuse for custom discount rules 23 protected double getDiscountRate(double amount) { 24 return amount > 5000 ? 0.05 : 0.0; 25 } 26 27 public static void main(String[] args) { 28 AccessModifierDemo demo = new AccessModifierDemo(); 29 System.out.println("Total (2 items at Rs.1500): Rs." + demo.calculateTotal(1500.0, 2)); 30 System.out.println("Total (4 items at Rs.1500): Rs." + demo.calculateTotal(1500.0, 4)); 31 } 32}
Output:
Total (2 items at Rs.1500): Rs.3000.0
Total (4 items at Rs.1500): Rs.5700.0

calculateTotal is the public face of this class. multiply and applyDiscount are implementation details — making them private means they can change tomorrow without breaking any caller. getDiscountRate is protected so subclasses can override the discount logic without duplicating the entire calculateTotal method.

Return Types — Every Possibility

The return type tells the compiler what the method will hand back. It can be any primitive, any reference type, an array, or void.

Java
1// File: ReturnTypeDemo.java 2 3import java.util.List; 4import java.util.ArrayList; 5 6public class ReturnTypeDemo { 7 8 // Returns a primitive int 9 public int countDigits(int number) { 10 return String.valueOf(Math.abs(number)).length(); 11 } 12 13 // Returns a primitive boolean 14 public boolean isEligibleForLoan(double monthlyIncome, double existingEmi) { 15 double emiToIncomeRatio = existingEmi / monthlyIncome; 16 return emiToIncomeRatio < 0.50; // standard banking rule — EMI must be under 50% of income 17 } 18 19 // Returns a String 20 public String formatCurrency(double amount) { 21 return String.format("Rs.%,.2f", amount); 22 } 23 24 // Returns a reference type (object) 25 public StringBuilder buildReport(String title, String content) { 26 return new StringBuilder() 27 .append("=== ").append(title).append(" ===\n") 28 .append(content); 29 } 30 31 // Returns a List 32 public List<String> getFilteredItems(List<String> items, String prefix) { 33 List<String> result = new ArrayList<>(); 34 for (String item : items) { 35 if (item.startsWith(prefix)) { 36 result.add(item); 37 } 38 } 39 return result; 40 } 41 42 // Returns void — performs an action, hands nothing back 43 public void logMessage(String level, String message) { 44 System.out.println("[" + level + "] " + message); 45 } 46 47 // Returns an array 48 public int[] generateRange(int start, int end) { 49 int[] range = new int[end - start + 1]; 50 for (int i = 0; i < range.length; i++) { 51 range[i] = start + i; 52 } 53 return range; 54 } 55 56 public static void main(String[] args) { 57 58 ReturnTypeDemo demo = new ReturnTypeDemo(); 59 60 System.out.println("Digits in 4821 : " + demo.countDigits(4821)); 61 System.out.println("Loan eligible : " + demo.isEligibleForLoan(80000, 25000)); 62 System.out.println("Formatted : " + demo.formatCurrency(1250000.75)); 63 64 List<String> products = List.of("Laptop", "LED TV", "Lamp", "Mouse", "Monitor"); 65 System.out.println("L-prefix items : " + demo.getFilteredItems(products, "L")); 66 67 demo.logMessage("INFO", "Application started"); 68 69 int[] range = demo.generateRange(1, 5); 70 System.out.print("Range : "); 71 for (int n : range) System.out.print(n + " "); 72 System.out.println(); 73 } 74}
Output:
Digits in 4821  : 4
Loan eligible   : true
Formatted       : Rs.12,50,000.75
L-prefix items  : [Laptop, LED TV, Lamp]
INFO Application started
Range           : 1 2 3 4 5

A method that returns void still does useful work — it performs side effects like printing, writing to a file, or updating state. A method that returns a value is expected to compute and deliver that value without side effects unless the name explicitly signals otherwise.

Static Methods vs Instance Methods

This is the distinction that trips up most beginners, and the one that comes up most in interviews.

A static method belongs to the class. It exists without any object being created. It cannot access instance fields or call instance methods directly. It is called using the class name.

An instance method belongs to an object. It requires an object to exist before it can be called. It can access instance fields and call other instance methods freely. It is called using an object reference.

Java
1// File: StaticVsInstanceDemo.java 2 3public class StaticVsInstanceDemo { 4 5 // Instance field — belongs to each object 6 private String merchantName; 7 private double totalRevenue; 8 9 public StaticVsInstanceDemo(String merchantName) { 10 this.merchantName = merchantName; 11 this.totalRevenue = 0.0; 12 } 13 14 // Static method — utility, no object needed, no instance state used 15 public static double calculateGst(double amount, double rate) { 16 return amount * rate; 17 } 18 19 // Static method — validates input before any object is created 20 public static boolean isValidMerchantId(String merchantId) { 21 return merchantId != null 22 && merchantId.startsWith("MID-") 23 && merchantId.length() == 10; 24 } 25 26 // Instance method — works with this specific object's state 27 public void recordSale(double saleAmount) { 28 totalRevenue += saleAmount; 29 System.out.println(merchantName + " recorded sale: Rs." + saleAmount 30 + " | Total: Rs." + totalRevenue); 31 } 32 33 // Instance method — reads this object's state 34 public String getSummary() { 35 return "Merchant: " + merchantName + " | Revenue: Rs." + totalRevenue; 36 } 37 38 public static void main(String[] args) { 39 40 // Static method — called on the class, no object needed 41 double gst = StaticVsInstanceDemo.calculateGst(10000.0, 0.18); 42 System.out.println("GST on Rs.10000: Rs." + gst); 43 44 boolean valid = StaticVsInstanceDemo.isValidMerchantId("MID-1234567"); 45 System.out.println("Valid merchant ID: " + valid); 46 47 System.out.println(); 48 49 // Instance methods — called on specific objects 50 StaticVsInstanceDemo merchant1 = new StaticVsInstanceDemo("Sneha Stores"); 51 StaticVsInstanceDemo merchant2 = new StaticVsInstanceDemo("Ravi Electronics"); 52 53 merchant1.recordSale(4500.0); 54 merchant1.recordSale(8200.0); 55 merchant2.recordSale(15000.0); 56 57 System.out.println(merchant1.getSummary()); 58 System.out.println(merchant2.getSummary()); 59 } 60}
Output:
GST on Rs.10000: Rs.1800.0
Valid merchant ID: false

Sneha Stores recorded sale: Rs.4500.0 | Total: Rs.4500.0
Sneha Stores recorded sale: Rs.8200.0 | Total: Rs.12700.0
Ravi Electronics recorded sale: Rs.15000.0 | Total: Rs.15000.0
Merchant: Sneha Stores | Revenue: Rs.12700.0
Merchant: Ravi Electronics | Revenue: Rs.15000.0

calculateGst and isValidMerchantId do not need any merchant's state to work — they are pure calculations or validations on their inputs. Making them static communicates this intent clearly. recordSale and getSummary operate on a specific merchant's revenue — they must be instance methods.

Static vs Instance Methods — Comparison Table

AspectStatic MethodInstance Method
Belongs toThe classA specific object
Called viaClass name: ClassName.method()Object reference: obj.method()
Requires objectNoYes — object must exist
Can access instance fieldsNoYes
Can call instance methodsNo — directlyYes
Can access static fieldsYesYes
Can call static methodsYesYes
MemoryLoaded once with classDispatched per object
this keyword availableNoYes
OverridableNo — method hiding onlyYes — true polymorphism
When to useUtilities, factories, validators, constants-based logicBehaviour that depends on object state
ExamplesMath.sqrt(), Collections.sort()list.add(), map.get()

The void Return Type and Returning Early

void methods still use return — without a value — to exit early when a condition is met. This avoids deep nesting and makes the control flow easier to follow.

Java
1// File: VoidMethodDemo.java 2 3public class VoidMethodDemo { 4 5 // Guard clauses — return early on invalid input rather than nesting 6 public void processRefund(String orderId, double amount) { 7 8 if (orderId == null || orderId.isBlank()) { 9 System.out.println("[REFUND] Rejected: order ID is required."); 10 return; // exit early — no further processing 11 } 12 13 if (amount <= 0) { 14 System.out.println("[REFUND] Rejected: amount must be positive."); 15 return; 16 } 17 18 if (amount > 100000) { 19 System.out.println("[REFUND] Rejected: amount exceeds single-refund limit."); 20 return; 21 } 22 23 // Only reach here if all guards pass 24 System.out.println("[REFUND] Approved: " + orderId + " | Rs." + amount); 25 } 26 27 public static void main(String[] args) { 28 29 VoidMethodDemo demo = new VoidMethodDemo(); 30 31 demo.processRefund("", 500.0); 32 demo.processRefund("ORD-001", -100.0); 33 demo.processRefund("ORD-002", 150000.0); 34 demo.processRefund("ORD-003", 2499.0); 35 } 36}
Output:
[REFUND] Rejected: order ID is required.
[REFUND] Rejected: amount must be positive.
[REFUND] Rejected: amount exceeds single-refund limit.
[REFUND] Approved: ORD-003 | Rs.2499.0

Guard clauses — early returns — are a standard clean code practice. They keep the happy path at the left margin without nesting, and each failure reason is clearly stated at the top of the method.

Real-World Example — Ride Fare Calculation Service

The Business Problem

A ride-hailing platform like Ola or Rapido calculates fares based on distance, time, surge pricing, and vehicle category. Each calculation step is a separate method — short, named, and testable. The service class composes them into a complete fare estimate. No single method does more than one job.

Java
1// File: FareConfig.java 2 3public final class FareConfig { 4 5 // Base rates per km by vehicle type (Rs. per km) 6 public static final double RATE_BIKE = 8.0; 7 public static final double RATE_AUTO = 12.0; 8 public static final double RATE_MINI_CAB = 14.0; 9 public static final double RATE_SEDAN_CAB = 18.0; 10 11 // Minimum fares 12 public static final double MIN_FARE_BIKE = 30.0; 13 public static final double MIN_FARE_AUTO = 40.0; 14 public static final double MIN_FARE_CAB = 60.0; 15 16 // Surge threshold 17 public static final double PEAK_HOURS_SURGE = 1.25; // 25% surge 18 19 private FareConfig() {} // utility class — no instantiation 20}
Java
1// File: FareCalculatorService.java 2 3public class FareCalculatorService { 4 5 // Static — pure calculation, no state needed 6 public static double getBaseRate(String vehicleType) { 7 return switch (vehicleType.toUpperCase()) { 8 case "BIKE" -> FareConfig.RATE_BIKE; 9 case "AUTO" -> FareConfig.RATE_AUTO; 10 case "MINI" -> FareConfig.RATE_MINI_CAB; 11 case "SEDAN" -> FareConfig.RATE_SEDAN_CAB; 12 default -> throw new IllegalArgumentException( 13 "Unknown vehicle type: " + vehicleType); 14 }; 15 } 16 17 // Static — pure calculation 18 public static double getMinimumFare(String vehicleType) { 19 return switch (vehicleType.toUpperCase()) { 20 case "BIKE" -> FareConfig.MIN_FARE_BIKE; 21 case "AUTO" -> FareConfig.MIN_FARE_AUTO; 22 case "MINI", 23 "SEDAN" -> FareConfig.MIN_FARE_CAB; 24 default -> throw new IllegalArgumentException( 25 "Unknown vehicle type: " + vehicleType); 26 }; 27 } 28 29 // Static — validates inputs before fare calculation 30 public static boolean isValidRideRequest(double distanceKm, String vehicleType) { 31 if (distanceKm <= 0) return false; 32 if (vehicleType == null || vehicleType.isBlank()) return false; 33 return switch (vehicleType.toUpperCase()) { 34 case "BIKE", "AUTO", "MINI", "SEDAN" -> true; 35 default -> false; 36 }; 37 } 38 39 // Static — applies surge pricing 40 public static double applySurge(double fare, boolean isPeakHour) { 41 return isPeakHour ? fare * FareConfig.PEAK_HOURS_SURGE : fare; 42 } 43 44 // Static — rounds to nearest rupee 45 public static double roundFare(double fare) { 46 return Math.round(fare); 47 } 48 49 // Static — orchestrates all the above into a complete estimate 50 public static String estimateFare(double distanceKm, 51 String vehicleType, 52 boolean isPeakHour) { 53 54 if (!isValidRideRequest(distanceKm, vehicleType)) { 55 return "Invalid ride request."; 56 } 57 58 double baseRate = getBaseRate(vehicleType); 59 double rawFare = distanceKm * baseRate; 60 double minFare = getMinimumFare(vehicleType); 61 double fare = Math.max(rawFare, minFare); // apply minimum fare 62 double surged = applySurge(fare, isPeakHour); 63 double finalFare = roundFare(surged); 64 65 return String.format( 66 "%s | %.1f km | Peak: %s | Fare: Rs.%.0f", 67 vehicleType.toUpperCase(), distanceKm, 68 isPeakHour ? "Yes" : "No", finalFare); 69 } 70}
Java
1// File: RideFareDemo.java 2 3public class RideFareDemo { 4 5 public static void main(String[] args) { 6 7 System.out.println("=== Ride Fare Estimates ===\n"); 8 9 // Various combinations of vehicle type, distance, and peak hour 10 System.out.println(FareCalculatorService.estimateFare(12.5, "BIKE", false)); 11 System.out.println(FareCalculatorService.estimateFare(12.5, "BIKE", true)); 12 System.out.println(FareCalculatorService.estimateFare(8.0, "AUTO", false)); 13 System.out.println(FareCalculatorService.estimateFare(3.0, "MINI", false)); // under minimum 14 System.out.println(FareCalculatorService.estimateFare(15.0, "SEDAN", true)); 15 16 System.out.println(); 17 System.out.println("=== Validation ===\n"); 18 System.out.println(FareCalculatorService.estimateFare(-5.0, "BIKE", false)); // invalid distance 19 System.out.println(FareCalculatorService.estimateFare(10.0, "HELI", false)); // invalid type 20 System.out.println(FareCalculatorService.isValidRideRequest(10.0, "AUTO")); // true 21 } 22}
Output:
=== Ride Fare Estimates ===

BIKE  | 12.5 km | Peak: No  | Fare: Rs.100
BIKE  | 12.5 km | Peak: Yes | Fare: Rs.125
AUTO  | 8.0 km  | Peak: No  | Fare: Rs.96
MINI  | 3.0 km  | Peak: No  | Fare: Rs.60
SEDAN | 15.0 km | Peak: Yes | Fare: Rs.338

=== Validation ===

Invalid ride request.
Invalid ride request.
true

Every step of the fare calculation is a separate method with a clear name. getBaseRate, getMinimumFare, applySurge, and roundFare can each be tested independently. estimateFare composes them. Changing the surge multiplier or adding a new vehicle type touches exactly one method each — no cascading changes.

Best Practices

One method, one responsibility. A method that calculates a fare, logs the result, saves to the database, and sends a notification is four responsibilities crammed into one block. It becomes untestable, unreusable, and unmaintainable. Split it. Name each piece what it actually does.

Name methods with a verb. Method names should describe an action: calculateFare, validateInput, sendNotification, buildReport. A name like data() or process() tells the caller nothing. A name like fetchOrdersByCustomerId() tells the caller exactly what to expect.

Keep methods short — ideally under 20 lines. A method that requires scrolling to read usually does too much. If a method needs comments to explain what different blocks do, those blocks are methods waiting to be extracted. The comments become the method names.

Make methods private by default, widen only when needed. Start with private. Promote to package-private when a test in the same package needs it. Promote to protected when a subclass needs to override. Promote to public only when external callers genuinely need it. Widening visibility is easy; narrowing it after the fact breaks callers.

Common Mistakes

Mistake 1 — Missing return Statement in a Non-void Method

Java
1public double calculateDiscount(double price, String tier) { 2 if (tier.equals("GOLD")) { 3 return price * 0.20; 4 } 5 if (tier.equals("SILVER")) { 6 return price * 0.10; 7 } 8 // Compile error — what does this method return if tier is "BRONZE"? 9 // The compiler cannot guarantee a return in all paths 10}
Compile error: missing return statement

Every execution path through a non-void method must end with a return statement. Add a default return at the end, or handle the remaining cases explicitly.

Mistake 2 — Calling an Instance Method From a Static Context

Java
1public class PaymentService { 2 3 private double processingFee = 2.5; 4 5 public double getProcessingFee() { return processingFee; } 6 7 // Compile error — getProcessingFee() is an instance method 8 // static context has no object, no 'this', no instance state 9 public static void main(String[] args) { 10 System.out.println(getProcessingFee()); // error 11 } 12}
Compile error: non-static method getProcessingFee() cannot be referenced from a static context

main is static. It has no this. To call getProcessingFee(), create an instance first: new PaymentService().getProcessingFee(). This is the most common compile error beginners encounter.

Mistake 3 — Method Does Too Much (Violates Single Responsibility)

Java
1// Bad — one method does four unrelated things 2public void processOrder(String orderId, double amount) { 3 // Part 1: validate 4 if (orderId == null || amount <= 0) return; 5 6 // Part 2: calculate tax 7 double tax = amount * 0.18; 8 9 // Part 3: save to database 10 System.out.println("Saving to DB: " + orderId); 11 12 // Part 4: send email 13 System.out.println("Sending email for: " + orderId); 14} 15 16// Better — each method does one thing 17public boolean isValidOrder(String orderId, double amount) { ... } 18public double calculateTax(double amount) { ... } 19public void saveOrder(String orderId, double amount) { ... } 20public void sendConfirmationEmail(String orderId) { ... }

A method that does four things cannot be tested, reused, or maintained independently. A change to the email logic requires touching the same method as a change to the tax calculation. Extracting each concern into its own method solves all three problems at once.

Interview Questions

Q1. What are the components of a method definition in Java?

A method definition has six components: the access modifier (public, private, protected, or package-private), the optional static or final keyword, the return type (any type or void), the method name in camelCase, the parameter list in parentheses (zero or more typed parameters), and the method body in curly braces. The return type and method name together with the parameter list form the method signature, which must be unique within the class for non-overloaded methods.

Q2. What is the difference between a static method and an instance method?

A static method belongs to the class — it is called using the class name and can run without any object being created. It cannot access instance fields or call instance methods directly because there is no this reference. An instance method belongs to a specific object — it is called on an object reference and can access both instance fields and static members. Static methods are for utility operations, validators, and factory logic that do not depend on object state. Instance methods are for behaviour that reads or modifies an object's state.

Q3. What is a void return type and can a void method use the return statement?

void means the method does not return a value to its caller. A void method can still use the return keyword without a value — return; — to exit the method early. This is commonly used for guard clauses: checking preconditions at the top of the method and returning immediately if they fail, rather than nesting the rest of the logic inside if blocks.

Q4. What is the difference between method signature and method definition?

The method signature consists of the method name and the parameter list — types, count, and order. It does not include the return type or access modifiers. The method definition is the complete declaration including all modifiers, return type, name, parameters, and the method body. The signature is what the compiler uses to distinguish overloaded methods — two methods in the same class can have the same name only if their parameter lists differ.

Q5. Why does Java give a compile error when a non-void method has a path that returns nothing?

The compiler performs reachability analysis on every execution path through the method. If any path can reach the end of the method without hitting a return statement, the compiler reports a "missing return statement" error. This is a static safety check — the compiler cannot determine at compile time which if branches will execute, so it requires every possible path to end with a return. The fix is either a default return at the end of the method or ensuring every conditional branch explicitly returns.

Q6. When should a method be static versus instance in production code?

Use static when the method is a pure function of its inputs — it does not read or write any instance state. Utility methods, validators, formatters, calculators, and factory methods are typically static. Use instance methods when the behaviour depends on the object's state — the method reads fields, modifies fields, or calls other instance methods. A common indicator for static: if you can call the method without any context about a specific object, it belongs to the class. If the method's output changes based on which object it is called on, it belongs to the instance.

FAQs

Can a method in Java return multiple values?

Not directly — a method has a single return type. To return multiple values, wrap them in an object, a record, an array, or a collection. A common pattern is creating a small result class or using a Java 16+ record — record FareResult(double fare, String breakdown) — and returning an instance of it. Returning an array works for homogeneous values; returning a record or class works for heterogeneous ones.

Is the method name case-sensitive in Java?

Yes. calculateGst and CalculateGst and calculategst are three different method names to the Java compiler. The convention is camelCase starting with a lowercase letter. Deviating from this convention does not cause errors but violates Java naming standards and makes code harder to read.

What is the difference between a method and a constructor in Java?

A constructor is a special block that initialises an object when it is created with new. It has the same name as the class, no return type — not even void — and runs automatically during object creation. A method is a named block that performs a task, has an explicit return type, is called explicitly by name, and can be called multiple times on an existing object. Constructors run exactly once per object; methods run as many times as called.

Can you define a method inside another method in Java?

No. Java does not support nested method definitions. Methods must be declared as members of a class, not inside another method. Anonymous classes and lambda expressions can be defined inside a method and can contain their own behaviour, but these are not method definitions in the traditional sense.

What happens if you define two methods with the same name and same parameters in the same class?

The compiler rejects it with a "duplicate method" error. Method names must be unique within a class when the parameter list is the same. Two methods with the same name but different parameter types or counts are valid — this is method overloading. Two methods with the same name and the same parameter list but different return types are also rejected — the return type alone does not distinguish methods.

Summary

Defining methods is the fundamental act of organising Java code into reusable, named units of work. Every method declares who can call it through its access modifier, what it needs through its parameters, what it gives back through its return type, and what it does through its body. Static methods belong to the class — no object required, no instance state accessible. Instance methods belong to an object — they read and modify state, and they form the behaviour layer of every Java application.

The habits that distinguish clean method definitions from messy ones are consistent in every production Java codebase: one responsibility per method, verb-based names, the smallest possible access modifier, and guard clauses instead of deeply nested conditions. A method that does one thing well — named to say exactly what that thing is — is the building block of every maintainable Java system.

What to Read Next

TopicLink
How parameters and return types work in depth with method signaturesJava Parameters and Return Types →
How method overloading lets multiple methods share a name with different signaturesJava Method Overloading →
How the static keyword controls class-level vs instance-level method behaviourJava static Keyword →
How constructors define a special kind of method for object initialisationJava Constructors →
How access modifiers control method visibility across packages and hierarchiesJava Access Modifiers →
Defining Methods in Java | DevStackFlow