English
Summary
Conclusions
Generics move type compatibility checks from runtime to compile time: an Object container requires casts, while Box<T> connects writing and reading to one type argument. Type parameters can be declared in classes, records, and methods; diamond and type argument inference shorten the syntax without disabling typing. Bounds such as <T extends Comparable<? super T>> describe the capabilities an algorithm needs but cannot provide guarantees the type does not actually offer. Ordinary generics are invariant, while arrays are covariant and check writes only at runtime. Wildcards ? extends and ? super express data flow direction through the PECS principle, while wildcard capture lets a helper method name an unknown type. Type erasure prevents creating new T() or new T[], overloading methods that coincide after erasure, or declaring a generic subclass of Throwable. Raw types and generic varargs weaken checks, so unchecked operations should be localized and justified by an invariant. Type safety does not replace domain validation, and a generic API's contract is checked both with tests and with negative compilation examples.
Self-check questions
- Why does an Object container require casts?
- How does a type parameter differ from a type argument?
- What is the scope of a static generic method's parameter?
- Why does Comparable often use super?
- How does generics invariance differ from arrays?
- Which operations do extends and super allow?
- When is wildcard capture needed?
- What is erased, and what remains in metadata?
- Why does the compiler generate a bridge method?
- Why should you not casually return an internal E[] to the client?
- What exactly does SafeVarargs promise?
- How do you test a contract with a negative compilation example?