# From C++ — `#include` and `import` are different kinds of thing

Most wrong guesses about the Java build come from reading `import` as `#include`. They are not the
same mechanism, and almost nothing you know about include hygiene carries over.

## The two lines, side by side

**C++**

```cpp
#include <vector>
```

The preprocessor opens `<vector>`, pastes its entire text into your translation unit, and hands the
result to the compiler. Consequences you have absorbed as facts of life:

- The file is genuinely read, costing compile time, once per translation unit.
- Include it twice and you get redefinition errors. Hence `#pragma once`.
- Order matters. An include depending on a macro defined above it behaves differently further down.
- Forgetting it is a hard error even when the library is installed and linked.
- What you can name is exactly what got pasted.

**Java**

```java
import java.util.List;
```

Nothing is opened at this line and nothing is pasted. It is one statement to the compiler: for the
rest of this file, the bare name `List` means `java.util.List`. Every consequence above evaporates.

| C++ `#include` | Java `import` |
|---|---|
| Textual paste of a file | A name-to-name alias, scoped to one file |
| Needs an include guard | Importing twice is legal and does nothing |
| Order-sensitive | Order-insensitive; place them anywhere above the type |
| Required to use the type | **Optional.** You may always write the full name |
| Costs compile time per inclusion | Costs nothing |
| Can bring in macros, templates, anything | Can bring in only a type name |

The one-line proof, from the worked example:

```java
List<String> viaImport()             { return List.copyOf(freeSpotIds); }
java.util.List<String> viaFullName() { return java.util.List.copyOf(freeSpotIds); }
```

Both methods compile. Both return the same runtime class, which `Main` verifies and prints as
`one runtime type: true`. Delete the import at the top and only the first one breaks. An `import`
is a typing convenience, not a dependency declaration.

The C++ construct it resembles is:

```cpp
using std::vector;      // a scoped name alias, no textual paste
```

Except `using` still needs the `#include` first. Java has no step corresponding to the `#include`.

## What actually finds a type

The paths, and only the paths.

**C++**

```
g++ -I include -c SpotBoard.cpp -o SpotBoard.o    # -I: where headers are
g++ SpotBoard.o Main.o -o app                     # a separate link step
```

**Java**

```
javac -d out *.java        # -d: where .class output goes
java -cp out Main          # -cp: where to find .class files. No link step, ever.
```

- **`-d out`** is the output directory, with package subdirectories created as needed. Without
  `-d`, class files land beside their sources, which is what you want approximately never.
- **`-cp out`** (identical to `-classpath`) is the search path for compiled classes. Entries are
  separated by `;` on Windows and `:` elsewhere. That is the one genuinely platform-specific build
  detail.
- **`Main`** at the end is a class name, not a filename. The launcher resolves it against the
  classpath. `java -cp out Main.class` and `java -cp out out/Main.class` both fail.

There is no object-file stage and no linker. A `.class` file loads lazily, by name, the first time
it is touched at run time. That is why a missing class can surface as a run-time
`NoClassDefFoundError` in a program that compiled without a murmur.

## No compilation order, and no need to list every file

**C++** — compile each `.cpp` separately, link the objects. Miss one and the linker tells you, late.

**Java** — name the sources you care about and `javac` follows the references:

```
javac -d out Main.java        # SpotBoard.java sits beside it, unnamed
```

That produces both `out/Main.class` and `out/SpotBoard.class`. `javac` needed `SpotBoard` and
searched its sourcepath, which defaults to the classpath, which defaults to the current directory.
It found `SpotBoard.java` and compiled it too. So `javac -d out *.java` is a safe habit rather than
a requirement, and there is no `Makefile`-shaped question about ordering.

## Packages, and the namespace that is also a directory

**C++ — a namespace is pure naming**

```cpp
namespace dojo {
    class SpotBoard { };
}
```

Any file, any directory, any nesting, split across as many files as you like. The filesystem has no
opinion.

**Java — the package declaration binds the name to a path**

```java
package dojo;

public class SpotBoard { }
```

Two consequences the compiler and launcher both enforce:

1. `-d out` puts the result at `out/dojo/SpotBoard.class`, never `out/SpotBoard.class`.
2. The class's real name is now `dojo.SpotBoard`. `java -cp out Main` fails with
   `Could not find or load main class Main`; you need `java -cp out dojo.Main`.

Unlike a namespace, a package cannot be reopened per file the way `namespace dojo { }` can be
scattered. One `package` line, at the top, covering the whole file. There is also no nesting
relationship: `dojo.detail` is a different package, with no special access to `dojo`.

## Why this project uses the default package

Omit the `package` line and the class lands in the default, unnamed package. One property makes
that a deliberate choice rather than a shortcut:

```java
// Main.java
package dojo;

public class Main {
    public static void main(String[] args) {
        SpotBoard board = new SpotBoard();     // SpotBoard is in the default package
    }
}
```

```
Main.java:12: error: cannot find symbol
        SpotBoard board = new SpotBoard();
        ^
  symbol:   class SpotBoard
  location: class Main
```

**A class in the default package is invisible to every named package.** No import reaches it,
because there is no package name to write after `import`. A codebase therefore uses the default
package throughout or not at all.

For twelve-minute drills, that is the property you want:

- Sources sit flat in one directory. No `src/main/java/com/example/...` to create first.
- `javac -d out *.java` then `java -cp out Main`, unchanged, every time.
- Zero imports between your own classes, so no timed drill loses a minute to an import.
- The hidden test suite drops in beside your files and sees your classes with no ceremony.

Real production Java uses named packages, and you will want them the moment a codebase passes
thirty files. Nothing here is an argument for flat layout in real work. It is an argument for flat
layout in a stopwatch exercise.
