• Home
  • LLMs
  • Python
  • Docker
  • Kubernetes
  • Java
  • Maven
  • All
  • About
Java | Methods
  1. Instance Methods vs. Static Methods
  2. Method Return Types and Return Values
  3. Method Parameters and Types
  4. Varargs (Variable-Length Argument Lists)
  5. Local Variables Within Methods

  1. Instance Methods vs. Static Methods
    • An instance method is only accessible when an instance has been created.

    • A static method (a.k.a. class method) can be accessed even if no instance of the class has been created.

    • A static method is declared using the static keyword.

    class ClassA {
        public void instanceMethod() { }
    
        public static void staticMethod() { }
    
        public void doSomeThing() {
            // Accessing instance methods
            (new ClassA()).instanceMethod(); // OK
            (new ClassA()).staticMethod(); // OK - Warning: The static method staticMethod() from the type ClassA should be accessed in a static way
    
            // Accessing static methods
            ClassA.staticMethod(); // OK
            ClassA.instanceMethod(); // Compiler error: Cannot make a static reference to the non-static method instanceMethod() from the type ClassA
        }
    }
    • The code inside an instance method can access all attributes (instance or static) and call all methods (instance or static).

    • The code inside a static method can only access static attributes and only call static methods.

    class ClassA {
        int var1 = 1;
        static int var2 = 1;
    
        public Integer instanceMethod() {
            return var1 * var2; // OK
        }
    
        public static Integer staticMethod() {
            Integer localVar1 = var2; // OK
            Integer localVar2 = instanceMethod(); // Compiler error: Cannot make a static reference to the non-static method instanceMethod() from the type ClassA
            return var1; // Compiler error: Cannot make a static reference to the non-static field var1
        }
    }
  2. Method Return Types and Return Values
    • The return type can be a primitive or a reference type (including classes, interfaces, and arrays).
      The returned value (or variable) must be the same type as the one declared for the method.
      int doReturnPrimitiveType() {
          int var1 = 0;
          return var1;
      }
      Object doReturnReferenceType() {
          Object obj = new Object();
          return obj;
      }
    • You can return a value (or variable) that can be implicitly cast to the declared return type.
      int doImplicitCastPrimitiveType() {
          return 'c';
      }
      Object doImplicitCastReferenceType() {
          return Integer.valueOf(10);
      }
    • You can return a value (or variable) that can be explicitly cast to the declared return type.
      int doExplicitCastPrimitiveType() {
          double var1 = 12.5;
          return (int) var1;
      }
      Integer doExplicitCastReferenceType() {
          Integer temp = Integer.valueOf(10);
          Object obj = temp;
          return (Integer) obj;
      }
    • You can return null, but only if the return type is a reference type.
      Object doReturnNullValue() {
          return null;
      }
    • The void type indicates that the method does not return any value.
      void doReturnVoid() {
      }
      You can also use the return keyword to explicitly indicate the method returns nothing:
      void doReturnVoid() {
          return;
      }
  3. Method Parameters and Types
    A method can declare multiple parameters, each with its own type.
    A parameter's type can be a primitive or reference type (including classes, interfaces, and arrays).

    Notes :
    • Parameters: The names declared in the method signature, used to match values passed in when the method is called.

    • Arguments: The actual values (or variables) passed in between the parentheses during a method call.

    public class ClassA {
        void foo(int param1, Integer param2, Object param3) {
        }
    
        void bar() {
            int arg1 = 0;
            Integer arg2 = 1;
            Object arg3 = this;
    
            foo(arg1, arg2, arg3);
        }
    }
    Here are the rules for arguments to be accepted by the compiler:

    • The number of arguments used in the method call must match the number of parameters.
      void bar() {
          int arg1 = 0;
          Integer arg2 = 1;
      
          foo(arg1, arg2); // Compiler error: The method foo(int, Integer, Object) in the type ClassA is not applicable for the arguments (int, Integer)
      }
    • Each argument must be of the same type as its corresponding parameter.
      void bar() {
          String arg1 = "0";
          Integer arg2 = 1;
          Object arg3 = this;
      
          foo(arg1, arg2, arg3); // Compiler error: The method foo(int, Integer, Object) in the type ClassA is not applicable for the arguments (String, Integer, Object)
      }
    • The argument type can differ from the parameter type as long as it can be implicitly converted to match.
      void bar() {
          Integer arg1 = 0; // OK: Integer --> int
          int arg2 = 1; // OK: int --> Integer
          String arg3 = "my String"; // OK: String is a subclass of Object
      
          foo(arg1, arg2, arg3);
      }
  4. Varargs (Variable-Length Argument Lists)
    Sometimes, you want a method to accept a variable number of arguments.
    For example, a method that sums all values passed in.
    To do this, follow the parameter type with three dots (...)

    public class ClassA {
        static int doSumArgs(int... varParams) { // method accepts a variable number of int arguments
            int total = 0;
    
            for (int param : varParams) { // loop through all arguments
                total += param;
            }
    
            return total;
        }
    
        public static void main(String[] args) {
            System.out.println(doSumArgs(1, 2)); // Method call with two arguments
            System.out.println(doSumArgs(1, 2, 3)); // Method call with three arguments
        }
    }
    You can mix regular parameters with varargs.
    However, varargs must be declared last.
    Only one vararg is allowed per method.
    void foo(String param1, Integer param2, int... varParams) { // OK
    }
    
    void bar(String param1, int... varParams, Integer param2) { // Compiler error: The variable argument type int of the method bar must be the last parameter
    }
    
    void multiVarArgs(int... varParams1, int... varParams2) { // Compiler error: The variable argument type int of the method multiVarArgs must be the last parameter
    }
    Note :
    The syntax for declaring and calling varargs is not part of the core Java language—it’s just "syntactic sugar";
    This means the compiler transforms the code into something else when generating bytecode.

    For example, this code:
    public class ClassA {
        void foo(int... varParams) {
        }
    
        void bar() {
            foo(1, 2, 3);
        }
    }
    Will be transformed by the compiler into:
    public class ClassA {
        void foo(int[] varParams) {
        }
    
        void bar() {
            foo(new int[] { 1, 2, 3 });
        }
    }
    You’ll notice that the vararg declaration int... varParams becomes an array declaration int[] varParams.
    And the argument list 1, 2, 3 becomes an anonymous array new int[] { 1, 2, 3 }.

    The most important thing to remember about varargs is that they are actually just arrays under the hood.
  5. Local Variables Within Methods
    Local variables are variables declared inside a method, constructor, or block. They are created when the method is invoked and destroyed when the method exits.

    • Local variables must be declared and initialized before use. They do not have default values, so the compiler will throw an error if they are accessed without initialization.

    • Local variables are only accessible within the method or block where they are declared (i.e., they have method scope).

    • Local variables cannot have access modifiers like public, private, or protected.

    • Local variables can shadow instance variables and static variables with the same name within the method.

    public class ClassA {
        int instanceVar = 10;
    
        void foo() {
            int localVar = 5; // Local variable declaration
    
            System.out.println(localVar); // OK
            System.out.println(instanceVar); // OK - accessing instance variable
    
            int instanceVar = 20; // This local variable shadows the instance variable
            System.out.println(instanceVar); // Refers to localVar, not the instance field
        }
    
        void bar() {
            int localVar;
            System.out.println(localVar); // Compiler error: The local variable localVar may not have been initialized
        }
    }
    Notes :
    • Local variables are stored on the stack and are not part of the object’s state. They are recreated each time the method is called.

    • You can declare final local variables if you want to prevent reassignment:
      void foo() {
          final int localVar = 3;
          localVar = 4; // Compiler error: The final local variable localVar cannot be assigned. It must be blank and not using a compound assignment
      }
© 2025  mtitek