Working With Java Programs
The classic structure
public class Calculator {
public static void main ( String [] args ) {
System . out . println ( "start" );
}
}
public class Calculator — file must be Calculator.java
static — the JVM can call it without an object
String[] args — command line arguments
The compact form (Java 25) does the same thing:
void main () {
IO . println ( "start" );
}
Both may contain fields and methods:
final double VAT = 0 . 19 ;
double gross ( double net ) { return net * ( 1 + VAT ); }
void main () { IO . println ( gross ( 100 )); }
Note
Compact for scripts and exercises, classic for real projects. The rest of the language is
identical.
Compile and run
java Calculator.java # run a single file directly
javac Calculator.java # produce Calculator.class
java Calculator
javac -d out $( find src -name "*.java" )
java -cp out com.example.Calculator
void main ( String [] args ) {
if ( args . length < 2 ) {
IO . println ( "usage: java Calculator.java <a> <b>" );
return ;
}
var a = Integer . parseInt ( args [ 0 ] );
var b = Integer . parseInt ( args [ 1 ] );
IO . println ( a + b );
}
Reading errors
Compile time — the program never runs:
Calculator.java:5: error: incompatible types: String cannot be converted to int
int x = "hello";
^
Runtime — read the stack trace bottom-up:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Calculator.divide(Calculator.java:12)
at Calculator.main(Calculator.java:5)
Catching exceptions
try {
var n = Integer . parseInt ( input );
IO . println ( 100 / n );
} catch ( NumberFormatException | ArithmeticException e ) {
IO . println ( "bad input: " + e . getMessage ());
} finally {
IO . println ( "always runs" );
}
Unchecked
Checked
base class
RuntimeException
Exception
must be handled
no
yes — catch or throws
typical
NullPointerException, IllegalArgumentException
IOException, SQLException
String read ( Path p ) throws IOException { // pass it up
return Files . readString ( p );
}
throw new IllegalArgumentException ( "age must not be negative: " + age );
Details in chapter 12 .
Files
import java.nio.file.Files ;
import java.nio.file.Path ;
var path = Path . of ( "notes.txt" );
Files . writeString ( path , "line 1\nline 2\n" );
Files . writeString ( path , "line 3\n" , StandardOpenOption . APPEND );
var content = Files . readString ( path );
for ( var line : Files . readAllLines ( path )) IO . println ( line );
Large files — stream them, and close the stream:
try ( var lines = Files . lines ( Path . of ( "big.log" ))) {
lines . filter ( l -> l . contains ( "ERROR" )). limit ( 10 ). forEach ( IO :: println );
}
try (...) closes everything automatically, even when an exception is thrown:
try ( var writer = Files . newBufferedWriter ( Path . of ( "out.txt" ))) {
writer . write ( "hello" );
writer . newLine ();
}
Paths:
var p = Path . of ( "data" , "2025" , "report.csv" );
Files . exists ( p ); Files . isDirectory ( p ); Files . size ( p );
Files . createDirectories ( p . getParent ());
Files . deleteIfExists ( p );
p . getFileName (); p . toAbsolutePath ();
UTF-8 is the default since Java 18 — no charset arguments needed.
A complete program
import java.nio.file.* ;
void main ( String [] args ) {
if ( args . length == 0 ) {
IO . println ( "usage: java WordCount.java <file>" );
return ;
}
try {
var words = Files . readString ( Path . of ( args [ 0 ] )). toLowerCase (). split ( "\\W+" );
var counts = new java . util . HashMap < String , Integer > ();
for ( var w : words ) {
if ( ! w . isBlank ()) counts . merge ( w , 1 , Integer :: sum );
}
counts . entrySet (). stream ()
. sorted (( a , b ) -> b . getValue () - a . getValue ())
. limit ( 10 )
. forEach ( e -> IO . println ( "%-15s %d" . formatted ( e . getKey (), e . getValue ())));
} catch ( java . io . IOException e ) {
IO . println ( "cannot read file: " + e . getMessage ());
}
}
★ Exercises
Run the word counter above on any text file.
Add a second argument: how many words to print.
Copy a file, adding line numbers.
What happens on a missing file? Catch it and print something useful.
Read a CSV of name;age;city into a list of records.
Trigger a NullPointerException on purpose and read the stack trace.