Lexical Structure and Style

This section documents the current Java release line, with Java 25 LTS as the reference point (no specific patch version is pinned), as published at the Java developer portal, the Java Tutorials, and the Java SE API specification — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

A Java source file is plain Unicode text made of tokens — identifiers, keywords, literals, separators, and operators — laid out in a fixed structure. This page follows JLS chapter 3, "Lexical Structure" and the Java Tutorials "Language Basics" lesson.

Source-File Structure

A conventional source file has three parts in order: an optional package declaration, then any import declarations, then one or more top-level type declarations.

// File: src/com/example/orders/Invoice.java
package com.example.orders;                        // 1. at most one package declaration, and it comes first

import java.time.LocalDate;                        // 2. imports: single-type imports read best
import java.util.List;
import static java.util.Objects.requireNonNull;    // a static import brings in a static member

public class Invoice {                             // 3. exactly one public top-level type per file
    private final LocalDate date = LocalDate.now();
    private final List<LineItem> items;

    public Invoice(List<LineItem> items) {
        this.items = requireNonNull(items);
    }
}

class LineItem { }                                 // extra non-public top-level types are allowed here

The rules:

  • At most one public top-level type per file, and if there is one, the file name must match it exactly — Invoice.java for public class Invoice. Additional package-private types may share the file, though one type per file is the usual style.

  • The package name mirrors the directory path (com/example/orders/Invoice.java). A file with no package line is in the unnamed package — fine for throwaway code, not for anything shared.

  • import a.b.C; imports a single type; import a.b.*; imports every type in package a.b (not its sub-packages). import static a.b.C.m; imports a static member so it can be used unqualified — the example above does this with Objects.requireNonNull.

  • Source is Unicode — UTF-8 by default — and a \uXXXX escape may appear anywhere in the file, not just in string literals.

A package groups related types and forms a namespace; see Packages and Modules. The current release line also allows a compact source file with no class declaration at all — see Getting Started.

Identifiers, Keywords, and Comments

An identifier names a variable, method, class, or package. It may contain Unicode letters, digits, , and $, and must not start with a digit. $ and a leading are legal but reserved by convention for machine-generated code.

int count;            // fine
double _rate;          // legal, discouraged
var café = "☕";        // any Unicode letter is allowed
int 2fast;             // ERROR: identifier cannot start with a digit

Reserved words (JLS 3.9, also listed in the Java Tutorials keyword list) can never be used as identifiers:

abstract   continue   for          new         switch
assert     default    if           package     synchronized
boolean    do         goto*        private     this
break      double     implements   protected   throw
byte       else       import       public      throws
case       enum       instanceof   return      transient
catch      extends    int          short       try
char       final      interface    static      void
class      finally    long         strictfp    volatile
const*     float      native       super       while

* const and goto are reserved but unused.  true, false and null are reserved literal values.

Contextual keywords — var, yield, record, sealed, permits, non-sealed, when, and the module-declaration words (module, requires, exports, opens, uses, provides, to, with, transitive, open) — act as keywords only inside the construct that needs them and remain valid identifiers everywhere else, so pre-existing code that used record as a variable name still compiles.

Literals denote fixed values: integers (42, 0xFF, 0b1010), floating-point (3.14, 6e23), char ('A'), String ("hi"), text blocks ("""), and true / false / null. Their exact syntax is on Primitive Types and Variables.

Java has three comment forms; see JLS 3.7:

// a line comment runs to the end of the line

/* a block comment
   can span several lines */

/**
 * A Javadoc comment documents the element that follows it.
 * @param name the recipient's display name
 * @return a greeting line
 */
public String greet(String name) {
    return "Hi, " + name;
}

Only Javadoc /** */ comments are processed by the javadoc tool into API documentation.

Statements, Blocks, and Whitespace

A statement is a unit of execution terminated by a semicolon. A block \{ …​ } groups zero or more statements, can appear wherever a statement can, and introduces a scope for the locals declared in it.

int x = 1;                         // an expression statement
x++;                               // another
{                                  // a block: its own scope
    int y = x + 1;
    System.out.println(y);
}                                  // y is not visible past here
;                                  // an empty statement is legal (and usually a mistake)

The semicolon — not the newline — ends a statement, so one statement may span many lines and several statements may share one line. Whitespace (spaces, tabs, newlines) separates tokens where needed but is otherwise insignificant: indentation is for readers, and the compiler ignores it. This is unlike Python, where indentation is syntactically meaningful.

Naming and Code Conventions

The community follows one broadly shared style. Rather than restate it, this section shows it once; the authoritative source is Oracle’s Java Code Conventions, assumed throughout this section.

package com.example.billing;                         // packages: all lowercase, reverse-domain, dotted

public class InvoicePrinter {                         // types: UpperCamelCase (a.k.a. PascalCase)

    public static final int MAX_RETRIES = 3;          // constants (static final): UPPER_SNAKE_CASE

    private int retryCount;                           // fields / locals / parameters: lowerCamelCase

    public void printInvoice(Invoice invoice) {       // methods: lowerCamelCase, usually a verb phrase
        int lineWidth = 80;
        // ...
    }
}

interface Repository<T, ID> { }                       // type parameters: short single uppercase letters

In short: UpperCamelCase for classes, interfaces, enums, records, and annotation types; lowerCamelCase for methods, fields, local variables, and parameters; UPPER_SNAKE_CASE for static final constants; all-lowercase reverse-domain names for packages; short uppercase letters (T, E, K, V, R) for type parameters. Mark a field final when it never changes after construction, and use final for genuine constants. The prevailing brace style is K&R ("Egyptian"): the opening brace sits at the end of the line that introduces the block, and every block is braced even when it holds a single statement.

See Also