Skip to content

Commit b18987f

Browse files
committed
Add Java constructors and invariants module
1 parent 6989bfe commit b18987f

13 files changed

Lines changed: 248 additions & 13 deletions

File tree

CONCEPT_INDEX.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Use this page to browse the same concept across every active language track.
3737
| Concept | C++ | C# | Go | Java | Python | TypeScript |
3838
| --- | --- | --- | --- | --- | --- | --- |
3939
| structs-and-classes | [C++](languages/cpp/03-advanced/structs-and-classes/README.md) | [C#](languages/csharp/03-advanced/structs-and-classes/README.md) | [Go](languages/go/03-advanced/structs-and-classes/README.md) | [Java](languages/java/03-advanced/structs-and-classes/README.md) | [Python](languages/python/03-advanced/structs-and-classes/README.md) | [TypeScript](languages/typescript/03-advanced/structs-and-classes/README.md) |
40-
| constructors-and-invariants | [C++](languages/cpp/03-advanced/constructors-and-invariants/README.md) | [C#](languages/csharp/03-advanced/constructors-and-invariants/README.md) | [Go](languages/go/03-advanced/constructors-and-invariants/README.md) | Planned | [Python](languages/python/03-advanced/constructors-and-invariants/README.md) | [TypeScript](languages/typescript/03-advanced/constructors-and-invariants/README.md) |
40+
| constructors-and-invariants | [C++](languages/cpp/03-advanced/constructors-and-invariants/README.md) | [C#](languages/csharp/03-advanced/constructors-and-invariants/README.md) | [Go](languages/go/03-advanced/constructors-and-invariants/README.md) | [Java](languages/java/03-advanced/constructors-and-invariants/README.md) | [Python](languages/python/03-advanced/constructors-and-invariants/README.md) | [TypeScript](languages/typescript/03-advanced/constructors-and-invariants/README.md) |
4141
| copy-and-move-semantics | [C++](languages/cpp/03-advanced/copy-and-move-semantics/README.md) | [C#](languages/csharp/03-advanced/copy-and-move-semantics/README.md) | [Go](languages/go/03-advanced/copy-and-move-semantics/README.md) | Planned | [Python](languages/python/03-advanced/copy-and-move-semantics/README.md) | [TypeScript](languages/typescript/03-advanced/copy-and-move-semantics/README.md) |
4242
| inheritance-and-polymorphism | [C++](languages/cpp/03-advanced/inheritance-and-polymorphism/README.md) | [C#](languages/csharp/03-advanced/inheritance-and-polymorphism/README.md) | [Go](languages/go/03-advanced/inheritance-and-polymorphism/README.md) | Planned | [Python](languages/python/03-advanced/inheritance-and-polymorphism/README.md) | [TypeScript](languages/typescript/03-advanced/inheritance-and-polymorphism/README.md) |
4343
| templates-basics | [C++](languages/cpp/03-advanced/templates-basics/README.md) | [C#](languages/csharp/03-advanced/templates-basics/README.md) | [Go](languages/go/03-advanced/templates-basics/README.md) | Planned | [Python](languages/python/03-advanced/templates-basics/README.md) | [TypeScript](languages/typescript/03-advanced/templates-basics/README.md) |

LANGUAGE_PARITY_MATRIX.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Current parity progress in non-C++ tracks:
4747

4848
- C#: `5/5` modules complete in `03-advanced`, `5/5` in `04-expert`
4949
- Go: `5/5` modules complete in `03-advanced`, `5/5` in `04-expert`
50-
- Java: `1/5` modules complete in `03-advanced`, `0/5` in `04-expert`
50+
- Java: `2/5` modules complete in `03-advanced`, `0/5` in `04-expert`
5151
- Python: `5/5` modules complete in `03-advanced`, `5/5` in `04-expert`
5252
- TypeScript: `5/5` modules complete in `03-advanced`, `5/5` in `04-expert`
5353

@@ -56,7 +56,7 @@ Current parity progress in non-C++ tracks:
5656
| Order | Module | C++ | C# | Go | Java | Python | TypeScript |
5757
| --- | --- | --- | --- | --- | --- | --- | --- |
5858
| 1 | structs-and-classes | Done | Done | Done | Done | Done | Done |
59-
| 2 | constructors-and-invariants | Done | Done | Done | Planned | Done | Done |
59+
| 2 | constructors-and-invariants | Done | Done | Done | Done | Done | Done |
6060
| 3 | copy-and-move-semantics | Done | Done | Done | Planned | Done | Done |
6161
| 4 | inheritance-and-polymorphism | Done | Done | Done | Planned | Done | Done |
6262
| 5 | templates-basics | Done | Done | Done | Planned | Done | Done |

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ If you only want to learn one track, follow that track README first because lang
5656
| C++ | 00-setup, 01-foundations, 02-core, 03-advanced, 04-expert | Foundations, Core, Advanced, Expert, projects, assessments | Most complete and primary track |
5757
| C# | 01-foundations, 02-core, 03-advanced, 04-expert | 8/8 foundations modules, 6/6 core modules, 5/5 advanced modules, 5/5 expert modules, 4/4 projects, 4/4 assessments | Module and checkpoint parity complete through expert |
5858
| Go | 01-foundations, 02-core, 03-advanced, 04-expert | 8/8 foundations modules, 6/6 core modules, 5/5 advanced modules, 5/5 expert modules, 4/4 projects, 4/4 assessments | Module and checkpoint parity complete through expert |
59-
| Java | 01-foundations, 02-core, 03-advanced partial | 8/8 foundations modules, 6/6 core modules, 1/5 advanced modules, 2/4 projects, 2/4 assessments | Java 21 MVP through core plus first advanced module; remaining advanced, expert, and later checkpoints planned |
59+
| Java | 01-foundations, 02-core, 03-advanced partial | 8/8 foundations modules, 6/6 core modules, 2/5 advanced modules, 2/4 projects, 2/4 assessments | Java 21 MVP through core plus two advanced modules; remaining advanced, expert, and later checkpoints planned |
6060
| Python | 01-foundations, 02-core, 03-advanced, 04-expert | 8/8 foundations modules, 6/6 core modules, 5/5 advanced modules, 5/5 expert modules, 4/4 projects, 4/4 assessments | Module and checkpoint parity complete through expert |
6161
| TypeScript | 01-foundations, 02-core, 03-advanced, 04-expert | 8/8 foundations modules, 6/6 core modules, 5/5 advanced modules, 5/5 expert modules, 4/4 projects, 4/4 assessments | Module and checkpoint parity complete through expert |
6262

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
11
# Java 03 Advanced
22

3-
This level starts the advanced Java track with object modeling. It is currently a partial expansion.
3+
This level starts the advanced Java track with object modeling and constructor-enforced invariants. It is currently a partial expansion.
44

55
## Learning Metadata
66

77
- Difficulty: Intermediate.
8-
- Estimated Time: 45-60 minutes for the current module.
8+
- Estimated Time: 1.5-2 hours for the current modules.
99
- Prerequisites: Completion of `01-foundations` and `02-core`.
1010
- Study Strategy: Focus on data plus behavior first, then compare Java classes with records, structs, and classes in other tracks.
1111

1212
## Module Order
1313

1414
1. [structs-and-classes](./structs-and-classes/README.md)
15+
2. [constructors-and-invariants](./constructors-and-invariants/README.md)
1516

1617
## Level Outcomes
1718

1819
- Model related data and behavior with Java records and classes.
1920
- Protect object state through constructors and methods.
21+
- Define invariants that remain true after construction and updates.
2022
- Compare Java object modeling with C++, C#, Go, Python, and TypeScript.
2123

2224
## Done When
2325

2426
- [ ] I ran `structs-and-classes/example/Main.java`.
2527
- [ ] I completed both `structs-and-classes` exercises.
28+
- [ ] I ran `constructors-and-invariants/example/Main.java`.
29+
- [ ] I completed both `constructors-and-invariants` exercises.
2630
- [ ] I can explain when a Java record is enough and when a class is better.
2731
- [ ] I can keep state updates behind methods instead of editing fields directly.
32+
- [ ] I can explain how constructors protect invariants.
2833

2934
## Study Tip
3035

31-
This level is intentionally partial. Finish `structs-and-classes` before expanding into constructors, copy/reference behavior, inheritance, and generics.
36+
This level is intentionally partial. Finish these object-state modules before expanding into copy/reference behavior, inheritance, and generics.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Constructors and Invariants (Java)
2+
3+
This module shows how constructors enforce valid object state.
4+
5+
## Learning Metadata
6+
7+
- Difficulty: Intermediate.
8+
- Estimated Time: 35-50 minutes.
9+
- Prerequisites: `03-advanced/structs-and-classes`.
10+
- Cross-Language Lens: Compare constructor rules, validation points, and object setup guarantees in each track.
11+
12+
## Quick Run
13+
14+
~~~bash
15+
javac -d build/java languages/java/03-advanced/constructors-and-invariants/example/Main.java
16+
java -cp build/java Main
17+
~~~
18+
19+
## Topics Covered
20+
21+
- Constructor guards that normalize invalid values.
22+
- Defining invariants as always-true object rules.
23+
- Safe update methods that reject invalid transitions.
24+
- Returning explicit operation success values.
25+
26+
## Common Pitfalls
27+
28+
- Accepting invalid constructor values and fixing later.
29+
- Writing directly into internal fields from outside methods.
30+
- Ignoring failed updates and assuming state changed.
31+
32+
## Exercise Focus
33+
34+
- exercises/Exercise01.java: bank account with non-negative balance invariant.
35+
- exercises/Exercise02.java: date model with month/day validation.
36+
37+
### Exercise Specs
38+
39+
1. exercises/Exercise01.java
40+
- Input: initial balance and transaction values.
41+
- Output: updated balance with validity checks.
42+
- Edge cases: negative initial balance; withdrawal beyond balance.
43+
44+
2. exercises/Exercise02.java
45+
- Input: month and day values.
46+
- Output: valid/invalid date result.
47+
- Edge cases: month out of range; day out of range for month.
48+
49+
## Checkpoint
50+
51+
- [ ] I can define clear invariants for a class.
52+
- [ ] I can enforce invariants in constructors and methods.
53+
- [ ] I can reject invalid updates safely.
54+
- [ ] I completed exercises/Exercise01.java.
55+
- [ ] I completed exercises/Exercise02.java.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Module focus: Building objects that start valid and stay valid through guarded updates.
2+
// Why it matters: practicing constructors and invariants patterns makes exercises and checkpoints easier to reason about.
3+
4+
import java.util.Locale;
5+
6+
public class Main {
7+
static class Temperature {
8+
private double celsius;
9+
10+
Temperature(double celsiusValue) {
11+
// The constructor clamps invalid starting data so every object starts valid.
12+
celsius = Math.max(-273.15, celsiusValue);
13+
}
14+
15+
boolean setCelsius(double newValue) {
16+
// Updates must protect the same invariant as construction.
17+
if (newValue < -273.15) {
18+
return false;
19+
}
20+
21+
celsius = newValue;
22+
return true;
23+
}
24+
25+
double celsius() {
26+
// Accessors expose the valid state without letting callers edit fields directly.
27+
return celsius;
28+
}
29+
}
30+
31+
public static void main(String[] args) {
32+
Locale.setDefault(Locale.US);
33+
34+
// Prepare sample inputs that exercise the key constructors and invariants path.
35+
Temperature temperature = new Temperature(-500.0);
36+
37+
// Report values so learners can verify the constructors and invariants outcome.
38+
System.out.printf("Initial value (clamped): %.2f C%n", temperature.celsius());
39+
40+
boolean updated = temperature.setCelsius(25.0);
41+
System.out.println("Set to 25.0 success: " + updated);
42+
System.out.printf("Current value: %.2f C%n", temperature.celsius());
43+
44+
boolean rejected = temperature.setCelsius(-300.0);
45+
System.out.println("Set to -300.0 success: " + rejected);
46+
47+
System.out.printf("Current value: %.2f C%n", temperature.celsius());
48+
}
49+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import java.util.Locale;
2+
import java.util.Scanner;
3+
4+
public class Exercise01 {
5+
static class BankAccount {
6+
private double balance;
7+
8+
BankAccount(double initialBalance) {
9+
balance = Math.max(0.0, initialBalance);
10+
}
11+
12+
boolean deposit(double amount) {
13+
if (amount <= 0.0) {
14+
return false;
15+
}
16+
balance += amount;
17+
return true;
18+
}
19+
20+
boolean withdraw(double amount) {
21+
if (amount <= 0.0 || amount > balance) {
22+
return false;
23+
}
24+
balance -= amount;
25+
return true;
26+
}
27+
28+
double balance() {
29+
return balance;
30+
}
31+
}
32+
33+
public static void main(String[] args) {
34+
Locale.setDefault(Locale.US);
35+
Scanner scanner = new Scanner(System.in);
36+
37+
double initialBalance = scanner.nextDouble();
38+
BankAccount account = new BankAccount(initialBalance);
39+
40+
double depositAmount = scanner.nextDouble();
41+
account.deposit(depositAmount);
42+
43+
double withdrawAmount = scanner.nextDouble();
44+
if (!account.withdraw(withdrawAmount)) {
45+
System.out.println("Withdrawal rejected.");
46+
}
47+
48+
System.out.printf("Final balance: %.2f%n", account.balance());
49+
}
50+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import java.util.Scanner;
2+
3+
public class Exercise02 {
4+
static class SimpleDate {
5+
private static final int[] DAYS_IN_MONTH = {
6+
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
7+
};
8+
9+
private final int month;
10+
private final int day;
11+
12+
SimpleDate(int month, int day) {
13+
this.month = month;
14+
this.day = day;
15+
}
16+
17+
boolean isValid() {
18+
if (month < 1 || month > 12) {
19+
return false;
20+
}
21+
return day >= 1 && day <= DAYS_IN_MONTH[month - 1];
22+
}
23+
}
24+
25+
public static void main(String[] args) {
26+
Scanner scanner = new Scanner(System.in);
27+
if (!scanner.hasNextInt()) {
28+
System.out.println("Invalid input.");
29+
return;
30+
}
31+
int month = scanner.nextInt();
32+
33+
if (!scanner.hasNextInt()) {
34+
System.out.println("Invalid input.");
35+
return;
36+
}
37+
int day = scanner.nextInt();
38+
39+
SimpleDate date = new SimpleDate(month, day);
40+
System.out.println(date.isValid() ? "Valid date" : "Invalid date");
41+
}
42+
}

languages/java/CHECKLIST.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@
4545

4646
- [ ] structs-and-classes example
4747
- [ ] structs-and-classes exercises
48+
- [ ] constructors-and-invariants example
49+
- [ ] constructors-and-invariants exercises
4850

4951
## Planned
5052

51-
- [ ] constructors-and-invariants module
5253
- [ ] copy-and-move-semantics module
5354
- [ ] inheritance-and-polymorphism module
5455
- [ ] templates-basics module

languages/java/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This track currently covers `01-foundations` and `02-core` as a Java 21 MVP, inc
66

77
- 8/8 foundations modules implemented.
88
- 6/6 core modules implemented.
9-
- 1/5 advanced modules implemented (`structs-and-classes`).
9+
- 2/5 advanced modules implemented (`structs-and-classes`, `constructors-and-invariants`).
1010
- 0/5 expert modules implemented.
1111
- 2/4 projects implemented (`01-foundations`, `02-core`).
1212
- 2/4 assessments implemented (`01-foundations`, `02-core`).
@@ -51,6 +51,7 @@ java -cp build/java Main
5151
- [error-handling-and-defensive-programming](./02-core/error-handling-and-defensive-programming/README.md)
5252
- [03-advanced](./03-advanced/README.md)
5353
- [structs-and-classes](./03-advanced/structs-and-classes/README.md)
54+
- [constructors-and-invariants](./03-advanced/constructors-and-invariants/README.md)
5455
- Projects
5556
- [01-foundations](./projects/01-foundations/README.md)
5657
- [02-core](./projects/02-core/README.md)

0 commit comments

Comments
 (0)