# NOTES — four files, and the four errors that teach them

Four files, one program. Compile and run it exactly like this, from the directory holding
the sources:

```
.toolchain\jdk-21\bin\javac.exe -d out *.java
.toolchain\jdk-21\bin\java.exe -cp out Main
```

Real output, from this code:

```
Greeter says: Hello, Pratyush.
Shouter says: HELLO PRATYUSH!
```

Note what `out/` contains afterwards:

```
out/Greeter.class
out/Greeting.class
out/Main.class
out/Punctuation.class
out/Shouter.class
```

**Five class files from four source files.** `Punctuation.class` exists on its own even
though `Punctuation` never had a file of its own. That is the first thing to internalise:
the *class file* is always one-per-class. Only the *source file* is allowed to hold more
than one, and only for non-public types.

---

## `Greeting.java`

```java
public interface Greeting {

    String greet(String name);
}
```

**`public interface Greeting`** — the filename rule is not about classes, it is about public
*types*. An interface, an enum, a record and a class are all types, and all four obey it. The
invariant: given a public type name, `javac` can compute the file to open without searching. That
is why the rule exists, and why the search in J2 is cheap.

**`String greet(String name);`** — no `public`, no `abstract`, no `virtual`, no `= 0`, no
trailing `const`. Interface methods are already public and abstract. Writing
`public abstract String greet(String name);` compiles and is redundant; a reviewer reads it as
"has not written Java before". Nothing technical is avoided by leaving them off. The signal you
send is.

There is also no virtual destructor, because there are no destructors. In C++ omitting
`virtual ~Greeting()` on a polymorphic base leaks. Here there is nothing to leak; cleanup of
*resources* (not memory) is `try`-with-resources, which is J9.

---

## `Greeter.java` — the file that holds two classes

```java
public class Greeter implements Greeting {

    private final String punctuation;
```

**`implements`, not `extends`.** `extends` is for the one class you inherit from; `implements`
is for the interfaces you satisfy, and there may be many. Writing `extends Greeting` here gives
you `error: no interface expected here`, which reads as nonsense until you know the two keywords
are not interchangeable.

**`private final String punctuation;`** — `final` says this reference is assigned exactly once
and never reassigned. It is narrower than C++ `const`: it constrains the variable, not the
object. `private final List<String> xs` still lets anyone holding the reference call
`xs.add(...)`. Here the field is a `String`, which is immutable, so `final` is enough. Reading
`final` as `const` is one of the traps in the bridge table; J4 and J6 return to it.

```java
    public Greeter() {
        this.punctuation = Punctuation.calm();
    }
```

**`Punctuation` is declared at the bottom of this same file, below the class using it.** No
forward declaration, no reordering, no header. The invariant `javac` maintains: every type and
member signature is known before any method body is resolved. Order carries no information.
The C++ bug that cannot happen here is the compile that succeeds or fails depending on include
order.

**`this.` is optional but not noise.** Java has no `m_` convention and no initialiser list. In
a constructor whose parameter and field share a name, `this.` is the only thing distinguishing
them, so the habit is worth keeping.

```java
    @Override
    public String greet(String name) {
```

**`@Override` earns its keystrokes.** It is checked, exactly like C++11 `override`. Without it,
misspelling `greet` as `greeting` silently adds a *new* method and leaves `Greeting.greet`
unimplemented. The error you then get points at the class declaration, seventeen lines away
from the actual typo:

```
Greeter.java:6: error: Greeter is not abstract and does not override abstract method greet(String) in Greeting
public class Greeter implements Greeting {
       ^
```

With `@Override` present, the error lands on the typo instead:
`method does not override or implement a method from a supertype`.

```java
class Punctuation {

    static String calm() { return "."; }
```

**A second class in the same file, deliberately not public.** This is the direct replacement
for a C++ anonymous namespace. `Punctuation` is *package-private*: visible to every class in
the same package, invisible outside it. Because it is not public, the filename rule does not
apply, so it may share `Greeter.java`.

**`static`, because Java has no free functions.** Every method belongs to a class. A namespace
of helpers becomes a class of `static` methods.

**`private Punctuation() { }`** — the way to say "never instantiate this". Without it Java
supplies a public no-argument constructor for free, and `new Punctuation()` compiles, which is
meaningless for a holder of static helpers.

---

## `Shouter.java` — the file with no imports

```java
public class Shouter implements Greeting {

    @Override
    public String greet(String name) {
        return "HELLO " + name.toUpperCase() + Punctuation.loud();
    }
}
```

**One line here is the whole lesson.** `Punctuation` is declared in `Greeter.java`, a different
file with a different name, and `Shouter.java` names it with no `import` and no `#include`. They
are in the same package, so `javac` already has it.

`Shouter` is public and therefore needs its own file. That is not a style guideline you could
choose to break; it is the compiler.

---

## `Main.java`

```java
    public static void main(String[] args) {
        System.out.println(describe(new Greeter(), "Pratyush"));
```

**The launcher matches this signature exactly.** `public`, `static`, `void`, one `String[]`.
`String... args` also works (same erasure). Anything else compiles fine and then fails at run
time, which is the surprising part — see error 4 below.

**`describe` is called from above its own declaration.** Same rule as `Punctuation`, now inside
a single class.

```java
    static String describe(Greeting greeting, String name) {
```

**The parameter type is the interface.** It is the one design decision in the lesson, and it is
here so the mechanics have a point. `describe` was compiled once and works for implementations
that do not exist yet. `Shouter` was written after it and needed no change to it.

---

# The four errors, produced for real

Every one of these was run against exactly the code above. Recognising them on sight is half of
what fluency means. Read the message, not the colour.

## 1 · Filename does not match the public class

Rename `Greeter.java` to `MyGreeter.java` and recompile:

```
MyGreeter.java:6: error: class Greeter is public, should be declared in a file named Greeter.java
public class Greeter implements Greeting {
       ^
1 error
```

**Read it as a rename instruction.** It names both the file it found the class in and the file
it wanted. Two fixes exist and they are not equivalent: rename the file, or rename the class.
Pick based on which name is right, not on which is less typing.

This is the single most likely error on your first Java day, because C++ imposes no such link
and `greeter.cpp` is perfectly ordinary there.

## 2 · Two public classes in one file

Add `public` to `class Punctuation` in `Greeter.java`:

```
Greeter.java:33: error: class Punctuation is public, should be declared in a file named Punctuation.java
public class Punctuation {
       ^
1 error
```

**Same error text, different cause.** There is no separate "two public classes" diagnostic. The
rule is not "one public class per file"; it is "a public class lives in its matching file". Two
classes cannot both match one filename, so the second one is reported the same way as a
mismatched name.

The fix that keeps the design: leave `Punctuation` package-private. The fix that changes the
design: give it its own file, and now it is part of your public surface.

## 3 · A type the compiler cannot find

Compile `Shouter.java` and `Greeting.java` without `Greeter.java` present:

```
Shouter.java:13: error: cannot find symbol
        return "HELLO " + name.toUpperCase() + Punctuation.loud();
                                               ^
  symbol:   variable Punctuation
  location: class Shouter
1 error
```

**`cannot find symbol` is Java's `undeclared identifier`, and it will be your most frequent
error for a week.** Read all three lines: the caret column, then `symbol:`, then `location:`.

Note it says **`variable Punctuation`**, not `class Punctuation`. `javac` cannot tell which you
meant — `Punctuation.loud()` is equally consistent with a variable named `Punctuation` holding
an object with a `loud()` method. So do not be thrown by the word "variable"; it means "this
name resolves to nothing", nothing more.

The cause is almost never a missing import. It is a missing *file* — the type is not on the
sourcepath or classpath at all. J2 is about where those paths point.

## 4 · A `main` the launcher will not accept

Rename `main` to `start`. This **compiles cleanly** and then:

```
Error: Main method not found in class Main, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
```

**Compile-time silence, run-time failure.** `main` is an ordinary method to `javac`. Only the
`java` launcher cares, and it looks the name up by reflection. So every variation you might reach
for is a legal method and a broken entry point: `void main()`, `static int main(String[] args)`,
`public void main(String[] args)`.

The message is worth reading in full: it prints the signature it wanted. Ignore the JavaFX
line; it is a legacy fallback the launcher mentions unconditionally.
