To know if a program is correct, one needs specifications that say what the program is intended to do or intended not to do. But how does one write such specifications for object-oriented software with subtypes and dynamically-dispatched methods, and how does one reason about the semantics of such programs? These lectures give the semantics of a language with modern object-oriented features and consider several issues in the specification of object-oriented programs, including some recently formalized methodology. The lectures also include a demo of a programming tool that reasons semantically about programs and uses an automatic theorem prover to find common errors, and go through some issues in designing such a checker.