Free Handbook · Every example compiled & verified

Fundamentals

Variables, the eight primitive types, operators, type casting, integer overflow and reading keyboard input with Scanner, with the compiler errors each one causes.

0 / 142 lessons🔥 0 day streak
ShareXLinkedIn

Module 01 · what you'll be able to do

  • Declare variables with an explicit type, with var, and as final constants
  • Choose the right primitive type and know its range, and write long, float and char literals correctly
  • Predict the result of integer division, %, ++ and short-circuit operators
  • Cast between numeric types and explain when Java widens automatically and when you must narrow by hand
  • Spot integer overflow and floating-point rounding before they reach production, and read input with Scanner
01

Variables and constants

A variable is a named box that holds one value of one type. In Java the type is fixed when you declare the variable and can never change: an int box only ever holds whole numbers. You write the type, the name, and optionally an initial value: int age = 30;. Assigning later uses just the name: age = 31;.

javaMain.java
public class Main {
    public static void main(String[] args) {
        int age = 30;              // declare and initialise
        String name = "Asha";      // String is a class, not a primitive
        double height;             // declare now...
        height = 1.68;             // ...assign later

        age = age + 1;             // reassign: the type stays int
        final double TAX_RATE = 0.18;   // final = cannot be reassigned

        var city = "Pune";         // var: the compiler infers String
        var count = 3;             // inferred int

        System.out.println(name + " is " + age + ", " + height + " m");
        System.out.println("Tax rate: " + TAX_RATE);
        System.out.println(city + " x" + count);
    }
}
Outputcompiled & run with real Java
Asha is 31, 1.68 m
Tax rate: 0.18
Pune x3
Your turn

Try count = "three"; after the var line. It will not compile: var still gives count a fixed type (int), it just saves you typing it.

var is not dynamic typing
var (Java 10+) only works for local variables that are initialised on the same line. The compiler reads the right-hand side, decides the type once, and it never changes. Use it when the type is obvious from the right side (var list = new ArrayList<String>()); write the type out when it is not.
Error you will hit

variable might not have been initialized

java
public class Main {
    public static void main(String[] args) {
        int total;
        System.out.println(total);
    }
}
Main.java:4: error: variable total might not have been initialized
        System.out.println(total);
                           ^
1 error
Why the compiler said that

Local variables in Java have no default value. The compiler proves every local is assigned before it is read, and refuses to compile if any path could read an empty box. (Fields and array elements do get defaults — 0, false, null — but locals never do.)

The fix

Give the variable a value before you read it.

java
int total = 0;
System.out.println(total);
Error you will hit

cannot assign a value to final variable

java
public class Main {
    public static void main(String[] args) {
        final int MAX_USERS = 100;
        MAX_USERS = 200;
        System.out.println(MAX_USERS);
    }
}
Main.java:4: error: cannot assign a value to final variable MAX_USERS
        MAX_USERS = 200;
        ^
1 error
Why the compiler said that

final means "assigned exactly once". The compiler rejects the second assignment — that is the whole point of marking it final.

The fix

Remove final if the value really must change, or use a new variable for the new value.

java
final int MAX_USERS = 100;
int allowedToday = MAX_USERS * 2;
02

The eight primitive types

Java has exactly eight primitive types. They hold a raw value directly (not a reference to an object), have a fixed size on every platform, and start with a lower-case letter. Everything else — String, arrays, your own classes — is a reference type.

TypeSizeRange / valuesLiteral exampleDefault (fields)
byte8 bit-128 to 127(byte) 100
short16 bit-32,768 to 32,767(short) 3000
int32 bitabout ±2.1 billion42, 1_000_0000
long64 bitabout ±9.2 quintillion8_000_000_000L0L
float32 bit~7 significant digits3.14f0.0f
double64 bit~15–16 significant digits3.140.0
char16 bitone UTF-16 code unit'A''\u0000'
boolean—true or falsetruefalse
javaMain.java
public class Main {
    public static void main(String[] args) {
        byte b = 127;
        short s = 32_000;
        int i = 2_147_483_647;
        long worldPopulation = 8_100_000_000L;   // L suffix = long literal
        float price = 19.99f;                    // f suffix = float literal
        double pi = 3.141592653589793;
        char grade = 'A';                        // single quotes = char
        boolean isActive = true;

        System.out.println(b + " " + s + " " + i);
        System.out.println(worldPopulation);
        System.out.println(price + " " + pi);
        System.out.println(grade + " " + isActive);
        System.out.println("int max:  " + Integer.MAX_VALUE);
        System.out.println("long max: " + Long.MAX_VALUE);
    }
}
Outputcompiled & run with real Java
127 32000 2147483647
8100000000
19.99 3.141592653589793
A true
int max:  2147483647
long max: 9223372036854775807
Your turn

Print Byte.MIN_VALUE and Short.MAX_VALUE. Every numeric wrapper class has MIN_VALUE and MAX_VALUE constants.

Error you will hit

integer number too large

java
public class Main {
    public static void main(String[] args) {
        long population = 8000000000;
        System.out.println(population);
    }
}
Main.java:3: error: integer number too large
        long population = 8000000000;
                          ^
1 error
Why the compiler said that

A number literal without a suffix is an int, and 8,000,000,000 does not fit in an int. It does not matter that the variable on the left is a long — the literal itself is invalid before the assignment happens.

The fix

Add the L suffix so the literal is a long. Use capital L; a lower-case l looks like the digit 1.

java
long population = 8_000_000_000L;
Error you will hit

String cannot be converted to char — quotes matter

java
public class Main {
    public static void main(String[] args) {
        char grade = "A";
        System.out.println(grade);
    }
}
Main.java:3: error: incompatible types: String cannot be converted to char
        char grade = "A";
                     ^
1 error
Why the compiler said that

Double quotes make a String (an object that can hold any number of characters). Single quotes make a char (exactly one character, a primitive).

The fix

Use single quotes for a char, or declare the variable as a String.

java
char grade = 'A';
What to use by default
int for whole numbers, long for IDs, timestamps in milliseconds and anything that could pass two billion, double for measurements, boolean for flags. byte, short and float are for memory-tight arrays and binary formats, rarely for everyday variables. For money, never use double — see the overflow lesson below.
03

Operators

Arithmetic operators are + - * / %. The one that surprises everyone: when both sides of / are integers, Java does integer division and throws away the remainder. 7 / 2 is 3, not 3.5. % gives the remainder — perfect for "is it even?" (n % 2 == 0) and wrapping around.

javaMain.java
public class Main {
    public static void main(String[] args) {
        System.out.println(7 / 2);      // int / int = int
        System.out.println(7 / 2.0);    // one double makes it double
        System.out.println(7 % 2);      // remainder
        System.out.println(-7 / 2);     // truncates toward zero
        System.out.println(-7 % 2);     // sign follows the left side

        int stock = 10;
        stock += 5;      // stock = stock + 5
        stock -= 3;
        stock *= 2;
        System.out.println("stock = " + stock);

        int a = 5, b = 8;
        System.out.println(a > b);
        System.out.println(a == 5 && b == 8);
        System.out.println(a > 10 || b > 7);
        System.out.println(!(a < b));
        System.out.println(2 + 3 * 4);     // * before +
        System.out.println((2 + 3) * 4);
    }
}
Outputcompiled & run with real Java
3
3.5
1
-3
-1
stock = 24
false
true
true
false
14
20
Your turn

Use % to print whether 2024 is divisible by 4, and then by 100.

Increment and decrement: prefix vs postfix

x++ and ++x both add 1 to x. The difference is the value of the expression: postfix x++ gives the old value and then increments; prefix ++x increments first and gives the new value. On a line by itself (count++;) there is no difference.

javaMain.java
public class Main {
    public static void main(String[] args) {
        int x = 5;
        int a = x++;
        int b = ++x;
        System.out.println("a=" + a + " b=" + b + " x=" + x);
    }
}
Outputcompiled & run with real Java
a=5 b=7 x=7
VisualizePostfix vs prefix, one step at a timeStep 1 / 4
int x = 5;
int a = x++;
int b = ++x;
System.out.println("a=" + a + " b=" + b + " x=" + x);
Line 1

x starts at 5.

Variables now
x5
All 4 steps as a table
StepLineWhat happenedVariables now
11x starts at 5.x = 5
22Postfix: the expression x++ evaluates to the old value 5, which goes into a; then x becomes 6.x = 6 a = 5
33Prefix: x becomes 7 first, and the expression evaluates to the new value 7.x = 7 a = 5 b = 7
44All three are printed.
Short-circuit: && and || stop early
&& does not evaluate its right side if the left side is false, and || skips the right side if the left is true. That is why if (name != null && name.length() > 3) is safe: when name is null, length() is never called. The single & and | always evaluate both sides.
04

Type casting and conversion

Widening — going from a smaller type to a bigger one (int → long → double) — happens automatically, because no information can be lost. Narrowing — double → int, long → int — can lose data, so Java makes you write an explicit cast: (int) 9.99. A cast to an integer type truncates, it does not round.

javaMain.java
public class Main {
    public static void main(String[] args) {
        int items = 7;
        double asDouble = items;            // widening: automatic
        System.out.println(asDouble);

        double price = 9.99;
        int whole = (int) price;            // narrowing: explicit, truncates
        System.out.println(whole);
        System.out.println(Math.round(price));   // rounding is a method, not a cast

        int total = 7, people = 2;
        System.out.println(total / people);            // 3: integer division
        System.out.println((double) total / people);   // 3.5: cast first

        char letter = 'A';
        int code = letter;                  // char widens to its code
        System.out.println(code);
        System.out.println((char) (code + 2));

        int big = 130;
        byte small = (byte) big;            // does not fit: wraps around
        System.out.println(small);

        String digits = "42";
        int parsed = Integer.parseInt(digits);   // String -> int
        String back = String.valueOf(parsed + 1); // int -> String
        System.out.println(back);
    }
}
Outputcompiled & run with real Java
7.0
9
10
3
3.5
65
C
-126
43
Your turn

Change (double) total / people to (double) (total / people). It prints 3.0 — the division already happened in integers before the cast.

Error you will hit

possible lossy conversion from double to int

java
public class Main {
    public static void main(String[] args) {
        double price = 9.99;
        int rounded = price;
        System.out.println(rounded);
    }
}
Main.java:4: error: incompatible types: possible lossy conversion from double to int
        int rounded = price;
                      ^
1 error
Why the compiler said that

Putting a double into an int would drop the fraction. Java never does that silently; it wants you to say so.

The fix

Cast explicitly if truncation is what you want, or use Math.round (returns a long) if you want rounding.

java
int truncated = (int) price;             // 9
int rounded = (int) Math.round(price);   // 10
Casts can silently wrap
The compiler trusts your cast. (byte) 130 is -126 and (int) 3_000_000_000L is a negative number — no error, no warning. Only cast when you know the value fits.
05

Integer overflow and floating-point precision

This is where juniors lose production data. An int has 32 bits. Add 1 to its maximum and it does not throw an error — it wraps around to the most negative value. Java does this silently on purpose, for speed. A multiplication of two innocent-looking ints (milliseconds in a month, price times quantity) can overflow before you ever store it in a long.

javaMain.java
public class Main {
    public static void main(String[] args) {
        int max = Integer.MAX_VALUE;
        System.out.println(max + 1);           // wraps to MIN_VALUE

        int msPerDay = 24 * 60 * 60 * 1000;
        long wrong = msPerDay * 30;            // int * int overflows first
        long right = msPerDay * 30L;           // L forces long arithmetic
        System.out.println(wrong);
        System.out.println(right);

        try {
            Math.addExact(max, 1);             // throws instead of wrapping
        } catch (ArithmeticException e) {
            System.out.println("caught: " + e.getMessage());
        }
    }
}
Outputcompiled & run with real Java
-2147483648
-1702967296
2592000000
caught: integer overflow
Your turn

Replace msPerDay * 30L with (long) msPerDay * 30. Same result — one operand being long is enough.

double has a different problem: it stores numbers in binary, and most decimal fractions (0.1, 0.2) have no exact binary form. The tiny errors show up when you add them. For money use java.math.BigDecimal built from a String, or store amounts as a long number of cents or paise.

javaMain.java
import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        System.out.println(0.1 + 0.2);
        System.out.println(0.1 + 0.2 == 0.3);

        BigDecimal a = new BigDecimal("0.10");
        BigDecimal b = new BigDecimal("0.20");
        System.out.println(a.add(b));

        long paise = 1999 * 3;                  // Rs 19.99 x 3, in paise
        System.out.println(paise / 100 + "." + paise % 100);
    }
}
Outputcompiled & run with real Java
0.30000000000000004
false
0.30
59.97
In real jobs
Overflow bugs show up as negative order totals, negative durations and IDs that suddenly look random. Code review rule of thumb: counts that can grow without bound are long, arithmetic that must never be wrong uses Math.addExact / Math.multiplyExact, and money is BigDecimal or integer minor units — never double.
06

Reading input with Scanner

java.util.Scanner reads text from the keyboard (System.in) and splits it into tokens. nextInt(), nextDouble() and next() read one whitespace-separated token; nextLine() reads the rest of the current line, spaces included.

javaMain.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        System.out.println("Enter your name:");
        String name = in.nextLine();

        System.out.println("Enter your age:");
        int age = in.nextInt();

        System.out.println("Hello, " + name + "! Next year you will be " + (age + 1) + ".");
    }
}
Outputcompiled & run with real Java
Enter your name:
Enter your age:
Hello, Asha! Next year you will be 26.

This run was fed the input Asha and 25. What you type is echoed by your terminal, not printed by the program, so it does not appear in the captured output below.

Your turn

Read a double height with in.nextDouble() and print it back.

The nextInt() then nextLine() trap

nextInt() reads the digits but leaves the newline you typed after them in the buffer. The next nextLine() sees that newline immediately and returns an empty string. The standard fix is one extra nextLine() to consume the leftover, or read every line with nextLine() and parse it yourself.

javaMain.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int age = in.nextInt();
        String leftover = in.nextLine();    // the "\n" after 25
        String fullName = in.nextLine();    // the real next line
        System.out.println("leftover = [" + leftover + "]");
        System.out.println(fullName + " is " + age);
    }
}
Outputcompiled & run with real Java
leftover = []
Asha Khan is 25

Input fed to this run: 25, then Asha Khan.

Error you will hit

InputMismatchException — the user typed text where a number was expected

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int age = in.nextInt();
        System.out.println(age);
    }
}
Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Unknown Source)
	at java.base/java.util.Scanner.next(Unknown Source)
	at java.base/java.util.Scanner.nextInt(Unknown Source)
	at java.base/java.util.Scanner.nextInt(Unknown Source)
	at Main.main(Main.java:6)
Why the compiler said that

This one compiles fine and crashes at runtime when the input is abc. Read a stack trace from the top for what went wrong and find the first line in your file (Main.java:6) for where.

The fix

Check with hasNextInt() before reading, and skip bad tokens.

java
Scanner in = new Scanner(System.in);
while (!in.hasNextInt()) {
    System.out.println("Please enter a number");
    in.next();          // throw away the bad token
}
int age = in.nextInt();
Primitive type
One of the eight built-in value types: byte short int long float double char boolean. Holds the value directly.
Reference type
Any class, interface, array or record type. The variable holds a reference (pointer) to an object, or null.
Literal
A value written directly in code: 42, 42L, 3.14f, 'A', "text", true.
Widening conversion
An automatic, lossless conversion to a larger type, such as int to long or double.
Narrowing cast
An explicit conversion to a smaller type, such as (int) 9.99. May truncate or wrap.
Integer overflow
When an arithmetic result is outside a type's range; Java ints and longs silently wrap around.
final
Marks a variable that can be assigned only once.
var
Local variable type inference (Java 10+): the compiler picks the static type from the initialiser.
Quick check

What does System.out.println(5 / 2 * 2.0); print?

JuniorWhat is the difference between int and Integer?

int is a primitive: it holds a 32-bit value directly, cannot be null, and has a default of 0 as a field. Integer is its wrapper class — an object that can be null and can be stored in collections like List<Integer> (generics cannot use primitives). Java converts between them automatically (autoboxing and unboxing), which is convenient but can throw a NullPointerException when a null Integer is unboxed, and == on two Integer objects compares references, not values.

What they are really testing: Whether you know autoboxing exists and the two traps it creates: null unboxing and == on wrappers.

Frequently asked questions

Why does 7 / 2 give 3 in Java?
Both operands are int, so Java performs integer division and discards the remainder. Make at least one operand a double — 7 / 2.0 or (double) 7 / 2 — to get 3.5.
Is String a primitive type in Java?
No. String is a class in java.lang, so String variables hold references and can be null. It gets special syntax (double-quoted literals and + for joining), which is why it feels primitive. Module 03 covers why that matters for ==.
Should I use var in Java?
Use it for local variables when the type is obvious from the right-hand side, such as var users = new ArrayList<User>(). Write the type explicitly when the initialiser is a method call whose return type a reader cannot see. It is never allowed for fields, parameters or return types.

Finish the Java handbook, then get hired

Sit the exam for your certificate, run your resume through the ATS checker, and see the jobs that ask for exactly this.

Check my resume
Found this course useful? Share it.
ShareXLinkedIn

Comments

0

Join the conversation. Sign in to leave a comment — we'd love to hear your thoughts.