Skip to lesson
CodeLangs AISoftware Training Institute
Java Program Structure and Basic Syntax

Chapter 2 · Java Foundations

Java Program Structure and Basic Syntax

Learn how a Java program is shaped — class declarations, the main method, statements, blocks, curly braces, semicolons, identifiers, keywords, literals, comments, naming conventions, and source file rules.

  • 16,057words
  • 73min read
  • 20quiz items
  • 14practice tools

Before we start writing bigger Java programs, there is one foundation we must make completely clear.

Imagine that someone gives you this Java program:

Java
public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

A beginner can copy this code, run it, and get the output.

But copying is not the same as understanding.

You should be able to answer questions such as:

  • Why did we write class?
  • Why is the class surrounded by { }?
  • Why is main() special?
  • Why is main written in lowercase?
  • What does public mean here?
  • What does static mean here?
  • Why does main() receive String[] args?
  • Why does System.out.println(...) end with ;?
  • Can the class name be anything?
  • Must the file name match the class name?
  • Can one .java file contain multiple classes?
  • Why can we write employeeName but not employee-name?
  • Is true a keyword?
  • What exactly is a literal?
  • Are Java names case-sensitive?
  • What happens when we pass values after the class name from the command line?

That is what this chapter is going to make clear.

The chapter specifically covers Java program structure, class declarations, main(), statements, blocks, braces, semicolons, identifiers, keywords and reserved words, literals, comments, naming conventions, case sensitivity, source-file rules, multiple classes, and command-line arguments.

By the end, a Java source file should no longer look like a collection of mysterious symbols.

You should be able to look at it and mentally see its structure.


1. First Understand the Shape of a Java Program#

Before discussing individual keywords, look at the big picture.

A traditional Java program usually has several structural levels:

Output
Java Source File
│
├── Optional package declaration
├── Optional import declarations
│
└── Class Declaration
    │
    ├── Fields
    ├── Constructors
    └── Methods
        │
        └── Statements
            │
            └── Expressions

For our first program, we only need a class and a method:

Java
public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

Think of the nesting:

Output
HelloJava.java
│
└── HelloJava class
    │
    └── main() method
        │
        └── println statement

The outer structure tells Java where something belongs.

The inner statements tell Java what work to perform.


2. Java Source File#

When you write Java source code, you normally save it in a file ending with:

Output
.java

For example:

Output
HelloJava.java
Employee.java
OrderService.java
Calculator.java

A .java file contains source code — the human-readable Java code written by the developer.

The Java compiler can compile that source code into JVM bytecode.

For example:

Terminal
javac HelloJava.java

After successful compilation, you will normally get:

Output
HelloJava.class

Then the JVM can run the compiled class:

Terminal
java HelloJava

The simplified flow is:

Output
HelloJava.java
     ↓
   javac
     ↓
HelloJava.class
     ↓
    JVM
     ↓
Program executes

Important distinction#

HelloJava.java is a source file.

HelloJava.class is normally a compiled class file containing bytecode.

They are not the same thing.


3. Why Does Java Need a Class?#

Look again at this program:

Java
public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

You may naturally ask:

Why can't we simply write System.out.println() directly in the file?

Historically, ordinary Java application code is organized inside types such as classes.

A class provides a structure in which data and behavior can be organized.

We will study classes deeply in Object-Oriented Programming.

For now, use this mental model:

A class is a named container that can contain the data and behavior belonging to a particular concept.

For example:

Output
Employee
    ├── employee data
    └── employee behavior

BankAccount
    ├── account data
    └── account behavior

OrderService
    └── order-related behavior

Our first program does not yet model a real business object, so we can simply create:

Java
public class HelloJava {
}

Now we are ready to understand the syntax.


4. Class Declaration#

Consider:

Java
public class HelloJava {
}

A simplified class declaration has this form:

Output
modifier class ClassName {
    class body
}

In our example:

Java
public class HelloJava {
}

the parts are:

PartMeaning
publicAccess modifier
classTells Java that a class is being declared
HelloJavaClass identifier/name
{Starts the class body
}Ends the class body

Do not worry about every possible class modifier yet.

The important thing is to recognize the structure.


Why is class required?#

Java needs to know what kind of declaration you are writing.

Compare:

Java
class Employee {
}

with concepts you may later encounter:

Java
interface PaymentGateway {
}
Java
enum OrderStatus {
    NEW,
    PAID,
    SHIPPED
}

The keyword communicates the type of language construct being declared.


5. Class Body#

Now look at:

Java
public class HelloJava {
    // class members go here
}

The pair of curly braces encloses the class body.

Later, the body can contain members such as:

  • fields
  • constructors
  • methods
  • nested types
  • initialization blocks

For now we will add one method:

Java
public class HelloJava {
    public static void main(String[] args) {
    }
}

There are now two nested brace pairs:

Output
class {
    method {
    }
}

Visually:

Output
HelloJava
┌────────────────────────────────────────────┐
│                                            │
│  main()                                    │
│  ┌──────────────────────────────────────┐  │
│  │                                      │  │
│  └──────────────────────────────────────┘  │
│                                            │
└────────────────────────────────────────────┘

This nesting is fundamental to understanding Java source code.


6. We Need Somewhere for Execution to Begin#

A class can contain many methods.

Suppose we have:

Java
public class Application {
    static void saveOrder() {
    }

    static void sendEmail() {
    }

    static void generateReport() {
    }
}

Which method should Java execute first when we launch this application?

Java needs an entry point.

Traditionally, that entry point is the main method.

Now the famous line finally has a reason to exist.


7. The Classic main() Method#

The traditional form used in Java applications is:

Java
public static void main(String[] args) {
}

Add it to our class:

Java
public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

In the classic model, the JVM launcher starts application execution through a suitable main method.

Let's decode the traditional signature carefully.

Output
public static void main(String[] args)
│      │      │    │         │
│      │      │    │         └── parameter name
│      │      │    └──────────── array of String
│      │      └───────────────── method name
│      └──────────────────────── no object required
└─────────────────────────────── accessible entry point

8. public in main()#

In the traditional signature:

Java
public static void main(String[] args)

public is an access modifier.

At a beginner level, remember:

public means the method is accessible from outside its declaring class according to Java access rules.

Historically, the classic launcher signature uses a public entry method.

We will study access modifiers properly when we study classes and encapsulation.


9. static in main()#

Normally, an instance method is called on an object.

Conceptually:

Output
Class
  ↓
Create Object
  ↓
Call Instance Method

But at application startup, we do not necessarily already have an object of your application class.

The traditional entry point therefore uses:

Java
static

A static method belongs to the class-level context and can be invoked without first creating an instance in the traditional startup model.

So:

Java
public static void main(String[] args)

means that main() can serve as the traditional startup method without requiring you to manually create an object first.

We will study static deeply later.

For this chapter, remember:

Classic main() is static so startup does not depend on an already-created application object.

10. void in main()#

Methods can return values.

For example, later you might write:

Java
static int add(int a, int b) {
    return a + b;
}

That method returns an int.

But the traditional main() method does not return a Java value to its caller.

Therefore its return type is:

Java
void

So:

Java
public static void main(String[] args)

contains:

Output
void → this method returns no value

This does not mean a Java process cannot communicate an operating-system exit status.

That is a different concept.

For example:

Java
System.exit(1);

can terminate a process with an exit status.

But that does not change main()'s Java return type.


11. Why Is It Called main?#

The launch protocol looks for a method named:

Output
main

Case matters.

This:

Java
public static void Main(String[] args) {
}

is not the same name as:

Java
public static void main(String[] args) {
}

Likewise:

Java
public static void MAIN(String[] args) {
}

has a different identifier.

This brings us naturally toward Java's case sensitivity, which we will explore properly later.


12. String[] args#

Now another unfamiliar piece appears:

Java
String[] args

Before continuing, we need to understand it.

When someone launches your program from a command line, they can provide extra values.

For example:

Terminal
java Greeting Dattatray

The program needs a way to receive:

Output
Dattatray

Java can provide those command-line values to main() as strings.

That is the role of:

Java
String[] args

At a beginner level:

  • String represents text.
  • [] indicates an array.
  • an array stores multiple values of the same declared element type.
  • args is simply the parameter name.

So:

Java
String[] args

means approximately:

"main() receives an array containing command-line text arguments."

Is the name args compulsory?#

No.

This works in the traditional signature:

Java
public static void main(String[] values) {
}

So does:

Java
public static void main(String[] commandLineArguments) {
}

The parameter type matters.

The local parameter name does not have to be args.

args is simply the conventional name.


String[] args vs String args[]#

Java permits both forms:

Java
public static void main(String[] args) {
}

and:

Java
public static void main(String args[]) {
}

The first is normally preferred:

Java
String[] args

because the array nature is visually attached to the type.


What about varargs?#

This is also compatible with the array representation:

Java
public static void main(String... args) {
}

String... is varargs syntax and is represented as an array for the method.

For beginner and interview preparation, the most recognizable form remains:

Java
public static void main(String[] args)

13. Important Modern Java Version Note About main()#

For many years, tutorials correctly taught the classic application entry point:

Java
public static void main(String[] args)

You should absolutely understand it because it remains ubiquitous in Java applications, frameworks, examples, interviews, and existing codebases.

However, modern Java has expanded the launch protocol.

Java SE 25 finalized compact source files and instance main methods. Modern Java can therefore launch certain main methods that are not necessarily public, not necessarily static, and can even have no parameters. Oracle's Java 25 documentation demonstrates compact programs such as:

Java
void main() {
    System.out.println("Hello, World!");
}

Java SE 26 continues to document JVM startup in terms of invoking a suitable main method.

What should you learn first?#

For enterprise development and traditional interview preparation, first master:

Java
public static void main(String[] args)

Then remember this version rule:

Output
Traditional Java teaching / enormous existing codebase
        ↓
public static void main(String[] args)

Modern Java SE 25+
        ↓
additional launchable main forms exist

Do not say in a modern Java interview:

"public static void main(String[] args) is the only possible launchable main method in every current Java program."

That statement is now too absolute.


14. Now We Need an Actual Instruction#

At this point our method is empty:

Java
public class HelloJava {
    public static void main(String[] args) {
    }
}

The program starts, but we have not told it to do anything.

So we add:

Java
System.out.println("Hello, Java!");

Now we have encountered another fundamental idea:

A Java program performs work through executable constructs, including statements.

15. Java Statements#

Consider:

Java
System.out.println("Hello, Java!");

At a beginner level, you can think of a statement as:

A complete Java instruction that participates in program execution.

Examples:

Java
int age = 36;
Java
age++;
Java
System.out.println(age);
Java
return;

Not every Java statement has exactly the same grammatical shape.

Java includes different statement categories such as:

  • local variable declaration statements
  • expression statements
  • selection statements
  • iteration statements
  • jump/transfer statements
  • blocks
  • empty statements
  • exception-handling statements

You do not need to learn all of those today.

For this chapter, the important idea is:

Output
method body
    ↓
contains executable statements
    ↓
statements determine program behavior

16. Statement vs Expression#

Beginners often mix these terms.

Consider:

Java
10 + 20

This is an expression that can produce a value.

Now:

Java
int total = 10 + 20;

This is a local-variable declaration statement.

The expression:

Java
10 + 20

appears inside the larger statement.

Another example:

Java
System.out.println("Hello");

is a method invocation expression used as an expression statement.

A useful mental model is:

Output
Expression
→ computes / represents a value or performs an operation

Statement
→ forms an executable step in program flow

We will study expressions and operators later.


17. Java Blocks#

Now look at:

Java
public static void main(String[] args) {
    System.out.println("Hello");
    System.out.println("Java");
}

The method body groups statements together.

A Java block is a sequence of permitted block statements enclosed in curly braces.

For example:

Java
{
    System.out.println("A");
    System.out.println("B");
}

Blocks are important because they help define:

  • grouping
  • scope
  • method bodies
  • conditional branches
  • loops
  • initialization sections

Later you will see:

Java
if (condition) {
    // block
}
Java
for (...) {
    // block
}
Java
while (...) {
    // block
}

A useful technical nuance#

Beginners often hear:

"Everything inside { } is a block."

That is a useful informal explanation, but it is not technically exact.

For example:

Java
class Employee {
}

uses braces for a class body.

A class body and a Java grammar Block are not exactly the same language construct.

Similarly, array initializers can also use braces.

Therefore, a more accurate rule is:

Curly braces are used by several Java constructs to delimit bodies or grouped content; a Java Block is one specific grammatical construct that also uses curly braces.

This distinction becomes useful in deeper interview discussions.


18. Why Blocks Matter for Scope#

Suppose:

Java
public class Demo {
    public static void main(String[] args) {
        {
            int number = 10;
            System.out.println(number);
        }
    }
}

The variable number belongs to the inner block's local scope.

If you try:

Java
public class Demo {
    public static void main(String[] args) {
        {
            int number = 10;
        }
        System.out.println(number);
    }
}

the code will not compile because number is outside its valid scope.

You do not need full variable-scope theory yet.

Just remember:

Braces are not only visual decoration. They can affect the structural and scope boundaries of Java code.

19. Curly Braces#

Java uses:

Output
{
}

to delimit several kinds of bodies and grouped constructs.

Examples:

Class body#

Java
class Employee {
}

Method body#

Java
static void work() {
}

Conditional body#

Java
if (true) {
    System.out.println("Yes");
}

Loop body#

Java
while (true) {
    break;
}

A missing brace can completely change or break the syntactic structure of your program.


20. Why Proper Indentation Matters#

The compiler primarily understands syntax, not visual beauty.

This code can still be syntactically valid:

Java
public class Demo{public static void main(String[] args){System.out.println("Hello");}}

But humans must maintain the program.

Compare:

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

The second version reveals the nesting immediately.

In production:

Formatting is a maintainability tool.

Good formatting makes it easier to:

  • review code
  • find incorrect nesting
  • understand scope
  • resolve merge conflicts
  • debug
  • onboard other developers

21. Semicolon#

You keep seeing:

Java
;

For example:

Java
System.out.println("Hello");

Why?

Many Java statement forms require a terminating semicolon.

Think of it as part of the grammar that marks the end of certain constructs.

Examples:

Java
int age = 36;
Java
age++;
Java
System.out.println(age);
Java
return;

But do not conclude:

"Every Java line must end with a semicolon."

That is wrong.

For example:

Java
public class Demo {
}

There is no required semicolon after the class declaration.

Likewise:

Java
if (age >= 18) {
    System.out.println("Adult");
}

The if statement itself does not require:

Java
};

22. A Dangerous Accidental Semicolon#

Consider:

Java
if (age >= 18);
{
    System.out.println("Adult");
}

Notice:

Java
if (age >= 18);

That semicolon represents an empty statement.

The following block is then separate from the if.

So the block can execute regardless of the intended condition.

This is a classic bug.

Intended#

Java
if (age >= 18) {
    System.out.println("Adult");
}

Risky / incorrect for the intended requirement#

Java
if (age >= 18); {
    System.out.println("Adult");
}

Important lesson:

Never add semicolons mechanically.

Understand which construct requires them.


23. Now We Need to Name Things#

So far we have created names such as:

Output
HelloJava
main
args
age

Java needs rules for these programmer-defined names.

That brings us to identifiers.


24. Identifiers#

An identifier is a name used to identify certain program elements.

Examples include names of:

  • classes
  • interfaces
  • methods
  • variables
  • parameters
  • packages
  • enum types
  • record types
  • labels

Examples:

Java
Employee
Java
calculateSalary
Java
employeeName
Java
MAX_RETRY_COUNT

25. Valid Identifier Examples#

Common valid examples:

Output
age
employee
employeeName
Employee
_count
$total
calculateSalary
order2
MAX_SIZE

Java's identifier rules are Unicode-aware, so the complete language rule is broader than merely A-Z, a-z, digits, _, and $.

For ordinary production code, however, conventional English-language names are normally easier for distributed development teams to maintain.


26. Important Identifier Rules#

A Java identifier:

  1. cannot begin with a digit
  2. cannot contain spaces
  3. cannot use operators or arbitrary punctuation such as -
  4. cannot be a reserved keyword
  5. is case-sensitive
  6. can contain digits after a valid starting character
  7. can contain _
  8. can contain $, although normal application code should rarely invent $ names

Examples:

Valid#

Output
employeeName
_employee
employee2
MAX_VALUE
$generated

Invalid#

Output
2employee

Reason: begins with a digit.

Output
employee name

Reason: contains a space.

Output
employee-name

Reason: - is interpreted as an operator rather than part of a normal identifier.

Output
class

Reason: class is a keyword.


27. The Special Case of _#

Older Java code could use:

Java
_

as an identifier.

Modern Java does not allow a single underscore as an ordinary identifier because _ became a reserved keyword beginning with Java 9.

So this is invalid in modern Java:

Java
int _ = 10;

But identifiers containing underscores can still be valid:

Java
int employee_count = 10;

Although standard Java naming conventions would normally prefer:

Java
int employeeCount = 10;

This is legal:

Java
int $total = 100;

But that does not mean it is a good naming convention.

The $ character is frequently associated with generated names and compiler/tool conventions.

Typical business code should prefer:

Java
int total = 100;

over:

Java
int $total = 100;

Decision rule:

Output
Is the name technically legal?
        ↓
       Yes

Is it idiomatic and readable Java?
        ↓
May still be No

Syntax correctness and production quality are different questions.


29. Keywords#

Now consider:

Java
public class Employee {
    static int count;
}

Words such as:

Output
public
class
static
int

have special language meaning.

They are not arbitrary names chosen by the programmer.

These are Java language keywords.

A keyword is a token reserved by the language for a particular syntactic or semantic role.

Therefore this is invalid:

Java
int class = 10;

You cannot reuse the keyword class as a normal variable identifier.


30. Common Java Keywords#

You will encounter keywords such as:

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

Do not try to memorize the complete set in one sitting.

You will naturally learn them through programming.


31. Keywords vs Contextual Keywords#

Modern Java has language words whose behavior depends on context.

Examples across modern Java language features include terms such as:

Output
var
record
sealed
permits
yield
module
requires
exports

These are not all treated identically to classic always-reserved keywords in every lexical context.

For beginners, the practical lesson is:

Do not assume every special-looking modern Java word follows exactly the same identifier rule as class or int.

When working with version-specific syntax, consult the Java Language Specification or the documentation for that Java release.


32. Reserved but Historically Unused Keywords#

Two famous Java keywords are:

Output
const
goto

Java reserves them, but they are not used as normal Java statements/features.

Therefore you cannot write:

Java
int goto = 10;

or:

Java
String const = "value";

This is a common interview question.


33. Are true, false, and null Keywords?#

This is another common interview trap.

Many beginners say:

"true, false, and null are Java keywords."

Technically, they are literals, not keywords.

Examples:

Java
boolean active = true;
Java
boolean deleted = false;
Java
String name = null;

Remember:

Output
true  → boolean literal
false → boolean literal
null  → null literal

They still cannot be used as ordinary identifiers.


34. Identifier vs Keyword vs Literal#

ConceptExamplePurpose
IdentifieremployeeNameProgrammer-defined name
KeywordclassSpecial language token
Literal"Dattatray"Source-code representation of a fixed value

Example:

Java
String employeeName = "Dattatray";

Here:

Output
String          → type name
employeeName    → identifier
=               → operator
"Dattatray"     → string literal
;               → terminator

35. Literals#

You have already used:

Java
System.out.println("Hello, Java!");

Where did "Hello, Java!" come from?

It is written directly in source code.

That introduces the concept of a literal.

A literal is source-code syntax representing a particular value.

Examples:

Java
10
Java
3.14
Java
'A'
Java
"Java"
Java
true
Java
null

36. Integer Literals#

Examples:

Java
10
Java
0
Java
5000

Java also supports different numeral systems.

Decimal#

Java
int value = 100;

Binary#

Prefix:

Output
0b

Example:

Java
int flags = 0b1010;

That represents decimal 10.

Hexadecimal#

Prefix:

Output
0x

Example:

Java
int color = 0xFF;

0xFF represents decimal 255.

Octal#

A leading zero can denote octal:

Java
int value = 012;

That value is decimal 10.

This can surprise developers.

Avoid unnecessary octal notation unless it has a clear purpose.


37. Numeric Separators#

Java permits underscores inside numeric literals to improve readability.

Example:

Java
int population = 1_000_000;

This is equivalent in value to:

Java
int population = 1000000;

Another example:

Java
long cardNumberPart = 1234_5678_9012_3456L;

The underscore is for readability.

It does not become part of the numeric value.

There are placement restrictions, so do not put underscores arbitrarily next to prefixes, suffixes, or decimal points.


38. Long Literals#

A large integer literal can be explicitly written as a long using:

Output
L

Example:

Java
long distance = 9_000_000_000L;

Although lowercase l is syntactically possible in contexts where the literal is valid, avoid it:

Java
100l

because lowercase l can look like digit 1.

Prefer:

Java
100L

Production readability matters.


39. Floating-Point Literals#

Examples:

Java
double price = 99.95;
Java
double rate = 0.05;

By default, a decimal floating-point literal such as:

Java
3.14

is normally of type double.

If you want a float literal, use F or f:

Java
float rate = 3.14F;

This is a common mistake:

Java
float rate = 3.14;

The literal is a double, so that assignment normally causes a compile-time type mismatch.

Correct:

Java
float rate = 3.14F;

40. Boolean Literals#

Java has exactly two boolean literal values:

Java
true
false

Example:

Java
boolean loggedIn = true;
boolean deleted = false;

Unlike some languages, Java does not normally treat integer values such as 0 and 1 as interchangeable with boolean.

This is invalid:

Java
boolean active = 1;

41. Character Literals#

A char literal uses single quotes:

Java
char grade = 'A';

Examples:

Java
'a'
Java
'7'
Java
'#'

A char represents one UTF-16 code unit.

For basic learning, you can think of it as representing a single character-like value, but Unicode reality is more nuanced because some Unicode characters require surrogate pairs.

That deeper Unicode topic belongs elsewhere.


42. Character vs String#

This is very important.

Character literal#

Java
'A'

uses single quotes.

String literal#

Java
"A"

uses double quotes.

They are different types.

Java
char letter = 'A';
String text = "A";

Wrong:

Java
char letter = "A";

Wrong:

Java
String text = 'A';

Mental rule:

Output
'...'  → char literal
"..."  → String literal

43. Escape Sequences#

How do you include a newline or quote inside a literal?

Java provides escape sequences.

Examples:

Java
System.out.println("Hello\nJava");

Output:

Output
Hello
Java

Useful escapes include:

EscapeMeaning
\nNew line
\tTab
\"Double quote
\'Single quote
\\Backslash
\rCarriage return
\bBackspace
\fForm feed

Example:

Java
String message = "He said, \"Hello\".";

44. String Literals#

Example:

Java
String language = "Java";

"Java" is a string literal.

An important later topic is that String is a class and Java manages string literals using special runtime mechanisms, including the string pool.

We do not need that mechanism to understand syntax today.

For now:

Text enclosed in double quotes forms a string literal.

45. Text Blocks#

Modern Java also supports text blocks for convenient multiline strings.

Example:

Java
String json = """
        {
          "name": "Java",
          "type": "language"
        }
        """;

Text blocks became a permanent Java language feature in Java 15.

They are useful for multiline content such as:

  • JSON
  • SQL
  • HTML
  • formatted text

Do not confuse a text block with an ordinary code block.

A text block still represents a String.


46. The null Literal#

Consider:

Java
String name = null;

null indicates the absence of an object reference.

It is not:

Output
""

and it is not:

Output
"null"

Compare:

Java
String a = null;
String b = "";
String c = "null";

These represent different things.

Output
a → no String object reference
b → reference to an empty String
c → reference to a String containing four characters: n u l l

This difference becomes extremely important when we study objects and exceptions.


47. Is -10 an Integer Literal?#

This is a good advanced interview detail.

You may write:

Java
int number = -10;

It looks like -10 is one literal.

Conceptually, Java normally treats the minus sign as a unary operator applied to a positive numeric literal:

Output
- 10
↑ ↑
| └── integer literal
└──── unary minus operator

There are specification-level edge rules around minimum representable integer values, but for ordinary development the main conceptual point is:

The sign can be an operator rather than part of the literal token itself.

48. Comments#

As programs grow, developers sometimes need explanatory text that is not executable Java logic.

That is where comments are useful.

Java provides three common comment forms:

  1. single-line comments
  2. traditional/block comments
  3. documentation comments

49. Single-Line Comments#

Syntax:

Java
// comment

Example:

Java
int total = 100; // total amount before tax

Or:

Java
// Calculate final amount
int finalAmount = total + tax;

The comment continues until the end of the line.


50. Multi-Line Comments#

Syntax:

Java
/*
comment
*/

Example:

Java
/*
This section calculates the invoice amount.
Tax calculation will be extracted later.
*/
int finalAmount = total + tax;

These comments can span multiple lines.


51. Documentation Comments#

Syntax:

Java
/**
 * Documentation text.
 */

These are commonly called Javadoc comments.

Example:

Java
/**
 * Calculates the total price.
 *
 * @param price base price
 * @param tax tax amount
 * @return total price
 */
public static double calculateTotal(double price, double tax) {
    return price + tax;
}

Javadoc tooling can use structured documentation comments to generate API documentation.


52. Comment Types Comparison#

TypeSyntaxMain Purpose
Single-line// ...Short explanation
Block/ ... /Longer internal comment
Javadoc/** ... */API/documentation generation

53. Comments Are Not an Excuse for Bad Code#

Consider:

Java
int x = p * q;

Then a developer writes:

Java
// x means total amount, p means unit price, q means quantity
int x = p * q;

A better solution may simply be:

Java
int totalAmount = unitPrice * quantity;

The code explains itself.

Decision rule:

Output
Can clear naming remove the need for the comment?
        ↓
       Yes
        ↓
Prefer clearer code

Useful comments often explain:

  • why a decision exists
  • non-obvious constraints
  • business reasoning
  • compatibility workarounds
  • unusual algorithms
  • security implications

Weak comments simply repeat the code.


54. Comment Rot#

Suppose:

Java
// Apply 10% discount
double discount = price * 0.15;

The comment says 10%.

The code applies 15%.

Now the comment is harmful.

This is called a form of comment drift or comment rot.

Production rule:

Comments must be maintained just like code.

55. Block Comments Do Not Simply Nest#

Do not assume you can safely write:

Java
/*
Outer comment

/*
Inner comment
*/

*/

Traditional block comments do not work as recursively nested comment containers.

This can cause surprising syntax errors.

If temporarily disabling large blocks of code, version control is usually a better long-term mechanism than building deeply commented-out code sections.


56. Comment Markers Inside Strings Are Text#

Consider:

Java
String url = "https://example.com";

The:

Output
//

inside the string does not start a Java comment.

Similarly:

Java
String value = "/* not a comment */";

Those characters belong to the string literal.

The lexer interprets them according to their surrounding syntax.


57. Naming Conventions#

Java syntax tells you what names are legal.

Naming conventions tell you what names are normally readable and professional.

That distinction is important.

This may be legal:

Java
class employee {
}

But conventional Java style prefers:

Java
class Employee {
}

Let's learn the normal conventions.


58. Class Naming#

Classes normally use UpperCamelCase or PascalCase.

Examples:

Java
Employee
Java
BankAccount
Java
OrderService
Java
PaymentProcessor

Avoid vague names such as:

Output
Data
Manager
Helper
Stuff
Object1

unless they genuinely describe the responsibility.

Prefer names that express the domain role.


59. Method Naming#

Methods usually use lowerCamelCase.

Examples:

Java
calculateSalary()
Java
sendEmail()
Java
findEmployee()
Java
processPayment()

Methods usually describe actions, so verb-oriented names are natural.

Weak:

Java
data()

Stronger:

Java
loadCustomerData()

assuming that accurately describes the behavior.


60. Variable Naming#

Variables normally use lowerCamelCase.

Examples:

Java
employeeName
Java
totalAmount
Java
orderCount
Java
isActive

A variable should communicate what its value represents.

Compare:

Java
int x = 5;

with:

Java
int retryCount = 5;

The second requires less mental decoding.


61. Boolean Names#

For booleans, names often read naturally as conditions:

Java
boolean active;
boolean isActive;
boolean hasPermission;
boolean canRetry;
boolean paymentCompleted;

Choose a style consistent with your project's conventions and framework conventions.

The important goal is that code reads naturally:

Java
if (hasPermission) {
}

62. Constant Naming#

Constants commonly use uppercase words separated by underscores:

Java
MAX_RETRY_COUNT
Java
DEFAULT_TIMEOUT
Java
API_VERSION

Example:

Java
static final int MAX_RETRY_COUNT = 3;

You will study static final later.

For now, recognize the naming convention:

Output
UPPER_SNAKE_CASE

63. Package Naming#

Package names normally use lowercase.

Example:

Java
com.example.payment

Production organizations often use reverse-domain-style package roots:

Output
com.company.product

For example:

Java
package com.codelangsai.training;

Avoid:

Java
package Com.CodeLangsAI.Training;

Lowercase package naming is the conventional Java style.


64. Good Names vs Short Names#

Short names are not automatically bad.

Inside a tiny loop:

Java
for (int i = 0; i < 10; i++) {
}

i is familiar and locally obvious.

But in business logic:

Java
double a = p * q;

forces readers to decode intent.

Prefer:

Java
double totalAmount = unitPrice * quantity;

Decision rule:

Output
Very small conventional local context?
→ short name can be reasonable

Business/domain meaning?
→ choose descriptive name

65. Avoid Encoding the Type Into Every Name#

Names such as:

Output
strEmployeeName
intEmployeeAge
dblSalary

are usually unnecessary in modern Java.

Your IDE and Java's static type system already expose the type.

Prefer:

Java
String employeeName;
int employeeAge;
double salary;

This keeps the name focused on business meaning.


66. Case Sensitivity#

We have already seen hints of this.

Java is case-sensitive.

These identifiers are different:

Output
age
Age
AGE

These are also different:

Output
main
Main
MAIN

Likewise:

Java
String name = "Java";
System.out.println(name);

works.

But:

Java
String name = "Java";
System.out.println(Name);

does not refer to the same variable.


67. Case Sensitivity and Java APIs#

Java's standard API names must also use exact case.

Correct:

Java
System.out.println("Hello");

Wrong:

Java
system.out.println("Hello");

Wrong:

Java
System.Out.println("Hello");

Wrong:

Java
System.out.Println("Hello");

Names must match their actual declarations.


68. Case-Sensitive Naming Trap#

This can technically compile:

Java
int amount = 10;
int Amount = 20;
int AMOUNT = 30;

They are three distinct identifiers.

But intentionally using names that differ only by case can make production code unnecessarily confusing.

Avoid:

Java
customer
Customer
CUSTOMER

for unrelated local variables in the same context.

Technical legality does not guarantee maintainability.


69. Source File Structure#

Now that we understand classes and names, we can zoom out again.

A conventional Java compilation unit can contain structural elements such as:

Output
package declaration
        ↓
import declarations
        ↓
top-level type declarations

Example:

Java
package com.example.app;

import java.util.List;

public class EmployeeService {
}

We are not studying packages and imports deeply in this chapter.

They appear here because they are part of ordinary Java source-file structure.


70. Package Declaration Placement#

When present, the package declaration appears before ordinary import declarations and top-level type declarations.

Example:

Java
package com.example.app;

import java.util.List;

public class Demo {
}

Not:

Java
import java.util.List;

package com.example.app;

public class Demo {
}

The second arrangement is not valid ordinary Java compilation-unit structure.


71. Imports Come Before Top-Level Class Declarations#

Typical structure:

Java
package com.example.app;

import java.util.ArrayList;
import java.util.List;

public class Demo {
}

You do not normally place an import inside a method:

Java
public class Demo {
    public static void main(String[] args) {
        // import java.util.List;  // invalid location
    }
}

Imports belong to the compilation-unit structure, not inside the method body.


72. Class Name and File Name#

Suppose you declare:

Java
public class Employee {
}

The normal source file should be named:

Output
Employee.java

This is the familiar Java rule used by ordinary file-based compilation.

Wrong for ordinary javac source organization:

Output
Person.java

containing:

Java
public class Employee {
}

You will normally get a compiler diagnostic telling you that the public class should be declared in a file named Employee.java.


73. Why Does the Naming Rule Matter?#

It gives a predictable relationship:

Output
Employee.java
        ↓
public class Employee

This makes large codebases navigable.

If you see:

Output
PaymentService.java

you can reasonably expect its principal public top-level type to be:

Java
public class PaymentService {
}

This convention is important when projects contain thousands of source files.


74. Multiple Classes in One Source File#

Can one .java file contain multiple top-level classes?

Yes, subject to Java's source-file/type rules.

Example:

Java
public class Application {
    public static void main(String[] args) {
        Helper.printMessage();
    }
}

class Helper {
    static void printMessage() {
        System.out.println("Hello");
    }
}

Save this as:

Output
Application.java

The source file contains:

Output
Application
Helper

After compilation, you may get separate class files:

Output
Application.class
Helper.class

Important mental model:

One source file can contain multiple top-level type declarations; compiled classes are separate runtime/class-file concepts.

75. Can There Be Two Public Top-Level Classes in One Normal .java File?#

Do not organize ordinary source code like this:

Java
public class Employee {
}

public class Department {
}

A conventional file cannot simultaneously satisfy the file-name requirement for both:

Output
Employee.java
Department.java

Therefore normal Java development uses one public top-level type per matching source file.

Prefer:

Output
Employee.java
Department.java

with one principal public type in each file.


76. Production Recommendation for Multiple Top-Level Classes#

Even when multiple package-private top-level classes are technically legal, do not overuse the technique.

Compare:

Output
PaymentService.java
├── PaymentService
├── Validator
├── Formatter
├── PaymentRule
└── RetryPolicy

against separate well-named files.

In a large project, separate files often improve:

  • discoverability
  • navigation
  • code ownership
  • testing
  • merge behavior
  • maintainability

A tiny tightly coupled helper can sometimes justify sharing a file, but it should be a deliberate decision.


77. A Modern Source-File Nuance#

Modern Java source-file launch mode and compact source files introduce additional rules and exceptions compared with the traditional "one named public class matching the file" beginner model.

For example, Java 25 compact source files can omit an explicit class declaration:

Java
void main() {
    System.out.println("Hello");
}

The compiler treats a compact source file as having an implicitly declared class, and modern Java can launch it directly. Oracle documents this feature as a way to make introductory programs less ceremonious.

This does not make traditional class-based source organization obsolete.

Enterprise Java still heavily relies on explicitly declared named classes and structured packages.

For interviews, know both:

Output
Traditional structured Java
→ explicit class
→ matching source-file conventions

Modern compact Java
→ may use compact source files
→ implicitly declared class

78. Command-Line Arguments#

We previously saw:

Java
public static void main(String[] args)

Now we can use it.

Create:

Java
public class Greeting {
    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

Compile:

Terminal
javac Greeting.java

Run:

Terminal
java Greeting Dattatray

Output:

Output
Dattatray

79. What Is Inside args?#

Run:

Terminal
java Greeting Dattatray Sabne

Conceptually Java provides:

Output
args[0] = "Dattatray"
args[1] = "Sabne"

Important:

The class name itself is not stored as args[0].

The arguments are the values supplied after the launch target.


80. All Command-Line Arguments Arrive as Strings#

Suppose:

Terminal
java Demo 10 20

The program receives text representations:

Output
"10"
"20"

not automatically:

Output
10
20

as integer values.

If you need numeric computation, conversion is required.

Example:

Java
public class AddNumbers {
    public static void main(String[] args) {
        int first = Integer.parseInt(args[0]);
        int second = Integer.parseInt(args[1]);
        System.out.println(first + second);
    }
}

Run:

Terminal
java AddNumbers 10 20

Output:

Output
30

A new concept appeared here:

Java
Integer.parseInt(...)

We are not studying wrapper classes today.

For now, just understand its role:

It converts suitable numeric text such as "10" into an int value.

81. Missing Command-Line Argument#

Look at:

Java
public class Greeting {
    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

Now run:

Terminal
java Greeting

There is no element at index 0.

The program can fail at runtime with an array index error.

A safer version checks the array length:

Java
public class Greeting {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Please provide your name.");
            return;
        }
        System.out.println("Hello, " + args[0]);
    }
}

You have not yet studied if and arrays deeply, so focus on the production lesson:

External input must not be assumed to exist or be valid.

82. Values Containing Spaces#

At the shell level, a value containing spaces normally needs quoting.

For example:

Terminal
java Greeting "Dattatray Sabne"

can result in one argument:

Output
args[0] = "Dattatray Sabne"

Whereas:

Terminal
java Greeting Dattatray Sabne

normally supplies two arguments:

Output
args[0] = "Dattatray"
args[1] = "Sabne"

Exact command-shell quoting behavior belongs to your operating environment, but Java receives the resulting argument strings.


83. Command-Line Argument Flow#

Output
Terminal
   │
   │ java Report monthly 2026
   ↓
Java Launcher
   ↓
main(String[] args)
   ↓
args[0] = "monthly"
args[1] = "2026"
   ↓
Program logic

This is a simple but extremely useful model.


84. A Complete Beginner Program#

Now combine what we know.

Java
public class StudentApplication {
    public static void main(String[] args) {
        String studentName = "Amit";
        int score = 85;
        System.out.println("Student: " + studentName);
        System.out.println("Score: " + score);
    }
}

Output:

Output
Student: Amit
Score: 85

Let's read this structurally.

Output
public class StudentApplication
→ declares the class

{
→ begins class body

public static void main(String[] args)
→ traditional program entry method

{
→ begins method block

String studentName = "Amit";
→ local variable declaration using String literal

int score = 85;
→ local variable declaration using integer literal

System.out.println(...)
→ executable output statements

}
→ ends method body

}
→ ends class body

You should now be able to read the structure rather than merely recognize the code visually.


85. Compilation and Execution Flow#

When you run:

Terminal
javac StudentApplication.java

the Java compiler performs several kinds of work.

A simplified mental model:

Output
Source characters
      ↓
Lexical processing
      ↓
Tokens
      ↓
Syntax analysis
      ↓
Type / semantic checks
      ↓
Bytecode generation
      ↓
.class file

Then:

Terminal
java StudentApplication

causes runtime startup:

Output
java launcher
      ↓
JVM starts
      ↓
class loading/linking/initialization as required
      ↓
launchable main method selected
      ↓
program executes

Do not try to memorize all JVM stages yet.

The useful distinction is:

Output
Compilation
→ Is the source structurally and semantically acceptable to the compiler?

Execution
→ What happens when compiled/launchable code actually runs?

86. Compile-Time Error vs Runtime Error#

This distinction becomes essential.

Compile-time example#

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println("Hello")
    }
}

Missing:

Output
;

The compiler rejects the source.

Runtime example#

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println(args[0]);
    }
}

This can compile.

But running without arguments:

Terminal
java Demo

can fail at runtime.

Mental model:

Output
Compile-time problem
→ program cannot successfully compile

Runtime problem
→ program compiled, but execution encounters a failure

87. Syntax Error Can Be Reported After the Real Mistake#

Suppose you forget a closing quote:

Java
System.out.println("Hello);
System.out.println("Java");

The compiler may report diagnostics that seem to point at code after the place where you actually made the mistake.

Why?

Because once the parser loses the expected structure, later tokens no longer fit the grammar.

Debugging rule:

When you see a syntax error, inspect the reported location and the immediately preceding code.

This is especially useful for:

  • missing "
  • missing )
  • missing }
  • missing ;

88. Common Mistakes#

Now that the foundation is complete, let's deliberately study mistakes you are likely to make.


Mistake 1 — Wrong main Case#

Risky/Incorrect for traditional entry-point intention#

Java
public static void Main(String[] args) {
}

Why developers make it#

Because Main looks visually similar to main.

Consequence#

It is a different method name and is not the classic method named main.

Preferred#

Java
public static void main(String[] args) {
}

Debugging clue#

The code may compile as a normal method but the launcher cannot use it as the expected entry point.

Interview connection#

Java identifiers are case-sensitive.


Mistake 2 — File Name Does Not Match Public Class#

File#

Output
Demo.java

Content#

Java
public class Application {
}

Consequence#

Ordinary file-based compilation typically reports that Application should be declared in Application.java.

Correct#

Output
Application.java

Mistake 3 — Missing Semicolon#

Wrong:

Java
int age = 36

Correct:

Java
int age = 36;

Category#

Compile-time syntax error.


Mistake 4 — Semicolon After if#

Wrong for intended conditional behavior:

Java
if (active);
{
    System.out.println("Active");
}

Correct:

Java
if (active) {
    System.out.println("Active");
}

Risk#

Logical behavior can differ dramatically from what indentation suggests.


Mistake 5 — Unbalanced Braces#

Wrong:

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println("Hello");
}

The source structure is incomplete.

Preferred formatting makes brace pairing obvious:

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

Mistake 6 — Identifier Starts With a Digit#

Wrong:

Java
int 2count = 10;

Correct:

Java
int count2 = 10;

Mistake 7 — Keyword Used as Identifier#

Wrong:

Java
int class = 10;

Correct:

Java
int classCount = 10;

Mistake 8 — Wrong Quote Type#

Wrong:

Java
String language = 'Java';

Correct:

Java
String language = "Java";

And:

Java
char initial = 'J';

Mistake 9 — Case Mismatch#

Wrong:

Java
String language = "Java";
System.out.println(Language);

Correct:

Java
String language = "Java";
System.out.println(language);

Mistake 10 — Assuming Command-Line Arguments Exist#

Risky:

Java
System.out.println(args[0]);

without validating argument count.

Preferred:

Java
if (args.length == 0) {
    System.out.println("Missing argument");
    return;
}
System.out.println(args[0]);

Mistake 11 — Assuming Numeric Arguments Are Already Numbers#

Wrong idea:

Output
java Calculator 10 20

does not magically make args[0] an int.

Conversion is required.


Mistake 12 — Overusing Comments#

Weak:

Java
// Increase count by 1
count++;

The comment contributes almost nothing.

Comments should explain meaningful intent that the code cannot communicate clearly by itself.


89. Frequently Confused Concepts#

Statement vs Block#

DimensionStatementBlock
PurposeRepresents an executable language step/constructGroups block statements
Examplecount++;{ count++; }
DelimiterDepends on statement kind{ }
Scope impactDepends on constructCan introduce local scope

Decision rule:

Output
Need one executable instruction?
→ statement

Need grouped statements / scope / body?
→ block

Identifier vs Keyword#

IdentifierKeyword
Programmer or API-defined nameLanguage-defined token
employeeNameclass
Often selectable by developerHas fixed grammatical role
Can identify variables/classes/methodsCannot normally be reused as an ordinary identifier

char vs String#

charString
Primitive typeClass/reference type
'A'"A"
Single UTF-16 code unitSequence of characters/code units
Single quotesDouble quotes

null vs Empty String#

null""
No object referenceA real String value
Cannot directly invoke instance methods through itCan invoke String methods
Not a String objectString object/reference

Source File vs Class#

Source FileClass
Physical/logical source compilation unitJava type
Often .javaDeclared using class
Can contain multiple top-level typesUsually compiles into corresponding class metadata/class files

90. Production Perspective#

This chapter appears basic, but production problems often begin with apparently small details.

A professional Java developer should care about:

Readability#

Prefer:

Java
double totalAmount = unitPrice * quantity;

over:

Java
double x = p * q;

when domain meaning matters.

Consistent formatting#

Use the formatter configured by the project.

Do not manually invent a different style in every file.

Predictable file organization#

Prefer a public top-level class in its clearly named source file.

Clear package structure#

Packages should reflect stable logical boundaries rather than random folders.

Input validation#

Never blindly trust command-line or external input.

Useful comments#

Explain reasoning, not obvious syntax.

Version awareness#

Do not claim older Java launch rules are universal across every modern Java version.

Tooling#

Use:

  • compiler diagnostics
  • IDE inspections
  • formatters
  • static analysis
  • version control
  • automated build tools

to catch structural and style problems early.


91. Developer Mental Model#

When you open a Java source file, mentally read it in this order:

Output
1. Which package?
        ↓
2. Which imports?
        ↓
3. Which top-level type?
        ↓
4. What is the class responsibility?
        ↓
5. Which fields/methods?
        ↓
6. Where does execution enter?
        ↓
7. Which blocks control scope?
        ↓
8. Which statements perform work?
        ↓
9. Which identifiers carry business meaning?
        ↓
10. Which literals/configured values are being used?

This is how source code becomes understandable architecture rather than visual noise.


92. Complete Revision#

One-Line Definitions#

Java source file: A file containing Java source code, normally ending in .java.

Class: A named Java type used to organize state and behavior.

Class declaration: The syntax that introduces a class, for example class Employee { }.

Classic main method: The familiar application entry point public static void main(String[] args).

Statement: A Java language construct representing an executable program step or control action.

Block: A sequence of block statements enclosed in { }.

Identifier: A valid Java name identifying a program element.

Keyword: A language-reserved token with special grammatical meaning.

Literal: Source-code syntax representing a particular value.

Comment: Non-executable source text used primarily for explanation or documentation.

Command-line argument: Text passed to a launched program and made available to its entry method.


93. Syntax Revision#

Basic class#

Java
public class Demo {
}

Traditional program#

Java
public class Demo {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

Variable declarations#

Java
int age = 36;
String name = "Amit";
boolean active = true;
char grade = 'A';

Single-line comment#

Java
// comment

Block comment#

Java
/*
comment
*/

Javadoc#

Java
/**
 * Documentation.
 */

94. Important Rules#

  1. Java is case-sensitive.
  2. Traditional source files use the .java extension.
  3. A public top-level class normally matches the source file name.
  4. One source file may contain multiple top-level classes.
  5. Ordinary Java project organization normally uses one public top-level type per matching file.
  6. main and Main are different identifiers.
  7. Many statements require ;, but not every Java line does.
  8. Curly braces define structural boundaries and often scope.
  9. Identifiers cannot begin with digits.
  10. Keywords cannot normally be used as identifiers.
  11. true, false, and null are literals rather than ordinary keywords.
  12. Character literals use single quotes.
  13. String literals use double quotes.
  14. Command-line arguments arrive as strings.
  15. Accessing a missing args element can fail at runtime.
  16. Modern Java supports additional launchable main forms beyond the classic signature.

95. If You Remember Only 10 Things#

  1. A Java source file normally contains Java type declarations such as classes.
  2. A traditional Java application commonly starts from public static void main(String[] args).
  3. Modern Java also supports newer entry-point forms.
  4. { } reveal program structure and can affect scope.
  5. Do not add semicolons mechanically.
  6. Java identifiers are case-sensitive.
  7. Keywords have language-defined meaning and cannot normally be ordinary identifiers.
  8. Literals directly represent values such as 10, "Java", 'A', true, and null.
  9. Public top-level class names normally match their .java filenames.
  10. Command-line arguments are strings and must be validated before use.

96. Final Knowledge Map#

Output
Java Program Structure and Basic Syntax
│
├── Source File
│   ├── .java
│   ├── package declaration
│   ├── import declarations
│   └── top-level type declarations
│
├── Class Declaration
│   ├── modifiers
│   ├── class keyword
│   ├── class identifier
│   └── class body
│
├── Program Entry
│   ├── classic main()
│   │   ├── public
│   │   ├── static
│   │   ├── void
│   │   ├── main
│   │   └── String[] args
│   └── modern launchable main forms
│
├── Executable Structure
│   ├── statements
│   ├── blocks
│   ├── curly braces
│   └── semicolons
│
├── Names
│   ├── identifiers
│   ├── keywords
│   ├── reserved names
│   ├── case sensitivity
│   └── naming conventions
│
├── Values
│   ├── integer literals
│   ├── floating literals
│   ├── boolean literals
│   ├── char literals
│   ├── String literals
│   ├── text blocks
│   └── null literal
│
├── Comments
│   ├── //
│   ├── /* */
│   └── /** */
│
├── Source-File Rules
│   ├── class/file naming
│   ├── public top-level type
│   ├── multiple classes
│   └── compiled class files
│
└── Command-Line Arguments
    ├── String array
    ├── indexing
    ├── validation
    └── conversion

Practice lab

Prove what you just learned