Object-Oriented Programming with Java and IntelliJ
An Open Education Resource Textbook
Overview
Object-Oriented Programming with Java and IntelliJ is an open educational resource designed for students learning object-oriented software development after completing an introductory programming course. The textbook combines conceptual explanations, Java examples, guided exercises, laboratory activities, and larger programming assignments to help students move from procedural problem solving toward the design of maintainable object-oriented systems.
The material emphasizes more than Java syntax. Testing and defensive programming, including exception handling, are introduced early and treated as a first-class concepts throughout the course. Students learn to model problems using classes and objects, assign responsibilities intentionally, encapsulate state, collaborate through interfaces, and evaluate tradeoffs among inheritance, abstraction, and composition. IntelliJ IDEA is used throughout so that students also develop familiarity with the navigation, debugging, refactoring, testing, and project-management tools found in a professional integrated development environment.
The textbook was developed as an open educational resource to reduce costs for students while allowing course material, examples, and assignments to remain closely aligned. Rather than treating the textbook and laboratory work as separate resources, each chapter introduces concepts that are reinforced through progressively more substantial programming activities.
Topics and Projects
The textbook follows a scaffolded progression in which each topic extends the design skills developed in earlier chapters. Short examples and focused laboratory exercises provide immediate practice, while larger assignments require students to combine multiple concepts into complete applications. The projects therefore serve not only as assessments, but also show students how all concepts interact together throughout the course.
Foundation
The first section for students is more of a "forward for the student" than a chapter. I try to outline reasonable expectations and what it really takes to succeed as a student and as a developer.
The first three chapters of content are a full review of structured programming with Java, an introduction to Unit Testing, and introduces Defensive Programming. Students learn from the very beginning that software testing goes hand-in-hand with writing software, just like a professional developer would work in their career. Other textbooks cover testing near the end of the book, if at all. I cover it as soon as the review is over, and integrate tests into every part of the rest of the course's hands-on labs and projects.
Defensive programming then shows students how to think proactively about what could go wrong and how to work to prevent or detect it early. I took a bit of liberty here to introduce exception handling early by using only the Exception object and politely ignoring the many specific types of exceptions that Java has. Those are then explained when Inheritance is introduced, and exception handling with different types of exceptions is covered then. They are also introduced to logging and then use it in many of the labs and projects in the rest of the course.
Projects
Students begin building the project they will evolve throughout the course, a completely functional Blackjack Card Game. Early in the course they create a Card and Deck class, and see firsthand the ideas of object state and instances vs. classes with the Card, Deck, and 52 different instances of cards.
Students also begin using the debugger as well as writing and using unit tests. They learn early and often the importance of testing their code as they write, and this is reinforced throughout the course with unit tests provided for each Blackjack assignment.
Key Concepts
Lambdas and Streams
One short chapter on Lambdas and Streams is provided. This shows how languages evolve and starts to introduce to students the idea that there is often more than one way to do something, and each approach has tradeoffs. When interfaces are introduced and default methods are discussed, the groundwork for the use-case has already been laid here. Although Lambdas and Streams occupy only a single chapter, they establish ideas that students revisit in later courses. Introducing functional pipelines here provides continuity when students later encounter LINQ and Entity Framework Core in ASP.NET Core.
Projects
Students refactor an application written with traditional processing of collections to use lambdas and streams. Unit tetsts prove the original implementation works correctly, and they see the value of using unit tests to prove that a refactor of code still provides the same functionality to the outside world.
Key Concepts
Inheritance
The real core of the course is covered in the three chapters related to inheritance. Here they are introduced to the concept of "is-a" and "has-a" relationships. The re-use of code and behavior through inheritance is shown.
Exception handling is then revisited with the concept of inheritance applied to the many specific types of exceptions. The order of catch blocks helps reinforce the "is-a" relationship of inheritance also. File processing and JSON/XML serialization with Jackson are also covered in this chapter. Since file processing is one of the most exception-prone operations there is, it is a great way to showcase using exception handling while also introducing important concepts around data persistence.
Finally the concepts of abstract classes and interfaces is covered. By using the JDK's Comparable and Comparator interface along with the Deck of Cards they created earlier in the semester, students get to see how a behavior can be defined without knowing anything about the implementation. I also use this as an opportunity to explain how plugins work, since most students use ad blocking plugins in their web browser.
Projects
Students use UML diagrams to evaluate an existing project with a lot of redundancy, and plan a refactor using inheritance to make the code DRY.
Students implement a Player and Dealer for Blackjack using inheritance. Since the Dealer "is-a" Player, the dealer gets all the player functionality through inheritance and only adds dealer specific components and behavior. This provides a simple and useful use case for inheritance that fits cleanly into the application they have been building. They also implement input validation and make their own IllegalBetException along with the corresponding try/catch for exception handling. This shows another use of inheritance while continuing to reinforce the importance of defensive programming.
This tour-de-force of inheritance culminates with them refactoring their game into an abstract game table, player and dealer. They then use these and implement game-specific classes for Blackjack and Poker. Implementing the second card game only requires a new deck with different points on the card, a game specific player with the game specific hand scoring, and a game specific table for handling scoring the game and taking bets. Everything else is a shared implementation.
Key Concepts
Graphical Desktop Applications with Swing
Although modern desktop applications are less common than web applications, Swing provides students with immediate visual feedback while introducing event-driven programming, callback interfaces, and separation between presentation and application logic.
Projects
Students build a GUI version of their Blackjack game.
Key Concepts
Deploying an Application
Many introductory programming courses end when the application successfully runs inside the IDE. I wrote this chapter to deliberately extend beyond that point. It is important to teach students how software is packaged, distributed, and executed outside the development environment, since this is a vital part of the software development lifecycle.
Projects
Students build and run a deployment of their console card game as a lab, then they build a deployment of their graphical game, which requires them to include the image files as a JAR resource.
Key Concepts
Learning Outcomes
By the completion of the textbook students have designed and implemented:
- Multiple object-oriented applications
- Unit-tested software
- Application logging
- Console applications
- Swing desktop applications
- Persistent applications using files and JSON
- Applications using inheritance and interfaces
- Deployable JAR applications
Throughout the process they repeatedly practice debugging, refactoring, testing, documentation, and incremental software development using IntelliJ IDEA.