Index

Variables, Types, and Literals

Java Syntax

2.1 Variable Declaration and Initialization

In Java, variables are used to store data values. Before using a variable, you must declare it by specifying its type and name. You can also initialize the variable by assigning it a value. Declaration and initialization can be done separately or combined.

Declaring Variables

A variable declaration tells the compiler about the variable's type and name:

int age;        // Declares an integer variable named age
double price;   // Declares a double variable named price
String name;    // Declares a String variable named name

At this point, the variables exist but do not hold any meaningful value (they have default values if they are instance or class variables, but local variables must be initialized before use).

Initializing Variables

You assign a value to a variable using the assignment operator =:

age = 25;           // Initializes age with 25
price = 19.99;      // Initializes price with 19.99
name = "Alice";     // Initializes name with the string "Alice"

Combined Declaration and Initialization

It is common and often clearer to declare and initialize a variable in a single statement:

int age = 25;
double price = 19.99;
String name = "Alice";

This approach reduces errors and makes your code easier to read.

Multiple Variables Declaration

You can declare multiple variables of the same type on one line, though it is best to initialize them separately for clarity:

int x = 10, y = 20, z = 30;  // Multiple variables declared and initialized

Naming Conventions and Best Practices

Click to view full runnable Code

public class VariableDemo {

    public static void main(String[] args) {
        // Declaration
        int age;
        double price;
        String name;

        // Initialization
        age = 25;
        price = 19.99;
        name = "Alice";

        // Combined declaration and initialization
        int score = 100;
        double taxRate = 0.13;
        String city = "Toronto";

        // Multiple variable declarations (same type)
        int x = 10, y = 20, z = 30;

        // Output values
        System.out.println("Age: " + age);
        System.out.println("Price: $" + price);
        System.out.println("Name: " + name);
        System.out.println("Score: " + score);
        System.out.println("Tax Rate: " + taxRate);
        System.out.println("City: " + city);
        System.out.println("x: " + x + ", y: " + y + ", z: " + z);
    }
}

Reflection

Clear and consistent variable declaration and initialization make your code easier to understand and maintain. Combining declaration and initialization is a good habit that prevents uninitialized variable errors. Choosing descriptive variable names following conventions improves readability and helps others (and your future self) grasp the code's intent quickly. Mastering variables is a fundamental step toward effective Java programming.

Index

2.2 Primitive Data Types

Java provides eight primitive data types that store simple values directly in memory. These types are the building blocks for storing data efficiently and performing fast operations.

The Eight Primitive Types

Type Size (bits) Description Example Declaration
byte 8 Small integer, from -128 to 127 byte b = 100;
short 16 Larger integer, from -32,768 to 32,767 short s = 30000;
int 32 Standard integer, from -2³¹ to 2³¹-1 int i = 1_000_000;
long 64 Large integer, from -2⁶³ to 2⁶³-1 long l = 10_000_000_000L;
float 32 Single-precision floating point float f = 3.14f;
double 64 Double-precision floating point double d = 3.14159;
char 16 A single Unicode character char c = 'A';
boolean 1 (logical) True or false value boolean flag = true;

When to Use Each Type

Syntax Examples

int age = 30;
double price = 19.99;
char grade = 'A';
boolean isActive = false;
byte smallNumber = 100;
long population = 7_800_000_000L;
float piApprox = 3.14f;
short temperature = -10;

Reflection

Choosing the right primitive type affects memory usage and performance. Smaller types save memory but may require extra care when performing operations or conversions. Larger types like long and double use more space but allow a wider range or precision. Understanding these types helps you write efficient Java code tailored to your program's needs.

Index

2.3 Type Conversion and Casting

In Java, type conversion happens when you assign a value from one data type to another. This can be implicit (automatic) or explicit (manual casting). Understanding these conversions is essential to avoid data loss and runtime errors.

Implicit Casting (Widening Conversion)

Java automatically converts smaller numeric types to larger ones because there is no risk of losing information. This is called widening conversion.

Example:

int i = 100;
long l = i;      // int implicitly cast to long
float f = l;     // long implicitly cast to float

Here, int converts to long, and then long converts to float without explicit code because the target type can hold all possible values of the source type.

Explicit Casting (Narrowing Conversion)

When converting from a larger type to a smaller one, you must explicitly cast the value. This is called narrowing conversion and may cause data loss.

Example:

double d = 9.78;
int i = (int) d;  // explicit cast from double to int, fractional part lost
System.out.println(i); // Output: 9

Casting a double to an int truncates the decimal part, which can cause loss of precision.

Another example with possible overflow:

int big = 130;
byte b = (byte) big;  // byte range is -128 to 127
System.out.println(b); // Output: -126 (due to overflow)

Because 130 exceeds the byte range, the value wraps around, leading to unexpected results.

Click to view full runnable Code

public class TypeCastingDemo {
    public static void main(String[] args) {
        // ===== Implicit Casting (Widening Conversion) =====
        int i = 100;
        long l = i;        // int -> long
        float f = l;       // long -> float

        System.out.println("=== Implicit Casting ===");
        System.out.println("int value: " + i);
        System.out.println("long value (from int): " + l);
        System.out.println("float value (from long): " + f);

        // ===== Explicit Casting (Narrowing Conversion) =====
        double d = 9.78;
        int i2 = (int) d;   // double -> int (fractional part lost)

        int big = 130;
        byte b = (byte) big;  // int -> byte (overflow expected)

        System.out.println("\n=== Explicit Casting ===");
        System.out.println("double value: " + d);
        System.out.println("int value (from double): " + i2);
        System.out.println("int value (for overflow): " + big);
        System.out.println("byte value (from int): " + b);
    }
}

Why Casting Is Needed

Casting allows flexibility in operations involving different numeric types and helps the compiler understand how to handle assignments. Without casting, certain assignments would cause compilation errors.

When Casting Becomes Dangerous

Reflection

Casting is a powerful tool but must be used carefully. Always be aware of the types involved and the possible effects of narrowing conversions. When precision and data integrity are critical, avoid unnecessary casts and prefer using types that can safely hold your values. Understanding type conversion helps you write robust and predictable Java programs.

Index

2.4 Constants with final

In Java, the final keyword is used to declare constants—variables whose values cannot be changed once assigned. Using constants improves code readability and helps prevent accidental modification of important values.

Declaring Constants

To declare a constant, use final before the variable type. By convention, constant names are written in uppercase letters with underscores separating words:

final int MAX_USERS = 100;
final double PI = 3.14159;
final String APP_NAME = "JavaSyntaxBook";

Reassignment Not Allowed

Once a final variable is initialized, attempting to change its value causes a compile-time error:

MAX_USERS = 200;  // Error: cannot assign a value to final variable MAX_USERS

This restriction ensures that constants remain fixed throughout the program.

Using final constants makes your code easier to read and maintain by clearly indicating values that are meant to stay the same. Constants serve as single sources of truth, preventing "magic numbers" or hard-coded values scattered throughout your code. This is especially useful for configuration settings, limits, or fixed parameters like mathematical constants. Declaring constants also helps prevent bugs caused by unintended variable reassignment, increasing the robustness of your programs.

Index

2.5 Local Variable Type Inference (var)

Starting from Java 10, you can declare local variables using the var keyword, which allows the compiler to infer the variable's type based on the assigned value. This feature reduces verbosity while maintaining type safety.

Correct Syntax

Instead of explicitly specifying the type, you write:

var message = "Hello, world!";   // inferred as String
var count = 100;                 // inferred as int
var list = new ArrayList<String>(); // inferred as ArrayList<String>

The compiler determines the type at compile time, so var does not make Java dynamically typed; the variable still has a fixed type.

Limitations

var x;  // Error: cannot use 'var' without initialization
var obj = null;  // Error: cannot infer type from null

When var Improves Clarity

var map = new HashMap<String, List<Integer>>();

When var Reduces Readability

var result = processData();  // What is the type of result?

var helps write cleaner, less cluttered code, especially with long type names. However, use it thoughtfully—clear, explicit types can sometimes improve readability, especially for beginners or complex codebases. Balancing var usage with clarity ensures maintainable and understandable Java programs.

Click to view full runnable Code

import java.util.*;

public class VarExample {
    public static void main(String[] args) {
        // ===== Correct Syntax: Type Inference with 'var' =====
        var message = "Hello, world!";                 // inferred as String
        var count = 100;                               // inferred as int
        var list = new ArrayList<String>();            // inferred as ArrayList<String>
        var map = new HashMap<String, List<Integer>>(); // inferred as HashMap<String, List<Integer>>

        System.out.println("Message: " + message);
        System.out.println("Count: " + count);
        list.add("Java");
        System.out.println("List: " + list);
        map.put("scores", List.of(85, 90, 95));
        System.out.println("Map: " + map);

        // ===== Limitation Examples (Commented Out) =====

        // var x; // ❌ Error: cannot use 'var' without initializer
        // var obj = null; // ❌ Error: cannot infer type from null

        // ===== Readability Considerations =====
        var name = "Alice";         // clear and obvious
        var total = calculateTotal(5, 3); // not clear what type 'total' is at a glance

        System.out.println("Name: " + name);
        System.out.println("Total: " + total);
    }

    static double calculateTotal(int a, int b) {
        return a * b * 1.5;
    }
}
Index

2.6 Numeric, Character, and Boolean Literals

In Java, literals are fixed values directly written in code. They represent data like numbers, characters, or boolean values. Understanding literal syntax helps write clear and readable code.

Integer Literals

int decimal = 1234;
int binary = 0b1010;  // equals decimal 10
int hex = 0xFF;       // equals decimal 255
int largeNumber = 1_000_000;

Floating-Point Literals

double pi = 3.14159;
float gravity = 9.8f;
double avogadro = 6.022e23;

Character Literals

char letter = 'A';
char digit = '7';
char smiley = '\u263A';

Boolean Literals

boolean isJavaFun = true;
boolean isFishTasty = false;
Click to view full runnable Code

public class LiteralsDemo {
    public static void main(String[] args) {
        // ===== Integer Literals =====
        int decimal = 1234;
        int binary = 0b1010;          // 10 in decimal
        int hex = 0xFF;               // 255 in decimal
        int largeNumber = 1_000_000;

        // ===== Floating-Point Literals =====
        double pi = 3.14159;
        float gravity = 9.8f;
        double avogadro = 6.022e23;

        // ===== Character Literals =====
        char letter = 'A';
        char digit = '7';
        char smiley = '\u263A';       // ☺

        // ===== Boolean Literals =====
        boolean isJavaFun = true;
        boolean isFishTasty = false;

        // ===== Output =====
        System.out.println("=== Integer Literals ===");
        System.out.println("Decimal: " + decimal);
        System.out.println("Binary (0b1010): " + binary);
        System.out.println("Hexadecimal (0xFF): " + hex);
        System.out.println("Large Number (with underscores): " + largeNumber);

        System.out.println("\n=== Floating-Point Literals ===");
        System.out.println("Double (pi): " + pi);
        System.out.println("Float (gravity): " + gravity);
        System.out.println("Scientific Notation (Avogadro's number): " + avogadro);

        System.out.println("\n=== Character Literals ===");
        System.out.println("Letter: " + letter);
        System.out.println("Digit: " + digit);
        System.out.println("Smiley (Unicode): " + smiley);

        System.out.println("\n=== Boolean Literals ===");
        System.out.println("Is Java fun? " + isJavaFun);
        System.out.println("Is fish tasty? " + isFishTasty);
    }
}

Reflection

Using the appropriate literal format increases code clarity and reduces errors. Underscores help make large numbers easier to read. Choosing the right literal suffix (f for floats, 0x for hex) avoids confusion and unintended data type issues. Clear, consistent literal usage is a simple but important part of writing clean Java syntax.

Index

2.7 Escape Sequences and Special Characters

In Java, escape sequences are special characters used inside string and character literals to represent otherwise hard-to-type or invisible characters. They begin with a backslash \.

Common Escape Sequences

Escape Sequence Description Example Output
\n New line Moves to the next line
\t Tab Inserts a horizontal tab
\\ Backslash Prints a single backslash \
\" Double quote Prints a double quote "
\' Single quote Prints a single quote '
\r Carriage return Returns cursor to line start
\b Backspace Deletes the previous character

Examples

System.out.println("Hello\nWorld!");       // Prints on two lines
System.out.println("Column1\tColumn2");    // Tab space between words
System.out.println("C:\\Program Files");   // Prints C:\Program Files
System.out.println("She said, \"Java is fun!\""); // Prints quotes inside string

Output:

Hello
World!
Column1    Column2
C:\Program Files
She said, "Java is fun!"

Escape sequences are essential for formatting output and including special characters inside strings. A common mistake is forgetting to escape backslashes or quotes, which leads to syntax errors or incorrect output. Using escape sequences properly allows you to produce readable and well-structured console output and handle string data that contains special characters without breaking the code. Mastery of escape sequences improves your ability to manipulate text in Java programs efficiently.

Index