Skip to content

Commit b82f64d

Browse files
authored
Merge pull request #156 from esw0624/Issue146
Adding a Summary Section and fixing typo in Chapter 7
2 parents d96e143 + ee5d231 commit b82f64d

2 files changed

Lines changed: 147 additions & 34 deletions

File tree

source/ch6_definingclasses.ptx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,7 @@ public class Fraction extends Number implements Comparable<Fraction> {
10111011
</program>
10121012
</section>
10131013

1014-
<section xml:id="chapter6_summary">
1014+
<section xml:id="java_classes_summary">
10151015
<title>Summary &amp; Reading Questions</title>
10161016
<p><ol>
10171017
<li>

source/ch7_recursion.ptx

Lines changed: 146 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<section xml:id="basic-recursion">
88
<title>Basic Recursion</title>
99
<p>
10-
In this chapter, we will explore how to translate your recursive logic from Python to Java. While the core concepts of recursion remain the same, the syntax and structure of your code will change somewhat.
10+
In this chapter, we will explore how to translate your recursive logic from Python to Java. While the core concepts of recursion remain the same, the syntax and a bit of the structure of your code will change somewhat.
1111
</p>
12-
<p><idx>recursion</idx>
13-
As you may know from Python, <term>recursion</term> is a powerful problem-solving technique involving base cases and recursive steps in which a function or method calls itself. When moving to Java, the core logic you've learned remains identical. The challenge is adapting that logic to Java's statically-typed, class-based syntax.
12+
<p><idx>recursion</idx><idx>base case</idx><idx>recursive step</idx>
13+
As you may know from Python, <term>recursion</term> is a powerful problem-solving technique involving one or more <term>base cases</term> and <term>recursive steps</term> in which a function or method calls itself while moving towards a base case. When moving to Java, the core logic you've learned remains identical. The challenge is adapting that logic to Java's statically-typed, class-based syntax.
1414
</p>
1515

1616
<p>
@@ -34,7 +34,7 @@
3434
as <m>n \times (n-1)!</m>.
3535
</p>
3636
<p>
37-
Here is a Python implementation of factorial using functions:
37+
Here is a Python implementation of factorial using just one function:
3838
</p>
3939
<program xml:id="factorial-python-function" interactive="activecode" language="python">
4040
<code>
@@ -49,20 +49,18 @@ def factorial(n):
4949
# Recursive Step: n * (n-1)!
5050
return n * factorial(n - 1)
5151

52-
def main():
53-
number = 5
54-
print(str(number) + "! is " + str(factorial(number)))
52+
number = 5
53+
print(str(number) + "! is " + str(factorial(number)))
5554

56-
main()
57-
</code>
55+
</code>
5856
</program>
5957

6058
<p>
61-
Many Python programs organize related functions into classes. The same factorial function can be placed inside a class as a method. Then you need to create an instance of the class to call the method. There we create the class <c>MathTools</c> with a method <c>factorial</c>, and we call it from the <c>main</c> function.
59+
Many Python programs organize related functions into classes. The same factorial function can be placed inside a class as a method instead of as a function. When this is done, you need to create an instance of the class in order to call the method. Below, we create the class <c>MathTools</c> with a method <c>factorial</c>, and we call it from the <c>main</c> function.
6260
</p>
6361
<program xml:id="factorial-python-class" interactive="activecode" language="python">
6462
<code>
65-
class MathTools:
63+
class MTools:
6664
def factorial(self, n):
6765
# Check for negative numbers
6866
if n &lt; 0:
@@ -76,9 +74,9 @@ class MathTools:
7674

7775
def main():
7876
# Create an instance of the class and call the method
79-
math_tools = MathTools()
77+
mtools_instance = MTools()
8078
number = 5
81-
print(str(number) + "! is " + str(math_tools.factorial(number)))
79+
print(str(number) + "! is " + str(mtools_instance.factorial(number)))
8280

8381
main()
8482
</code>
@@ -92,7 +90,7 @@ main()
9290
</p>
9391
<program xml:id="factorial-java-class" interactive="activecode" language="java">
9492
<code>
95-
public class MathTools {
93+
public class MTools {
9694
public static int factorial(int n) {
9795
// Check for negative numbers
9896
if (n &lt; 0) {
@@ -115,7 +113,7 @@ public class MathTools {
115113
</code>
116114
</program>
117115
<p>
118-
Notice the key differences from Python: instead of <c>def factorial(n):</c>, Java uses <c>public static int factorial(int n)</c> which declares the method's visibility as <c>public</c>, that it belongs to the class rather than an instance (hence, <c>static</c>), the return type as integer, and the parameter type also as integer. The recursive logic—base case and recursive step—remains identical to Python, but all code blocks use curly braces <c>{}</c> instead of indentation.
116+
Notice the key differences from Python: instead of <c>def factorial(n):</c>, Java uses <c>public static int factorial(int n)</c> which declares the method's visibility as <c>public</c>, that it belongs to the class rather than an instance (hence, <c>static</c>), the return type as integer, and the parameter type also as integer. The recursive logic—base case and recursive step—remains identical to Python, and, of course, all code blocks use curly braces <c>{}</c> instead of indentation.
119117
</p>
120118
</section>
121119

@@ -258,7 +256,7 @@ public class ArrayProcessor {
258256
public static void main(String[] args) {
259257
int[] numbers = {1, 2, 3, 4, 5};
260258
int result = sumArray(numbers);
261-
System.out.println("The sum of [1, 2, 3, 4, 5] is " + result);
259+
System.out.println("The sum of " + Arrays.toString(numbers) + " is " + result);
262260
}
263261
}
264262
</code>
@@ -276,7 +274,7 @@ public class ArrayProcessor {
276274
<section xml:id="recursion-limits-in-java">
277275
<title>Recursion Limits: Python vs. Java</title>
278276
<p>
279-
The consequence of deep recursion, running out of stack space, is a concept you've already encountered in Python. Java handles this in a very similar way, throwing an error when the call stack depth is exceeded.
277+
The consequence of deep recursion, running out of stack space, is a concept you may have already encountered in Python. Java handles this in a very similar way to Python, throwing an error when the call stack depth is exceeded.
280278
</p>
281279
<p>
282280
The key difference is the name of the error:
@@ -286,10 +284,10 @@ public class ArrayProcessor {
286284
<li>In Java, this throws a <c>StackOverflowError</c>.</li>
287285
</ul>
288286
<p>
289-
Neither language supports <idx> tail call optimization </idx><term>tail call optimization</term>, so the practical limits on recursion depth are a factor in both. If an algorithm requires thousands of recursive calls, an iterative (loop-based) approach is the preferred solution in both Python and Java.
287+
Neither language supports <idx> tail call optimization </idx><term>tail call optimization</term>, so the practical limits on recursion depth are a factor in both. If an algorithm requires thousands of recursive calls, an iterative, loop-based, approach is likely going to be the preferred solution in both Python and Java.
290288
</p>
291289
<p>
292-
The following Python code demonstrates a situation where a function calls itself indefinitely without a base case, leading to aRecursionError.
290+
The following Python code demonstrates a situation where a function calls itself indefinitely without a base case, leading to a <c>RecursionError</c>.
293291
</p>
294292
<program xml:id="python-recursion-error" interactive="activecode" language="python">
295293
<code>
@@ -299,36 +297,151 @@ public class ArrayProcessor {
299297
"""
300298
cause_recursion_error()
301299

302-
# Standard Python entry point
303-
if __name__ == "__main__":
304-
print("Calling the recursive function... this will end in an error!")
305-
306-
# This line starts the infinite recursion.
307-
# Python will stop it and raise a RecursionError automatically.
308-
cause_recursion_error()
300+
print("Calling the recursive function... this will end in an error!")
301+
302+
# The line below will start the infinite recursion.
303+
# Python will stop it and raise a RecursionError automatically.
304+
# Each call adds a new layer to the program's call stack.
305+
# Eventually, the call stack runs out of space, causing the error.
306+
cause_recursion_error()
309307
</code>
310308
</program>
311309

312310
<p>
313-
The following Java code demonstrates a similar situation, where a method calls itself indefinitely without a base case, leading to a StackOverflowError.
311+
The following Java code demonstrates a similar situation, where a method calls itself indefinitely without a base case, leading to a <c>StackOverflowError</c>.
314312
</p>
315313
<program xml:id="java-stack-overflow" interactive="activecode" language="java">
316314
<code>
317315
public class Crash {
318316
public static void causeStackOverflow() {
319-
// This method calls itself endlessly without a stopping condition (a base case).
320-
// Each call adds a new layer to the program's call stack.
321-
// Eventually, the stack runs out of space, causing the error.
317+
// The line below will start the infinite recursion.
318+
// Java will stop it and raise a StackOverflowError automatically.
319+
// Each call adds a new layer to the program's call stack.
320+
// Eventually, the call stack runs out of space, causing the error.
322321
causeStackOverflow();
323322
}
324-
// A main method is required to run the program.
323+
// A main method is required to run the Java program.
325324
public static void main(String[] args) {
326325
System.out.println("Calling the recursive method... this will end in an error!");
327-
// This line starts the infinite recursion.
328-
causeStackOverflow();
326+
327+
causeStackOverflow();
329328
}
330329
}
331330
</code>
332331
</program>
333332
</section>
333+
334+
<section xml:id="recursion_summary">
335+
<title>Summary &amp; Reading Questions</title>
336+
<p><ol label="1">
337+
<li>
338+
<p>Recursion solves problems by defining a <em>base case</em> and a <em>recursive step</em>; each call reduces the problem size until the base case is reached.</p>
339+
</li>
340+
<li>
341+
<p>Java methods must declare visibility, static/instance context, return type, and parameter types; e.g., <c>public static int factorial(int n)</c>.</p>
342+
</li>
343+
<li>
344+
<p>The recursive logic in Java mirrors Python conceptually, but Java uses curly braces <c>{}</c> and explicit types instead of indentation and dynamic typing.</p>
345+
</li>
346+
<li>
347+
<p>The helper method pattern hides implementation details (like array indices) from callers, providing clean public interfaces while managing recursive state privately.</p>
348+
</li>
349+
<li>
350+
<p>Deep or unbounded recursion can exhaust the call stack: Python raises <c>RecursionError</c>; Java throws <c>StackOverflowError</c>.</p>
351+
</li>
352+
<li>
353+
<p>Neither Java nor Python guarantees tail call optimization, so programmers should use iterative solutions for algorithms that would require very deep recursion.</p>
354+
</li>
355+
<li>
356+
<p>Recursive methods in Java must specify return types explicitly, unlike Python's dynamic typing, which affects how you handle error cases and return values.</p>
357+
</li>
358+
</ol></p>
359+
<reading-questions xml:id="rqs-recursion-java">
360+
<exercise label="recursion-method-signature">
361+
<statement>
362+
<p>Which method signature and behavior best match a typical Java recursive factorial implementation?</p>
363+
</statement>
364+
<choices>
365+
<choice>
366+
<statement><p><c>public static int factorial(int n)</c> that returns <c>0</c> when <c>n &lt;= 0</c> and otherwise returns <c>n * factorial(n - 1)</c>.</p></statement>
367+
<feedback><p>No. While this handles negative numbers, the base case is incorrect - factorial of 0 should be 1, not 0.</p></feedback>
368+
</choice>
369+
<choice>
370+
<statement><p><c>public void factorial(int n)</c> that prints each partial product and stops when <c>n</c> reaches zero.</p></statement>
371+
<feedback><p>No. Printing results is fine for testing, but a proper factorial method should return the computed value.</p></feedback>
372+
</choice>
373+
<choice correct="yes">
374+
<statement><p><c>public static int factorial(int n)</c> that returns <c>1</c> when <c>n &lt;= 1</c> and otherwise returns <c>n * factorial(n - 1)</c>.</p></statement>
375+
<feedback><p>Correct. This matches the standard recursive factorial definition in Java.</p></feedback>
376+
</choice>
377+
<choice>
378+
<statement><p><c>public static long factorial(int n)</c> that returns <c>1</c> when <c>n == 0</c> and otherwise returns <c>n * factorial(n - 1)</c>.</p></statement>
379+
<feedback><p>No. While this logic is close, it doesn't handle the case when n = 1, and using long as return type when int parameter is used creates inconsistency.</p></feedback>
380+
</choice>
381+
</choices>
382+
</exercise>
383+
<exercise label="recursion-helper-method">
384+
<statement>
385+
<p>Why use a private helper method (e.g., <c>sumHelper(int[] arr, int index)</c>) behind a public method (e.g., <c>sumArray(int[] arr)</c>) in recursive array processing?</p>
386+
</statement>
387+
<choices>
388+
<choice>
389+
<statement><p>Because it allows Java to automatically optimize the recursion for faster execution.</p></statement>
390+
<feedback><p>No. Java does not automatically optimize recursion just because you use a helper method.</p></feedback>
391+
</choice>
392+
<choice correct="yes">
393+
<statement><p>To keep the public API simple while encapsulating extra recursion state (such as the current index) inside a private method.</p></statement>
394+
<feedback><p>Correct. This keeps the interface clean while hiding internal details from the caller.</p></feedback>
395+
</choice>
396+
<choice>
397+
<statement><p>Because public methods cannot take more than one parameter in recursive calls.</p></statement>
398+
<feedback><p>No. Public methods can take multiple parameters; this is about interface clarity, not parameter limits.</p></feedback>
399+
</choice>
400+
<choice>
401+
<statement><p>To eliminate the need for a base case by handling termination in the helper method automatically.</p></statement>
402+
<feedback><p>No. The helper method still needs an explicit base case to stop recursion.</p></feedback>
403+
</choice>
404+
</choices>
405+
</exercise>
406+
<exercise label="recursion-limits">
407+
<statement>
408+
<p>Which statement about recursion limits and errors is accurate?</p>
409+
</statement>
410+
<choices>
411+
<choice correct="yes">
412+
<statement>
413+
<p>When the call stack is exhausted, Python raises a <c>RecursionError</c> whereas Java throws a <c>StackOverflowError</c>, and neither language applies automatic tail call optimization.</p>
414+
</statement>
415+
<feedback>
416+
<p>Correct. This difference in exception types and the lack of built-in tail call optimization is a key distinction between the two languages.</p>
417+
</feedback>
418+
</choice>
419+
<choice>
420+
<statement>
421+
<p>Java automatically applies tail call optimization to recursive methods marked as <c>final</c>, preventing most stack overflows.</p>
422+
</statement>
423+
<feedback>
424+
<p>No. Java does not perform automatic tail call optimization, regardless of whether methods are marked as final.</p>
425+
</feedback>
426+
</choice>
427+
<choice>
428+
<statement>
429+
<p>Declaring a recursive method as <c>static</c> in Java reduces memory usage per call, allowing more recursive calls before a stack overflow occurs.</p>
430+
</statement>
431+
<feedback>
432+
<p>No. The <c>static</c> modifier changes method context (class vs. instance) but does not meaningfully affect per-call stack memory usage.</p>
433+
</feedback>
434+
</choice>
435+
<choice>
436+
<statement>
437+
<p>The JVM can detect simple recursive patterns and automatically convert them to iterative loops to prevent stack overflow.</p>
438+
</statement>
439+
<feedback>
440+
<p>No. The JVM does not automatically convert recursive methods to iterative ones. This optimization must be done manually by the programmer.</p>
441+
</feedback>
442+
</choice>
443+
</choices>
444+
</exercise>
445+
</reading-questions>
446+
</section>
334447
</chapter>

0 commit comments

Comments
 (0)