1.3 Structure of a Java Program & The main Method
Key Takeaways
- A Java source file (.java) enforces an unbending order — an optional package declaration first, then import statements, then class or interface declarations — and may declare at most one public class, whose name must match the base file name with exact case sensitivity.
- The standalone application entry point must strictly declare the signature public static void main(String[] args); altering modifiers, return types, or parameter types prevents JVM launching.
- The java.lang package is automatically imported into every Java compilation unit by the compiler, eliminating the need to import fundamental types such as System, String, and Math.
- Java supports single-line (//), multi-line (/* */), and Javadoc (/** */) comments; multi-line comments cannot be nested within one another without causing compilation errors.
- Java SE 8 defines 50 lowercase reserved keywords plus the reserved literals true, false, and null; const and goto are reserved but carry no semantics, while String, System, and main are ordinary identifiers rather than reserved words.
1.3 Structure of a Java Program & The main Method
[!NOTE] Exam Focus: In the 1Z0-811 examination, questions frequently test your ability to spot syntactically invalid Java source file layouts. You must know the mandatory ordering of file elements (package -> imports -> class), understand why a file name must match its public class, recognize valid versus invalid
mainmethod signatures, and identify comment syntax errors.
A Java source code file (bearing the .java extension) is a structured compilation unit that adheres to strict grammatical and syntactical rules defined by the Java Language Specification. Violating these rules results in immediate compile-time errors.
Anatomical Layout of a Java Source File (.java)
A Java source file can contain three primary top-level elements, which must appear in an exact sequential order:
| File Element | Keyword | Quantity in File | Order Rule | Purpose |
|---|---|---|---|---|
| Package Declaration | package | Zero or One (0..1) | Must be the first non-comment statement | Defines the logical namespace and folder directory structure |
| Import Statements | import | Zero or Many (0..*) | Must appear after package, before class declarations | Makes external types accessible without fully qualified names |
| Type Declarations | class, interface, enum | One or Many (1..*) | Must appear after import statements | Declares classes, interfaces, or enumerations |
// Line 1: Comments and whitespace may appear anywhere in the file
package com.oracle.certification; // 1. Package declaration (at most one)
import java.util.ArrayList; // 2. Import statements (zero or more)
import java.time.LocalDate;
public class ExamCandidate { // 3. Class declaration (at most one public class)
// Fields, constructors, and methods
}
[!WARNING] Ordering Violations Cause Compiler Errors: If an
importstatement precedes apackagedeclaration, or if apackagedeclaration appears after aclassdeclaration, the Java compiler will reject the file with a compilation error. The only tokens permitted prior to the package declaration are comments (//,/* */,/** */) and whitespace.
Package Declarations: Namespaces and File Paths
A package provides a mechanism for grouping related classes, interfaces, and enumerations into a unified namespace. Packages serve two fundamental purposes:
- Preventing naming collisions: Two distinct classes can share the identical simple name
Dateas long as they reside in different packages (java.util.Dateversusjava.sql.Date). - Access protection: Packages establish an access control boundary. Package-private members (members declared without an explicit access modifier) are accessible only to other classes residing in the identical package.
Syntax and Directory Mapping
The package declaration consists of the package keyword followed by a dot-separated hierarchical identifier terminated by a semicolon:
package com.company.finance.payroll;
By industry convention, package names are written entirely in lowercase letters to avoid confusion with class names, using the reversed domain name of an organization (com.company.project). On the physical file system, package hierarchies must map directly to subdirectories. The class com.company.finance.payroll.SalaryCalculator must reside inside the directory path:
com/company/finance/payroll/SalaryCalculator.java
If a source file omits the package statement altogether, the types defined within that file belong to the default package (unnamed package). While legal in simple learning exercises, the default package should never be used in production applications because classes in named packages cannot import classes from the default package.
Import Statements: Explicit vs. Wildcard Imports
To use a class located in another package, Java developers have two choices:
- Use the Fully Qualified Class Name (FQCN) throughout the code:
java.util.ArrayList<String> list = new java.util.ArrayList<String>(); - Use an
importstatement at the top of the file, allowing the class to be referenced by its simple name:import java.util.ArrayList; // ... ArrayList<String> list = new ArrayList<String>();
Single-Type vs. On-Demand Wildcard Imports
Java supports two syntactical styles of import statements:
- Single-Type Import: Explicitly names the single class or interface being imported:
import java.util.Scanner; import java.util.List; - Type-Import-on-Demand (Wildcard
*): Uses an asterisk (*) to import allpublicclasses and interfaces declared directly within the specified package:import java.util.*;
[!IMPORTANT] Wildcards Do NOT Import Sub-packages: A wildcard import does not recursively import classes from sub-packages. For example,
import java.awt.*;imports classes directly insidejava.awt(such asjava.awt.Colorandjava.awt.Font), but does not import classes insidejava.awt.event.*(such asjava.awt.event.ActionEvent). A separate import statement (import java.awt.event.*;) is required.
[!TIP] Performance Myth: Using a wildcard import (
import java.util.*;) does not degrade runtime application performance or bloat the compiled.classbytecode. The Java compiler resolves imports at compile time; the generated bytecode contains only direct references to the specific types actually utilized.
The Automatic java.lang Import
Every Java compilation unit implicitly and automatically imports the entire java.lang package:
import java.lang.*; // Automatically included by the compiler behind the scenes
Consequently, developers never need to write import statements for ubiquitous core types like System, String, Math, Object, Thread, Exception, or primitive wrapper classes like Integer, Double, and Boolean.
Ambiguity and Name Collisions
When a source file imports two packages that contain a class with the identical name, a naming collision can occur:
import java.util.*;
import java.sql.*;
public class Report {
Date reportDate; // COMPILE ERROR: Reference to 'Date' is ambiguous!
}
Because both java.util.Date and java.sql.Date exist, the compiler cannot determine which class is intended. To resolve this ambiguity, the developer must either:
- Add an explicit single-type import, which always takes precedence over wildcard imports:
import java.util.Date; // Takes precedence over java.sql.* - Use the fully qualified class name directly at the variable declaration site:
java.util.Date reportDate = new java.util.Date();
Class Declarations and File Naming Rules
A Java source file can define one or more classes, interfaces, or enums. However, two strict rules govern top-level declarations:
The Single Public Class Rule
- A single
.javafile can contain at most onepublictop-level class. - If a file contains a
publicclass, the base name of the.javafile must match the name of that public class exactly, including letter case.
// File MUST be saved exactly as: Vehicle.java
public class Vehicle { // Matches filename
// ...
}
class Engine { // Valid: package-private class in the same file
// ...
}
If the file above were saved as vehicle.java (lowercase v) on a case-sensitive file system, or as Transport.java, the compiler would fail with the error:
class Vehicle is public, should be declared in a file named Vehicle.java.
Files with Zero Public Classes
A .java file is not required to declare any public class. If a file contains only package-private (default access) classes, the file name can be any legal identifier ending with .java, even if it does not match any of the class names declared within it:
// File saved as: Helpers.java (Fully valid!)
class MathHelper {
// ...
}
class StringHelper {
// ...
}
Deconstructing the main Method Signature
To execute a Java program as an independent standalone console application, the JVM requires an entry point. The Java launcher strictly expects the following method signature:
public static void main(String[] args)
Every single keyword in this signature serves a vital architectural purpose:
public static void main (String[] args)
│ │ │ │ │
│ │ │ │ └─ Array of command-line String arguments
│ │ │ └─ Exact identifier required by the JVM launcher
│ │ └─ Method returns no value to caller
│ └─ Callable directly on the class without instantiating an object
└─ Accessible by the JVM launcher from any package
public: An access modifier. The entry point must be universally accessible so the JVM launcher, which executes outside the application's package, can locate and invoke it.static: A method modifier indicating that the method belongs to the class itself rather than any specific instance. When launching an application, the JVM does not instantiate an object of the host class (e.g.,new Main()). Declaring the methodstaticallows the JVM to invokeMain.main()directly.void: The return type. The method performs operations and returns no value back to the JVM. (To exit with a specific status code, an application callsSystem.exit(int status)).main: The exact method identifier (all lowercase) required by the JVM specification. Methods namedMain,MAIN, orstartwill not be recognized as entry points.String[] args: The parameter list. The JVM gathers all command-line arguments passed to the program and bundles them into an array ofStringobjects.
Permissible Syntax Variations
The 1Z0-811 exam frequently tests candidate recognition of valid alternative syntaxes for main:
- Bracket placement on array: Both
String[] argsandString args[](orString []args) are valid. - Parameter identifier name: The parameter does not have to be named
args. Any legal Java identifier is valid (e.g.,String[] parametersorString[] data). - Varargs syntax (Java 5+): Variable-length argument lists (
String... args) are interchangeable withString[] argsand are accepted by the JVM launcher. - Order of modifiers: The access modifier and
statickeyword can be placed in reverse order:static public void main(String[] args)is completely valid, althoughpublic staticis universal convention.
Invalid main Signatures That Compile but Cannot Be Launched
The following signatures compile without error as regular methods, but the JVM launcher will fail to recognize them as valid application entry points at runtime:
| Invalid Signature | Reason It Fails as an Entry Point |
|---|---|
public void main(String[] args) | Missing static modifier; JVM cannot invoke without an instance |
static void main(String[] args) | Missing public modifier (package-private); JVM launcher cannot access |
public static int main(String[] args) | Return type is int instead of void |
public static void Main(String[] args) | Capitalized M; Java is strictly case-sensitive |
public static void main(String args) | Parameter is a single String, not an array (String[]) |
Statements, Blocks, and Variable Scoping
Statements
A statement is a complete unit of execution in Java, analogous to a complete sentence in natural language. In Java, simple statements must terminate with a semicolon (;):
int count = 5; // Declaration and assignment statement
count++; // Increment statement
System.out.println(); // Method invocation statement
;
An isolated semicolon by itself is an empty statement, which is syntactically legal but performs no operation.
Blocks and Variable Scope
A block (also called a compound statement) consists of zero or more statements enclosed within a matching pair of curly braces: { and }.
- Blocks can be used wherever a single statement is permitted (such as after
if,while, orforloops). - Blocks establish a lexical variable scope. Variables declared inside a block are visible only within that block and its nested inner blocks. Once execution exits the enclosing closing brace
}, the local variables declared within that block cease to exist:
public void calculate() {
int x = 10; // In scope throughout calculate()
{
int y = 20; // In scope only within this inner block
System.out.println(x + y); // 30
}
// System.out.println(y); // COMPILE ERROR: 'y' cannot be resolved to a variable!
}
Java Reserved Words
Oracle's Basic Java Elements topic area lists the objective "use Java reserved words" explicitly, and the exam tests it by showing you an identifier that collides with a keyword. A reserved word is a token the Java grammar claims for itself; it can never be used as the name of a variable, method, class, package, or label.
Java SE 8 defines 50 reserved keywords, plus 3 reserved literals (true, false, null) that are technically literal values rather than keywords but are equally off-limits as identifiers:
| Category | Reserved Words |
|---|---|
| Primitive types | boolean, byte, char, short, int, long, float, double |
| Control flow | if, else, switch, case, default, for, while, do, break, continue, return |
| Exception handling | try, catch, finally, throw, throws, assert |
| Class and object model | class, interface, enum, extends, implements, new, this, super, instanceof, void |
| Access modifiers | public, protected, private |
| Other modifiers | static, final, abstract, native, synchronized, transient, volatile, strictfp |
| Packaging | package, import |
| Reserved but unused | const, goto |
| Reserved literals | true, false, null |
Four Rules the Exam Actually Tests
- Keywords are always lowercase. Every reserved word is written entirely in lowercase. Because Java is case-sensitive,
Int,Class, andNeware not reserved — they are perfectly legal identifiers (though appallingly poor style). constandgotoare reserved but do nothing. Java claims both tokens so that C and C++ programmers get a clear compiler error instead of silently wrong behaviour, but the language defines no semantics for either. Declaringint goto = 5;fails to compile.varis not a keyword — and does not exist in Java 8. Local variable type inference arrived in Java 10, and even therevaris a reserved type name, not a keyword. On the 1Z0-811 exam (Java SE 8),var x = 10;simply fails to compile because no type namedvarexists.- Common class names are not reserved.
String,System,Math,Integer,Object, andmainare ordinary identifiers supplied by the standard library, not reserved words. Writingint String = 5;compiles — it merely shadows the type name inside that scope and creates a maintenance nightmare.
// COMPILE ERRORS: reserved words cannot be identifiers
// int class = 10; // 'class' is reserved
// double new = 3.14; // 'new' is reserved
// String final = "text"; // 'final' is reserved
// boolean null = true; // 'null' is a reserved literal
// LEGAL (but terrible style): these are NOT reserved words
int Class = 10; // Capital C -> ordinary identifier
int Integer = 42; // Shadows the wrapper class name inside this scope
int main = 7; // 'main' is just a method name convention
Identifier Rules That Travel With Reserved Words
Beyond avoiding reserved words, a legal Java identifier must:
- Begin with a letter, a currency symbol (
$), or an underscore (_) — never a digit.int 2ndPlace;fails to compile. - Contain only letters, digits,
$, and_after the first character. Hyphens, spaces, and operators such as-or+are illegal. - Be a single unreserved token. A lone underscore (
_) is legal in Java 8 but produces a compiler warning, and it became a hard error in Java 9.
Comments in Java Source Code
Comments allow developers to document code logic and intent. The Java compiler ignores comments during tokenization; comments generate zero bytecode and have zero impact on program execution. Java supports three styles of comments:
1. Single-Line Comments
Initiated by two forward slashes (//). Everything from // to the end of that physical line is ignored:
// This is a single-line comment
int total = 100; // Inline comment explaining variable total
2. Multi-Line (Traditional) Comments
Initiated by /* and terminated by */. Can span multiple lines:
/*
* Multi-line comment
* spanning across multiple lines
*/
int bonus = 50;
[!WARNING] Nesting Prohibition: Multi-line comments cannot be nested! The first occurrence of
*/encountered by the compiler immediately terminates the entire comment, leaving the remaining text as invalid code that triggers compiler errors:/* Outer comment /* Inner nested comment */ <-- Terminates here! This text causes a COMPILE ERROR! */
3. Javadoc Documentation Comments
Initiated by a slash followed by two asterisks (/**) and terminated by */. These comments are inspected and processed by the JDK's javadoc tool to generate standardized HTML documentation:
/**
* Calculates the annual interest accrued on a savings account.
*
* @param principal The starting investment balance in USD
* @param rate The annual interest rate as a decimal (e.g., 0.05)
* @return The total interest earned over one year
*/
public double calculateInterest(double principal, double rate) {
return principal * rate;
}
Standard Javadoc tags include @param (describes a method parameter), @return (describes the return value), @throws / @exception (documents exceptions thrown), @author (documents the developer), and @version (specifies version information).
A developer writes a Java source code file containing a public class declaration. Which rule is strictly enforced by the Java compiler regarding the file structure and naming?
Consider the following class definition: public class Starter { public static void Main(String[] args) { System.out.println("Running..."); } } What happens when a developer compiles this file with javac Starter.java and attempts to run it with java Starter?
Why does a developer never need to include the statement import java.lang.*; to use ubiquitous classes like String, System, Math, or Integer in a Java source file?
Which one of the following variable declarations fails to compile in Java SE 8 because the identifier collides with a Java reserved word?