Difficulty: Beginner to Intermediate | Prerequisites: Basic Java syntax, understanding of classes.
This topic sits at the heart of early Java programming. Before you touch loops, arrays or object design, you need to know how methods call each other, what happens to variables when execution jumps between methods, and why Java insists on types. If you have written a "Hello World" program and know what a class declaration looks like, you are ready. If not, start there.
Static methods, variable scope and primitive data types are the building blocks everything else in CS101 rests on. Misunderstand scope and you will spend hours debugging code that compiles but produces wrong output. Misunderstand types and you will lose data to silent truncation.
Java's static methods belong to the class, not to an instance, and each method has its own local scope for variables. Primitive data types (int, double, float, boolean and others) each occupy a fixed amount of memory and cannot be used interchangeably without explicit casting. When you trace through nested method calls, you must track each method's own copy of its local variables separately.
Static method
A method declared with the static keyword that belongs to the class itself rather than to any particular object instance. You call it via ClassName.methodName() or, within the same class, just methodName(). In simple terms, it is a function you can use without creating an object first.
Variable scope (local scope)
The region of code where a variable is accessible. A variable declared inside a method exists only while that method is running and cannot be seen by other methods. Think of it as each method having its own private whiteboard that gets erased when the method finishes.
Primitive data type
One of Java's eight built-in types that store simple values directly in memory rather than as references to objects: boolean, byte, short, int, long, float, double, char. Each has a fixed size in bits.
Method signature
The combination of a method's name and its parameter list (types and order). Java uses the signature to distinguish overloaded methods. Think of it as the method's fingerprint.
Return type
The data type of the value a method sends back to the caller. A method declared void returns nothing. A method declared int must return an integer value.
Pass by value
Java's mechanism for passing arguments to methods. A copy of the variable's value is handed to the method, so changes inside the method do not affect the original variable. In simple terms, the method gets a photocopy, not the original document.
How static method calls work
When main calls foo(), execution jumps to foo. Any local variable x inside foo is separate from any x in main.
The private static modifier means the method can only be called from within the same class. public static means it can be called from anywhere.
A static method cannot access instance variables directly. It can only work with its own parameters, local variables, and other static members.
Variable scope rules
A variable declared inside a method (local variable) exists only during that method's execution.
If main declares int x = 12 and foo declares its own int x = 14, they are entirely different variables. Changing one does not affect the other.
Parameters behave like local variables: static int foo(int a) means a is local to foo, initialised with whatever value was passed in.
Tracing nested method calls (foo and bar example)
The source notes trace a program where foo calls bar and both modify a local variable a:
int a = foo(1) calls foo with argument 1
Inside foo(int a): a = bar(a - 2) calls bar with a - 2
Inside bar(int a): a = a - 1, then prints a, then returns a + 3
Back in foo: a is assigned the return value from bar, then System.out.print(a) prints it, then foo returns a
Final output from the traced example: -210
The key lesson: each call to foo or bar creates its own copy of a. You must track them on separate lines of your trace, like separate columns on paper.
Static method calls with varying parameter values
The notes show several small programs that call foo() with different values of x set at class level or passed as parameters:
When x = 5 in the class and main sets int x = 13, then calls foo(): the method sees whichever x is in its scope (the static field x = 5, not main's local x = 13).
When the static field is int x = 15 and foo is private static (int x = 3): the parameter x = 3 shadows the field inside foo.
When x = 2 and static int x = 7: calling foo() then System.out.println(x) prints the static field value, not a local one.
Java has eight primitive types. The source notes list them with their size rankings (the number indicates relative memory size):
Type | Size | What It Stores |
|---|---|---|
byte | 8 bits | Whole numbers, -128 to 127 |
short | 16 bits | Whole numbers, -32,768 to 32,767 |
int | 32 bits | Whole numbers, roughly -2.1 billion to 2.1 billion |
long | 64 bits | Very large whole numbers |
float | 32 bits | Decimal numbers, ~7 digits of precision |
double | 64 bits | Decimal numbers, ~15 digits of precision |
char | 16 bits | A single Unicode character |
boolean | 1 bit (conceptually) |
|
Size hierarchy from the notes
The handwritten notes rank them: boolean (5), char, double (6), long, int (7), short, float (8), byte. The numbers in parentheses appear to be a ranking or exam reference. The practical hierarchy for widening conversions is:
byte → short → int → long → float → double
Java will automatically widen (e.g. assign an int to a double), but narrowing (e.g. assigning a double to an int) requires an explicit cast and may lose data.
Real-world application
Choosing the right type matters when memory is constrained (embedded systems, large arrays) or when precision matters (financial calculations should avoid float and double in favour of BigDecimal). For most coursework, int for whole numbers and double for decimals is sufficient.
"A static method can access any variable in the class." It cannot access instance variables. It can only access other static members and its own local variables. If you get a "non-static variable cannot be referenced from a static context" error, this is why.
"Calling a method changes the caller's variables." Java is pass-by-value for primitives. If main passes x to foo, and foo modifies its parameter, main's x is untouched.
"int and double are interchangeable." Widening (int to double) happens automatically, but narrowing (double to int) requires an explicit cast and truncates the decimal portion. int x = 3.7; will not compile.
"boolean takes 1 bit of memory." Conceptually it represents one bit of information, but the JVM typically allocates a full byte or more. The distinction rarely matters in coursework but comes up in systems-level questions.
⚠️ Method tracing is a near-certainty on exams. You will be given code with nested method calls and asked to write the output. Practise tracing on paper with a separate column for each method's local variables.
⚠️ Scope questions appear as "what is the value of x after this code runs?" The trap is confusing a local variable in one method with a same-named variable in another.
⚠️ Know the eight primitive types and their sizes. Multiple-choice questions often test whether a given assignment compiles (e.g. assigning a long to an int without a cast).
⚠️ The difference between private static and public static is commonly tested. A private static method is only callable within its own class.
True or False: A static method can directly access instance variables of its class.
Answer: False. Static methods can only access static members and their own local variables.
Fill in the blank: Java passes primitive arguments to methods by ____.
Answer: value
True or False: int x = 3.14; will compile in Java.
Answer: False. Narrowing from double to int requires an explicit cast.
Fill in the blank: The automatic conversion from int to double is called ____.
Answer: widening (or implicit widening conversion)
True or False: If main declares int x = 10 and passes x to foo(int x), and foo sets x = 99, then after foo returns, main's x is still 10.
Answer: True. Java is pass-by-value for primitives.
Q: Given the following code, what is printed?
public class Main {
private static int x = 5;
private static void foo() {
System.out.println(x);
}
public static void main(String[] args) {
int x = 13;
foo();
}
}A: 5 is printed. The method foo() sees the static field x = 5, not main's local x = 13.
Q: What is the output of this code?
static int foo(int a) {
a = bar(a - 2);
System.out.print(a);
return a;
}
static int bar(int a) {
a = a - 1;
System.out.print(a);
return a + 3;
}
// Called with: int result = foo(1);A: Trace it step by step. foo(1): a = bar(1 - 2) = bar(-1). Inside bar(-1): a = -1 - 1 = -2, prints -2, returns -2 + 3 = 1. Back in foo: a = 1, prints 1, returns 1. Output: -21. The result variable holds 1.
Q: Which of the following assignments will NOT compile? (a) double d = 42; (b) int i = 3.14; (c) long l = 100;
A: (b) will not compile. Assigning a double literal to an int is a narrowing conversion and requires an explicit cast: int i = (int) 3.14;
Q: Explain why two methods can each have a variable called x without conflict.
A: Each method has its own local scope. Variables declared inside a method are created when the method starts and destroyed when it returns. Two methods' local variables are stored in separate stack frames, so their names do not collide.
This material connects directly to object-oriented programming: once you understand static methods, the next step is understanding instance methods, which require an object and can access instance variables. The scope rules here carry over to loops and conditionals (variables declared inside a for loop's body are not visible outside it).
Primitive data types connect to arrays (the second study doc), where you must declare the type an array holds. They also connect to type casting, which appears in arithmetic expressions involving mixed types.
static method, class method, local variable, variable scope, scope rules, pass by value, Java primitives, int, double, float, boolean, char, byte, short, long, widening conversion, narrowing conversion, type casting, method signature, return type, void, private static, public static, method tracing, call stack, stack frame, CS101, Arizona State University, ASU CS101