@@ -201,5 +201,4 @@
-
\ No newline at end of file
diff --git a/source/ch2_firstjavaprogram.ptx b/source/ch2_firstjavaprogram.ptx
index e6f65c4..7f1669d 100644
--- a/source/ch2_firstjavaprogram.ptx
+++ b/source/ch2_firstjavaprogram.ptx
@@ -4,167 +4,7 @@
Java Programs
-
- Classes and Objects
-
- object-oriented programming OOP
- Depending on how deep your knowledge of Python and programming in general is, you may or may not be familiar with classes and objects. These two important Object-Oriented Programming (OOP) concepts will briefly be discussed. If you already have a good understanding of classes and objects in Python, this section may be skipped.
-
-
-
- object
- attribute
- instance variable
- method
- Objects in the context of programming are instances of classes. Objects contain attributes (also referred to as instance variables), which are data that describe the object or are associated with the object, and methods, which are special functions used by the object. Methods are typically actions the object can perform, or can be used to make changes to the object's attributes.
-
-
-
- class
- constructor
- Classes can be thought of as being similar to blueprints or a recipe; they hold details of how to create an instance of an object. Classes contain a special method called a constructor that is used to create an instance of an object. Once the object is created, it will use the class definition to define its attributes and call methods.
-
-
-
- The best way to understand classes and objects is to see them in action. Let's define a Dog class in Python:
-
-
-
-
-
- class Dog:
- """ A simple Dog class definition. """
- def __init__(self, name, breed, fur_color):
- # constructor method to create a Dog object
- self.name = name
- self.breed = breed
- self.fur_color = fur_color
- self.trained = False # dogs are not trained by default
- print("Dog named " + self.name + " created!")
-
- def bark(self):
- # method to make the dog bark
- print(self.name + " says woof!")
-
- def sit(self):
- # method to make the dog sit
- if self.trained: # check if the dog has been trained otherwise it will not sit
- print(self.name + " sits.")
- else:
- print(self.name + " has not been trained.")
-
- def train(self):
- # method to train the dog, which will set the trained attribute to True
- self.trained = True
-
-
-
-
-
- Let's unpack what is going on in . The first line is where we declare the class definition and name it Dog. Next, we have a special method called __init__. This __init__ method is the constructor and is required for every Python class definition. Within the __init__ method, attributes are defined. As you can see, the attributes name, breed, and fur_color must be defined when creating a Dog object using this class definition, but the trained attribute is defined within the constructor and is initialized as False. We can also have the __init__ method run any code, such as the print statement informing us that a Dog object was created.
-
-
-
- The next three blocks of code are the class's methods. These include bark(self), sit(self), and train(self). As you can see, the class defines attributes (the variables in the __init__ method) and methods for instances of the Dog class.
-
-
-
- self
- Within each method, and for each attribute, you will notice the use of self. This is required in Python. self simply indicates that an attribute or method is being used for a specific instance of an object created with a class.
-
-
-
- Next, we will use this class to create a new Dog object. We will call this new Dog object my_dog:
-
-
-
-
- class Dog:
- """ A simple Dog class definition. """
- def __init__(self, name, breed, fur_color):
- # constructor method to create a Dog object
- self.name = name
- self.breed = breed
- self.fur_color = fur_color
- self.trained = False # dogs are not trained by default
- print("Dog named " + self.name + " created!")
-
- def bark(self):
- # method to make the dog bark
- print(self.name + " says woof!")
-
- def sit(self):
- # method to make the dog sit
- if self.trained: # check if the dog has been trained otherwise it will not sit
- print(self.name + " sits.")
- else:
- print(self.name + " has not been trained.")
-
- def train(self):
- # method to train the dog, which will set the trained attribute to True
- self.trained = True
-
- # Create a Dog object called my_dog
- my_dog = Dog("Rex", "pug", "brown")
-
-
-
-
- In the final line of code in , we have created an object called my_dog. We have initialized its attributes, setting name to Rex, breed to pug, and fur_color to brown.
-
-
-
- Now that we have created a Dog object using the class we defined, we can utilize the class's methods:
-
-
-
-
-
- class Dog:
- """ A simple Dog class definition. """
- def __init__(self, name, breed, fur_color):
- # constructor method to create a Dog object
- self.name = name
- self.breed = breed
- self.fur_color = fur_color
- self.trained = False # dogs are not trained by default
- print("Dog named " + self.name + " created!")
-
- def bark(self):
- # method to make the dog bark
- print(self.name + " says woof!")
-
- def sit(self):
- # method to make the dog sit
- if self.trained:
- print(self.name + " sits.")
- else:
- print(self.name + " has not been trained.")
-
- def train(self):
- # method to train the dog, which will set the trained attribute to True
- self.trained = True
-
-
- my_dog = Dog("Rex", "pug", "brown")
- my_dog.bark() # call the bark method
- my_dog.sit() # call the sit method
-
-
-
-
-
-
- When running , the line Rex has not been trained. will appear in the output when calling the sit() method. Try adding a one or more lines of code so that Rex sits. appears in the output!
-
-
-
-
- Now, we have a full class definition and have utilized its methods. Class definitions in Java will be covered thoroughly in chapter 6. For now, it is important to know that Python programs can be written without using classes at all. Java, on the other hand, requires all code to reside in a class. This will be discussed in the next section.
-
-
-
Lets look at a Java Program
@@ -526,6 +366,9 @@ Hello World!
+
+
+
@@ -636,6 +479,135 @@ Hello World!
+
+
+
+
+ Construct a complete Java program that prints your name and your favorite color to the console.
+ Drag the blocks into the correct order on the right.
+
+
+
+
+
+ public class NameColor {
+
+
+ class NameColor {
+
+
+
+
+
+ public static void main(String[] args) {
+
+
+ public static main(String[] args) {
+
+
+
+
+
+ System.out.println("Name: Alex");
+ System.out.println("Favorite Color: Blue");
+
+
+ system.out.println(Name: Alex);
+ System.out.println("Favorite Color: Blue")
+
+
+
+
+ }
+ }
+
+
+
+
+
+
+ Naming Conventions
+
+ It is worth pointing out that Java has some very handy naming conventions. It is advisable to both use meaningful names and to follow these naming conventions while developing software in Java for good maintenance and readability of code.
+
+
+
+
+ -
+
+ Class names should be nouns that are written in UpperCamelCase, namely with the first letter of each word capitalized including the first.
+ For example, ArrayList, Scanner, StringBuilder, System, etc.
+
+
+
+ -
+
+ Method names use lowerCamelCase which start with a verb that describes the action they perform. This means that method names start with a lower case letter, and use upper case for each internal-word method names. For example, isInt(), nextLine(), getDenominator(), setNumerator(), etc.
+
+
+
+ -
+
+ Instance variables of a class start with a lower case letter and use lowerCamelCase like method names. For example, count, totalAmount, etc.
+
+
+
+ -
+
+ Constants are in all upper case letters or in upper snake case, which also known as screaming snake case, and which is a naming convention in which each word is written in uppercase letters, separated by underscores.
+ For example, Math.MAXINT or MAX_INT.
+
+
+
+
+
+
+
+
+ Which of the following is a valid variable name according to the core syntax rules of Java, but causes a syntax error in Python?
+
+
+
+
+ _variableName
+
+
+ Incorrect. Leading underscores are valid in both Java and Python (commonly used in Python for private/protected attributes).
+
+
+
+
+
+ variable_name
+
+
+ Incorrect. Snake_case names with underscores are valid in both languages (and are actually standard convention in Python).
+
+
+
+
+
+ $variableName
+
+
+ Correct! Java allows the dollar sign ($) in variable names, but Python generates a SyntaxError because $ is not a permitted identifier character in Python.
+
+
+
+
+
+ variableName2
+
+
+ Incorrect. Numbers at the end of variable names are valid syntax in both Java and Python.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/ch3_javadatatypes.ptx b/source/ch3_javadatatypes.ptx
index 151e699..6c69c36 100644
--- a/source/ch3_javadatatypes.ptx
+++ b/source/ch3_javadatatypes.ptx
@@ -230,6 +230,7 @@ public class TempConv {
So, what exactly does the import statement do? What it does is tell the compiler that we are going to use a shortened version of the class’s name. In this example we are going to use the class java.util.Scanner but we can refer to it as just Scanner. We could use the java.util.Scanner class without any problem and without any import statement, provided that we always referred to it by its full name. As an experiment, you may want to try this yourself. Remove the import statement and change the string Scanner to java.util.Scanner in the rest of the code. The program should still compile and run.
+
@@ -279,6 +280,77 @@ public class TempConv {
The general rule in Java is that you must decide what kind of an object your variable is going to reference and then you must declare that variable before you use it. In our temperature converter, the calculation (fahr - 32) * 5.0/9.0 works correctly because 5.0 and 9.0 are treated as double values, preventing the integer division that would occur if we had written 5/9, which would result in 0.
+
+
+
+
+ Construct a complete Java program that reads a distance in kilometers from the user and converts it to miles.
+ Drag the blocks into the correct order on the right.
+
+
+
+
+
+
+ import java.util.Scanner;
+
+
+ import Scanner;
+
+
+
+
+ public class KmToMiles {
+
+
+
+ public static void main(String[] args) {
+
+
+
+ Scanner input;
+ Double kilometers;
+ Double miles;
+
+
+
+
+ input = new Scanner(System.in);
+
+
+ input = new Scanner(System.out);
+
+
+
+
+
+ kilometers = input.nextDouble();
+
+
+ kilometers = input.readDouble();
+
+
+
+
+
+ miles = kilometers * 0.621;
+
+
+ miles = kilometers / 0.621;
+
+
+
+
+ System.out.println(kilometers + " kilometers is equal to " + miles + " miles.");
+
+
+ }
+ }
+
+
+
+
+
@@ -446,6 +518,63 @@ void main() {
In , we first create a Dog object and assign it to an Animal reference (upcasting). Then, we check if the Animal reference is actually pointing to a Dog object before downcasting it back to a Dog reference.
+
+
+
+
+ Construct a program that safely downcasts a Shape reference to a Circle object and calls a subclass method.
+ Drag the blocks into the correct order on the right.
+
+
+
+
+ class Shape {
+ ...
+ }
+
+
+
+ class Circle extends Shape {
+ public void drawCircle() {
+ System.out.println("Circle");
+ }
+ }
+
+
+
+ public class Downcast {
+ public static void main(String[] args) {
+ Shape myShape = new Circle();
+
+
+
+
+ if (myShape instanceof Circle) {
+
+
+ if (myShape.equals(Circle)) {
+
+
+
+
+
+ Circle myCircle = (Circle) myShape;
+ myCircle.drawCircle();
+
+
+ Circle myCircle = myShape;
+ myCircle.drawCircle();
+
+
+
+
+ }
+ }
+ }
+
+
+
+
@@ -684,7 +813,7 @@ public class Histo {
- Now, let’s look at what is happening in the Java source. As usual, we declare the variables we are going to use at the beginning of the method. In this example we are declaring a Scanner variable called data, an integer called idx and an ArrayList called count. However, there is a new twist to the ArrayList declaration. Unlike Python where lists can contain just about anything, in Java we let the compiler know what kind of objects our array list is going to contain. In this case the ArrayList will contain Integers. The syntax we use to declare what kind of object the list will contain is the <Type> syntax.
+ Now, let’s look at what is happening in the Java source. As usual, we declare the variables we are going to use at the beginning of the method. In , we are declaring a Scanner variable called data, an integer called idx and an ArrayList called count. However, there is a new twist to the ArrayList declaration. Unlike Python where lists can contain just about anything, in Java we let the compiler know what kind of objects our array list is going to contain. In this case the ArrayList will contain Integers. The syntax we use to declare what kind of object the list will contain is the <Type> syntax.
@@ -705,7 +834,7 @@ public class Histo {
- Lines 13—20 are required to open the file. Why so many lines to open a file in Java? The additional code mainly comes from the fact that Java forces you to reckon with the possibility that the file you want to open is not going to be there. If you attempt to open a file that is not there you will get an error. A try/catch construct allows us to try things that are risky, and gracefully recover from an error if one occurs. shows the general structure of a try/catch block.
+ Lines 13—20 in are required to open the file. Why so many lines to open a file in Java? The additional code mainly comes from the fact that Java forces you to reckon with the possibility that the file you want to open is not going to be there. If you attempt to open a file that is not there you will get an error. A try/catch construct allows us to try things that are risky, and gracefully recover from an error if one occurs. shows the general structure of a try/catch block.
@@ -721,55 +850,73 @@ public class Histo {
- Notice that in line 16 we are catching an IOException. In fact, we will see later that we can have multiple catch blocks to catch different types of exceptions. If we want to be lazy and catch any old exception we can catch an Exception which is the parent of all exceptions. However, catching Exception is a terrible practice, since you may inadvertently catch exceptions you do not intend to, making it harder to identify bugs in your program.
-
-
-
- On line 22 we create our ArrayList and give it an initial size of 10. Strictly speaking, it is not necessary to give the ArrayList any size. It will grow or shrink dynamically as needed, just like a list in Python. On line 23 we start the first of three loops. The for loop on lines 23–25 serves the same purpose as the Python statement count = [0]*10, that is it initializes the first 10 positions in the ArrayList to hold the value 0.
+ Notice that in line 16 in , we are catching an IOException. In fact, we will see later that we can have multiple catch blocks to catch different types of exceptions. If we want to be lazy and catch any old exception we can catch an Exception which is the parent of all exceptions. However, catching Exception is a terrible practice, since you may inadvertently catch exceptions you do not intend to, making it harder to identify bugs in your program.
- The syntax of this for loop probably looks very strange to you, but in fact it is not too different from what happens in Python using range. In fact for (Integer i = 0; i < 10; i++) is exactly equivalent to the Python for i in range(10) The first statement inside the parenthesis declares and initializes a loop variable i. The second statement is a Boolean expression that is our exit condition. In other words we will keep looping as long as this expression evaluates to true. The third clause is used to increment the value of the loop variable at the end of iteration through the loop. In fact i++ is Java shorthand for i = i + 1 Java also supports the shorthand i-- to decrement the value of i. Like Python, you can also write i += 2 as shorthand for i = i + 2 Try to rewrite the following Python for loops as Java for loops:
+ On line 22 in , we create our ArrayList and give it an initial size of 10. Strictly speaking, it is not necessary to give the ArrayList any size. It will grow or shrink dynamically as needed, just like a list in Python. On line 23 we start the first of three loops. The for loop on lines 23–25 serves the same purpose as the Python statement count = [0]*10, that is it initializes the first 10 positions in the ArrayList to hold the value 0.
-
- -
-
- for i in range(2,101,2)
-
-
-
- -
-
- for i in range(1,100)
-
-
-
- -
-
- for i in range(100,0,-1)
-
-
+ The syntax of this for loop probably looks very strange to you, but in fact it is not too different from what happens in Python using range. In fact for (Integer i = 0; i < 10; i++) is exactly equivalent to the Python for i in range(10) The first statement inside the parenthesis declares and initializes a loop variable i. The second statement is a Boolean expression that is our exit condition. In other words we will keep looping as long as this expression evaluates to true. The third clause is used to increment the value of the loop variable at the end of iteration through the loop. In fact i++ is Java shorthand for i = i + 1 Java also supports the shorthand i-- to decrement the value of i. Like Python, you can also write i += 2 as shorthand for i = i + 2.
- -
-
- for x,y in zip(range(10),range(0,20,2)) [hint, you can separate statements in the same clause with a ,]
-
-
-
-
+
+
+
+ Match each Python for loop with its equivalent Java for loop.
+
+
+
+
+
+
+ for i in range(2, 102, 2)
+ for (int i = 2; i < 102; i += 2)
+
+
+
+ for i in range(1, 100)
+ for (int i = 1; i < 100; i++)
+
+
+
+ for (int i = 1; i <= 100; i++)
+
+
+
+ for i in range(100, 0, -1)
+ for (int i = 100; i > 0; i--)
+
+
+
+ for (int i = 2; i <= 102; i += 2)
+
+
+
+ for x, y in zip(range(10), range(0, 20, 2))
+ for (int x = 0, y = 0; x < 10; x++, y += 2)
+
+
+
+ for (int i = 100; i < 0; i--)
+
+
+
+ for (int x = 0, int y = 0; x < 10; x++, y += 2)
+
+
+
- The next loop (lines 27–30) shows a typical Java pattern for reading data from a file. Java while loops and Python while loops are identical in their logic. In this case, we will continue to process the body of the loop as long as data.hasNextInt() returns true.
+ The next loop (lines 27–30) in shows a typical Java pattern for reading data from a file. Java while loops and Python while loops are identical in their logic. In this case, we will continue to process the body of the loop as long as data.hasNextInt() returns true.
- Line 29 illustrates another important difference between Python and Java. Notice that in Java we can not write count[idx] = count[idx] + 1. This is because in Java there is no overloading of operators. Everything except the most basic math and logical operations is done using methods. So, to set the value of an ArrayList element we use the set method. The first parameter of set indicates the index or position in the ArrayList we are going to change. The next parameter is the value we want to set. Notice that, once again, we cannot use the indexing square bracket operator to retrieve a value from the list, but we must use the get method.
+ Line 29 in illustrates another important difference between Python and Java. Notice that in Java we can not write count[idx] = count[idx] + 1. This is because in Java there is no overloading of operators. Everything except the most basic math and logical operations is done using methods. So, to set the value of an ArrayList element we use the set method. The first parameter of set indicates the index or position in the ArrayList we are going to change. The next parameter is the value we want to set. Notice that, once again, we cannot use the indexing square bracket operator to retrieve a value from the list, but we must use the get method.
- The last loop in this example is similar to the Python for loop where the object of the loop is a Sequence. In Java we can use this kind of for loop over all kinds of sequences, which are called Collection classes in Java. The for loop on line 33 for(Integer i : count) is equivalent to the Python loop for i in count: This loop iterates over all of the elements in the ArrayList called count. Each time through the loop the Integer variable i is bound to the next element of the ArrayList. If you tried the experiment of removing the <Integer> part of the ArrayList declaration you probably noticed that you had an error on this line. Why?
+ The last loop in is similar to the Python for loop where the object of the loop is a Sequence. In Java we can use this kind of for loop over all kinds of sequences, which are called Collection classes in Java. The for loop on line 33 in for(Integer i : count) is equivalent to the Python loop for i in count: This loop iterates over all of the elements in the ArrayList called count. Each time through the loop the Integer variable i is bound to the next element of the ArrayList. If you tried the experiment of removing the <Integer> part of the ArrayList declaration you probably noticed that you had an error on this line. Why?
@@ -820,6 +967,48 @@ public class HistoArray {
The main difference between and is that we declare count to be an Array of integers. We also can initialize short arrays directly using the syntax shown here: Integer[] count = {0,0,0,0,0,0,0,0,0,0}Then notice that we can use the square bracket notation count[idx] to index into an array.
+
+
+
+
+ Construct a short Java program that creates an array of three integers,
+ changes the first value, and prints it. Drag the blocks into the correct order on the right.
+
+
+
+
+ public class ArrayExample {
+ public static void main(String[] args) {
+
+
+
+
+ Integer[] nums = {1, 2, 3};
+
+
+ Integer[] nums = (1, 2, 3);
+
+
+
+
+
+ nums[0] = 5;
+
+
+ nums(0) = 5;
+
+
+
+
+ System.out.println(nums[0]);
+
+
+
+ }
+ }
+
+
+
@@ -932,44 +1121,54 @@ public class HistoMap {
Improve to remove the punctuation.
+
+
+
+
+ Rearrange the blocks to create a general Java method that accepts a dictionary (Map) of item prices and updates the price of a specific item. If the item does not exist, do nothing.
+
+
+
+
+
+ public void updatePrice(Map<String, Double> catalog, String item, double newPrice) {
+
+
+ public void updatePrice() {
+ Map<String, Double> catalog,
+ String item,
+ double newPrice
+
+
+
+
+
+ if (catalog.containsKey(item)) {
+
+
+ if (catalog.get(item) == null) {
+
+
+
+
+
+ catalog.put(item, newPrice);
+
+
+ catalog.add(item, newPrice);
+
+
+
+
+ }
+ }
+
+
+
+
-
- Naming Conventions
-
- It is worth pointing out that Java has some very handy naming conventions. It is advisable to both use meaningful names and to follow these naming conventions while developing software in Java for good maintenance and readability of code.
-
-
-
- -
-
- Class names should be nouns that are written in UpperCamelCase, namely with the first letter of each word capitalized including the first.
- For example, ArrayList, Scanner, StringBuilder, System, etc.
-
-
-
- -
-
- Method names use lowerCamelCase which start with a verb that describes the action they perform. This means that method names start with a lower case letter, and use upper case for each internal-word method names. For example, isInt(), nextLine(), getDenominator(), setNumerator(), etc.
-
-
-
- -
-
- Instance variables of a class start with a lower case letter and use lowerCamelCase like method names. For example, count, totalAmount, etc.
-
-
-
- -
-
- Constants are in all upper case letters or in upper snake case, which also known as screaming snake case, and which is a naming convention in which each word is written in uppercase letters, separated by underscores.
- For example, Math.MAXINT or MAX_INT.
-
-
-
-
-
Summary & Reading Questions
@@ -1114,6 +1313,7 @@ public class HistoMap {
+
\ No newline at end of file
diff --git a/source/ch4_conditionals.ptx b/source/ch4_conditionals.ptx
index 3023211..623587a 100644
--- a/source/ch4_conditionals.ptx
+++ b/source/ch4_conditionals.ptx
@@ -4,14 +4,16 @@
Conditionals
-
- Using the Simple if Statement
+ Using Conditional Statements in Java
+
conditional statements
Conditional statements in Python and Java are very similar.
- In Python we have three patterns:
+ In Python we have three patterns.
-
+
+
+ Using the if Statement
shows how the simple if statement is written in Python.
@@ -50,9 +52,10 @@ if score >= 90: # Note the colon at the end of the line
Once again you can see that in Java the curly braces define a block rather than indentation.
In Java, the parentheses around the condition are required because it is technically a function that evaluates to True or False.
-
-
-
+
+
+
+
Using the if - else Statement
shows how the if - elsestatement is written in Python.
@@ -60,7 +63,7 @@ if score >= 90: # Note the colon at the end of the line
age = 16
- if age >= 18:
+ if age >= 18: # notice the semicolon
print("You can vote.")
else: # notice the semicolon
print("You are not yet eligible to vote.")
@@ -75,7 +78,7 @@ if score >= 90: # Note the colon at the end of the line
public class IfElseExample {
public static void main(String[] args) {
int age = 16;
- if (age >= 18) {
+ if (age >= 18) {
System.out.println("You can vote.");
} else { // else has its own block.
System.out.println("You are not yet eligible to vote.");
@@ -85,9 +88,9 @@ if score >= 90: # Note the colon at the end of the line
-
+
-
+
Can we use elif?
elif statement
@@ -102,7 +105,7 @@ if score >= 90: # Note the colon at the end of the line
grade = int(input('enter a grade'))
if grade < 60:
print('F')
-elif grade < 70:
+elif grade < 70: # notice the semicolon
print('D')
elif grade < 80:
print('C')
@@ -126,7 +129,7 @@ public class ElseIf {
int grade = 85;
if (grade < 60) {
System.out.println('F');
- } else {
+ } else { // else has its own block.
if (grade < 70) {
System.out.println('D');
} else {
@@ -155,12 +158,12 @@ We can get even closer to the elif statement by taking advantage of the J
-public class ElseIf {
+public class ElseIf {
public static void main(String args[]) {
- int grade = 85;
+ int grade = 85;
if (grade < 60) {
System.out.println('F');
- } else if (grade < 70) {
+ } else if (grade < 70) { // notice how we got rid of the curly braces.
System.out.println('D');
} else if (grade < 80) {
System.out.println('C');
@@ -172,20 +175,21 @@ public class ElseIf {
-
+
-
+
Using the switch Statement
-Java also supports a switch statement that acts something like the elif or Python match statement under certain conditions. To write the grade program using a switch statement we would use the following:
+Java also supports a switch statement that acts something like the elif or Python match statement under certain conditions. shows how a grade program using a switch statement would look in Python.
The match - case statement was introduced in Python 3.10, so doesn't run in earlier version of Python. Here is an example using Python's match - case structure.
-
+
+
Match Case Example
grade = 85
@@ -206,6 +210,7 @@ Java also supports a switch statement that acts something like the eli
print(grading(tempgrade))
+
switch
The switch statement in Java provides an alternative to chaining multiple if-else conditions, when comparing a single variable against several constant values. It supports a variety of data types, including primitive types (byte, short, char, int), their wrapper classes, enumerations, and String (introduced in Java 7). Each case within a switch must be defined using a constant expression, and duplicate case values are not permitted. By default, control flow "falls through" from one case to the next unless a break, return, or throw statement is used to terminate execution.
@@ -214,10 +219,11 @@ Java also supports a switch statement that acts something like the eli
switch expressions
yield
- Java 14 introduced switch expressions, enhancing functionality by allowing the switch to return values and eliminating fall-through via the -> arrow syntax. These expressions can even use yield within code blocks for more complex evaluations. yield is used inside a switch expression’s block to produce the value of that expression, unlike break which simply exits a switch statement or loop. It’s important to note that traditional switch statements do not support null values and will throw a NullPointerException if evaluated with null. As the language evolves, newer versions of Java continue to extend switch capabilities with features like pattern matching and enhanced type handling, making it a more powerful and expressive tool for decision-making in Java programs.
+ Java 14 introduced switch expressions, enhancing functionality by allowing the switch to return values and eliminating fall-through via the -> arrow syntax. These expressions can even use yield within code blocks for more complex evaluations. yield is used inside a switch expression’s block to produce the value of that expression, unlike break which simply exits a switch statement or loop. It’s important to note that traditional switch statements do not support null values and will throw a NullPointerException if evaluated with null. As the language evolves, newer versions of Java continue to extend switch capabilities with features like pattern matching and enhanced type handling, making it a more powerful and expressive tool for decision-making in Java programs. shows how the switch expression is written in Java.
-
-
+
+
+
public class SwitchUp {
public static void main(String args[]) {
@@ -245,73 +251,276 @@ Java also supports a switch statement that acts something like the eli
}
+
The switch statement is not used very often, and we recommend you do not use it. First, it is not as powerful as the else if model because the switch variable can only be compared for equality with an integer or enumerated constant. Second, it is very easy to forget to put in the break statement, so it is more error-prone. If the break statement is left out then then the next alternative will be automatically executed. For example, if the grade was 95 and the break was omitted from the case 9: alternative then the program would print(out both A and B.)
Finally, the switch statement does not support relational expressions such as greater than or less than. So you cannot use it to completely replace the elif. Even with the new features of Java 14+ the switch statement is still limited to constant comparisons using equality.
+
+
+
+
+
+ Rearrange the blocks to create a Java method that accepts a temperature reading and returns a status string ("CRITICAL", "WARNING", or "NORMAL").
+
+
+
+
+
+ public String checkTemperature(double temp) {
+
+
+ public String checkTemperature(double temp); {
+
+
+
+
+
+ if (temp >= 100.0) {
+ return "CRITICAL";
+ }
+
+
+ if (temp == 100.0) {
+ return "CRITICAL";
+ }
+
+
+
+
+
+ else if (temp >= 75.0) {
+ return "WARNING";
+ }
+
+
+ else (temp >= 75.0) {
+ return "WARNING";
+ }
+
+
+
+
+
+ else {
+ return "NORMAL";
+ }
+
+
+ else if {
+ return "NORMAL";
+ }
+
+
+
+
+ }
+
+
+
+
-
+
+ The Ternary Operator
+
+ Boolean operators simple comparisons compound Boolean expressions
+The conditionals used in the if statement can be Boolean variables, simple comparisons, and compound Boolean expressions.
+
+
+ternary operator
+Java also provides the ternary operator condition ? valueIfTrue : valueIfFalse, which lets you use a boolean test directly inside an assignment. If the condition is true, the first value is chosen; otherwise, the second value is used. summarizes how it works.
+
+
+
+ Ternary Operator in Java
+
+
+ | Component |
+ Description |
+
+
+ | condition |
+ The boolean expression that is evaluated (e.g., a % 2 == 0). |
+
+
+ | ? |
+ This is the ternary operator that separates the condition from the trueValue. |
+
+
+ | trueValue |
+ The value assigned if the condition is true (e.g., a * a). |
+
+
+ | : |
+ This is the ternary operator that separates the trueValue from the falseValue. |
+
+
+ | falseValue |
+ The value assigned if the condition is false (e.g., 3 * x - 1). |
+
+
+ | Example Usage |
+ a = a % 2 == 0 ? a * a : 3 * x - 1 |
+
+
+ | Equivalent if-else Code |
+ Can also be written with a regular if-else statement, but the ternary form is more concise. |
+
+
+
+
+
+Using this operator can make code shorter and more readable in cases where a simple conditional assignment is needed. shows an example where we see the same logic implemented in two different ways.
+
+
+
+
+public class Ternary {
+ public static void main(String[] args) {
+ int a = 4;
+ int x = 2;
+ int outp;
+
+ // ternary:
+ outp = (a % 2 == 0) ? (a * a) : (3 * x - 1);
+ System.out.println("ternary result: " + outp);
+
+ // Equivalent using if/else
+ if (a % 2 == 0) {
+ outp = a * a;
+ } else {
+ outp = 3 * x - 1;
+ }
+
+ System.out.println("if/else result: " + outp);
+ }
+}
+
+
+
+
+
+ In , we are using this ternary operator to assign a value to a based on whether a is even or odd. If a is even, it will be squared; if odd, it will be instead be calculated as 3 * x - 1. This is a concise way to write conditional assignments in Java. However, you might want to use it sparingly, as it can make code less readable if overused or used with complex expressions.
+
+
+
+
+
+ Rearrange the blocks to create a Java method that calculates shipping costs. Orders over $100 get free shipping ($0.0), while members pay $5.0 and non-members pay $10.0.
+
+
+
+
+
+ public double calculateShipping(double orderTotal, boolean isMember) {
+
+
+ public double calculateShipping()
+ double orderTotal
+ boolean isMember
+ {
+
+
+
+
+
+ if (orderTotal >= 100.0) {
+ return 0.0;
+ }
+
+
+ if (orderTotal = 100.0) {
+ return 0.0;
+ }
+
+
+
+
+
+ else {
+ return isMember ? 5.0 : 10.0;
+ }
+
+
+ else {
+ return isMember : 5.0 ? 10.0;
+ }
+
+
+
+
+ }
+
+
+
+
+
+
Exception Handling
- In Python, if you want a program to continue running when an error has occurred, you can use try-except blocks to handle exceptions. If you wanted to write a program that asks the user to enter a whole number and then squares that number, you could use the following code to do so:
+ In Python, if you want a program to continue running when an error has occurred, you can use try-except blocks to handle exceptions. If you wanted to write a program that asks the user to enter a whole number and then squares that number, you could use the following code to do so. shows the Python code to achieve this.
-
+
+
- number = int(input("Please enter a whole number: "))
- squared = number ** 2
- print("Your number squared is " + str(squared))
+ number = int(input("Please enter a whole number: ")) # ask user for a number
+ squared = number ** 2 # square the number
+ print("Your number squared is " + str(squared))
+
- The Java code that would perform the same task is a little more complex and utilizes the Scanner class for input.
+ shows the Java code that would perform the same task. It is a little more complex and utilizes the Scanner class for input.
-
-
+
+
import java.util.Scanner;
public class SquareNumber {
public static void main(String[] args) {
- Scanner user_input = new Scanner(System.in);
+ Scanner user_input = new Scanner(System.in); // create a scanner object
- System.out.print("Please enter a whole number: ");
- int number = user_input.nextInt();
- int squared = number * number;
+ System.out.print("Please enter a whole number: ");
+ int number = user_input.nextInt(); // ask user for a number
+ int squared = number * number; // square the number
System.out.println("Your number squared is " + squared);
}
}
+
- This code works well, but will end with an exception if the user types anything other than a whole number (such as 12.5 or two). If we wanted to ensure the code will continue to run until the user enters the correct format, we could add try-except (Python) or try-catch (Java) blocks within a while loop that iterates until the user enter the correct code. Adding try-except blocks and a while loop to the Python code will look something like this:
+ This code works well, but will end with an exception if the user types anything other than a whole number (such as 12.5 or two). If we wanted to ensure the code will continue to run until the user enters the correct format, we could add try-except (Python) or try-catch (Java) blocks within a while loop that iterates until the user enter the correct code. While try-except blocks aren't strictly required in Python, shows how using them alongside a while loop makes the code more robust.
-
-
+
+
while True:
- try:
+ try: # try to convert the user input to an integer
number = int(input("Please enter a whole number: "))
squared = number ** 2
print("Your number squared is " + str(squared))
break
- except ValueError:
+ except ValueError: # if the user enters a non-integer, print an error message
print("That was not a valid number. Please try again: ")
+
- Now that we have Python code that will continuously prompt the user until they enter a whole number, let's look at Java code that accomplishes the same task. Like most other equivalent Java code blocks, this code has a lot of extra bits that are necessary to get working code.
+ Now that we have Python code that will continuously prompt the user until they enter a whole number, shows the Java code that accomplishes the same task. Like most other equivalent Java code blocks, this code has a lot of extra bits that are necessary to get working code.
-
-
+
+
import java.util.Scanner;
import java.util.InputMismatchException;
@@ -320,14 +529,14 @@ The switch statement is not used very often, and we recommend you do not
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
- while (true) {
- try {
+ while (true) { // keep asking the user for a number until they enter a valid integer
+ try { // try to convert the user input to an integer
System.out.print("Please enter a whole number: ");
int number = scanner.nextInt();
int squared = number * number;
System.out.println("Your number squared is " + squared);
break;
- } catch (InputMismatchException e) {
+ } catch (InputMismatchException e) { // if the user enters a non-integer, print an error message
System.out.println("That was not a valid number. Please try again: ");
scanner.nextLine(); // Clear the invalid input from the scanner
}
@@ -336,6 +545,7 @@ The switch statement is not used very often, and we recommend you do not
}
+
Firstly, let's talk about the extra import alongside the Scanner import. In Java, we need to import InputMismatchException because it's not automatically available like basic exceptions. This is different from Python where most exceptions are readily accessible. If you ran the previous Java codeblock without try-catch blocks and entered an erroneous input, you would have got an InputMismatchException exception despite not having imported this class. That being said, removing the explicit import of this library for the try-catch code block above will lead to compilation errors.
@@ -344,11 +554,11 @@ The switch statement is not used very often, and we recommend you do not
checked exception
unchecked exception
- Exceptions in Java fall under two categories: checked and unchecked. Checked exceptions must be explicitly imported and declared along with try-catch blocks for a program to compile. Unchecked exceptions do not need to be imported unless try-catch blocks are implemented for them (except for java.lang exceptions). InputMismatchException is an unchecked exception that is not part of the java.lang library, so it is only included if try-catch blocks declare it. Here are some common exceptions used with try-catch blocks:
+ Exceptions in Java fall under two categories: checked and unchecked. Checked exceptions must be explicitly imported and declared along with try-catch blocks for a program to compile. Unchecked exceptions do not need to be imported unless try-catch blocks are implemented for them (except for java.lang exceptions). InputMismatchException is an unchecked exception that is not part of the java.lang library, so it is only included if try-catch blocks declare it. shows the exceptions used with try-catch blocks.
-
- Exceptions
+
+ Java Exceptions Used with try-catch Blocks
| Exception |
@@ -402,90 +612,6 @@ The switch statement is not used very often, and we recommend you do not
Note that as with other structures in Java, try-catch blocks blocks must be encased with braces {}. The most important part of this code is, after catch, there is a set of parenthesis with an exception type and a variable name catch (InputMismatchException e). This is where we declare a InputMismatchException exception and name it with the variable name e. It is common practice, though not a requirement, to name exception variables e in this manner.
-
-
-
- The Ternary Operator
-
- Boolean operators simple comparisons compound Boolean expressions
-The conditionals used in the if statement can be Boolean variables, simple comparisons, and compound Boolean expressions.
-
-
-ternary operator
-Java also provides the ternary operator condition ? valueIfTrue : valueIfFalse, which lets you use a boolean test directly inside an assignment. If the condition is true, the first value is chosen; otherwise, the second value is used. The table below summarizes how it works:
-
-
-
- Ternary Operator in Java
-
-
- | Component |
- Description |
-
-
- | condition |
- The boolean expression that is evaluated (e.g., a % 2 == 0). |
-
-
- | ? |
- This is the ternary operator that separates the condition from the trueValue. |
-
-
- | trueValue |
- The value assigned if the condition is true (e.g., a * a). |
-
-
- | : |
- This is the ternary operator that separates the trueValue from the falseValue. |
-
-
- | falseValue |
- The value assigned if the condition is false (e.g., 3 * x - 1). |
-
-
- | Example Usage |
- a = a % 2 == 0 ? a * a : 3 * x - 1 |
-
-
- | Equivalent if-else Code |
- Can also be written with a regular if-else statement, but the ternary form is more concise. |
-
-
-
-
-
-Using this operator can make code shorter and more readable in cases where a simple conditional assignment is needed. See the following as an example where we see the same logic implemented in two different ways.
-
-
-
-public class Ternary {
- public static void main(String[] args) {
- int a = 4;
- int x = 2;
- int outp;
-
- // ternary:
- outp = (a % 2 == 0) ? (a * a) : (3 * x - 1);
- System.out.println("ternary result: " + outp);
-
- // Equivalent using if/else
- if (a % 2 == 0) {
- outp = a * a;
- } else {
- outp = 3 * x - 1;
- }
-
- System.out.println("if/else result: " + outp);
- }
-}
-
-
-
-
- In this example we are using this ternary operator to assign a value to a based on whether a is even or odd. If a is even, it will be squared; if odd, it will be instead be calculated as 3 * x - 1. This is a concise way to write conditional assignments in Java. However, you might want to use it sparingly, as it can make code less readable if overused or used with complex expressions.
-
-
-
Summary & Reading Questions
diff --git a/source/ch5_loopsanditeration.ptx b/source/ch5_loopsanditeration.ptx
index ff221d2..c0e87a1 100644
--- a/source/ch5_loopsanditeration.ptx
+++ b/source/ch5_loopsanditeration.ptx
@@ -11,161 +11,230 @@
for loop
- A definite loop is a loop that is executed a specific or definite number of times. In Python, the easiest way to write a definite loop is using the for loop in conjunction with the range function.
- For example:
+ definite loop
+ A definite loop, also known as a for loop, is a loop that is executed for a specific or definite number of times. In Python, the easiest way to write a definite loop is using the for loop structure in conjunction with the range function. shows the syntax for the range function.
-
-
+
+
-for i in range(10):
+for i in range(10): # range(10) is a list of integers from 0 to 9
print(i)
+
- In Java, we would write this as:
+ shows how the for loop is written in Java.
-
+
+
public class DefiniteLoopExample {
public static void main(String[] args) {
- for (Integer i = 0; i < 10; i++ ) {
+ for (Integer i = 0; i < 10; i++ ) { // notice how the initialization, condition, and update are all on the same line.
System.out.println(i);
}
}
}
+
- Recall that the range function provides you with a wide variety of options for controlling the value of the loop variable.
+ Recall that the range function provides you with a wide variety of options for controlling the value of the loop variable as shown in .
-
-
+
+
+
range(stop)
range(start,stop)
range(start,stop,step)
-
+
+
+
- The Java for loop is really analogous to the last option giving you explicit control over the starting, stopping, and stepping in the three clauses inside the parenthesis.
- You can think of it this way:
+ The Java for loop is really analogous to the last option giving you explicit control over the starting, stopping, and stepping in the three clauses inside the parenthesis.
+ shows how the Java for loop is written.
-
-
+
+
+
for (start clause; stop clause; step clause) {
statement1
statement2
...
}
-
-
+
+
+
+
- If you want to start at 100, stop at 0 and count backward by 5, the Python loop would be written as:
+ If you want to start at 100, stop at 0 and count backward by 5, shows how the Python for loop is written.
-
+
+
-for i in range(100, -1, -5):
+for i in range(100, -1, -5): # start at 100, stop at 0, decrement by 5
print(i)
+
- In Java, we would write this as:
+ shows how the for loop is written in Java.
-
-
+
+
public class DefiniteLoopBackward {
public static void main(String[] args) {
- for (Integer i = 100; i >= 0; i -= 5) {
+ for (Integer i = 100; i >= 0; i -= 5) { // start at 100, stop at 0, decrement by 5
System.out.println(i);
}
}
}
-
+
In Python, the for loop can also iterate over any sequence such as a list, a string, or a tuple.
Java also provides a variation of its for loop that provides the same functionality in its so-called for each loop.
- In Python, we can iterate over a list as follows:
+ shows how the for loop can be used to iterate over a list in Python.
-
-
+
+
-l = [1, 1, 2, 3, 5, 8, 13, 21]
-for fib in l:
+l = [1, 1, 2, 3, 5, 8, 13, 21] # create a list of integers
+for fib in l: # iterate over the list
print(fib)
+
- In Java we can iterate over an ArrayList of integers too. Note that this requires importing the ArrayList class.
+ shows how the for loop can be used to iterate over an ArrayList of integers in Java.
-
-
+
+
import java.util.ArrayList;
public class ForEachArrayListExample {
public static void main(String[] args) {
- ArrayList<Integer> l = new ArrayList<Integer>();
- l.add(1);
- l.add(1);
- l.add(2);
+ ArrayList<Integer> l = new ArrayList< // create an ArrayList of integers
+ l.add(1); // add the first integer to the list
+ l.add(1); // add the second integer to the list
+ l.add(2); // keep going
l.add(3);
l.add(5);
l.add(8);
l.add(13);
- l.add(21);
- for (Integer i : l) {
+ l.add(21); // add the last integer to the list
+ for (Integer i : l) { // iterate over the list
System.out.println(i);
}
}
}
+
- This example stretches the imagination a bit, and in fact points out one area where Java's primitive arrays are easier to use than an array list.
- In fact, all primitive arrays can be used in a for each loop.
+ stretches the imagination a bit, and in fact points out one area where Java's primitive arrays are easier to use than an array list.
+ shows how the for loop can be used to iterate over all elements in a primitive array in Java.
-
+
+
public class ForEachArrayExample {
public static void main(String[] args) {
- int l[] = {1,1,2,3,5,8,13,21};
- for(int i : l) {
+ int l[] = {1,1,2,3,5,8,13,21}; // create an array of integers using primitive syntax
+ for(int i : l) { // iterate over the array
System.out.println(i);
}
}
}
+
- To iterate over the characters in a string in Java do the following:
-
-
-
+ shows how the for loop can be used to iterate over all elements in a string in Java.
+
+
+
public class StringIterationExample {
public static void main(String[] args) {
- String t = "Hello World";
- for (char c : t.toCharArray()) {
+ String t = "Hello World"; // create a string
+ for (char c : t.toCharArray()) { // iterate over the characters in the string
System.out.println(c);
}
}
}
+
+
+
+
+
+ Rearrange the blocks to create a Java method that accepts an upper bound integer limit and calculates the sum of all even numbers from 2 up to and including limit.
+
+
+
+
+ public int sumEvens(int limit) {
+
+
+
+
+ int total = 0;
+
+
+ int total;
+
+
+
+
+
+ for (int i = 2; i <= limit; i += 2) {
+
+
+ for (int i = 2; i < limit; i =+ 2) {
+
+
+
+
+
+ total += i;
+ }
+
+
+ total = i;
+ }
+
+
+
+
+
+ return total;
+ }
+
+
+ return i;
+ }
+
+
+
+
@@ -174,54 +243,113 @@ public class StringIterationExample {
while loop
Both Python and Java support the while loop, which continues to execute as long as a condition is true.
- Here is a simple example in Python that counts down from 5:
+ shows a simple example in Python that counts down from 5.
-
+
+
i = 5
-while i > 0:
+while i > 0: # while i is greater than 0
print(i)
- i = i - 1
+ i = i - 1
+
- In Java, we add parentheses and curly braces. Here is the same countdown loop in Java:
+ In Java, we add parentheses and curly braces. shows the same countdown loop in Java.
-
+
+
public class WhileLoopExample {
public static void main(String[] args) {
- int i = 5;
- while (i > 0) {
+ int i = 5;
+ while (i > 0) { // while i is greater than 0
System.out.println(i);
- i = i - 1;
+ i = i - 1;
}
}
}
+
do-while loop
Java adds an additional, if seldom used variation of the while loop called the do-while loop.
The do-while loop is very similar to while except that the condition is evaluated at the end of the loop rather than the beginning.
This ensures that a loop will be executed at least one time.
Some programmers prefer this loop in some situations because it avoids an additional assignment prior to the loop.
- For example, the following loop will execute once even though the condition is initially false.
+ For example, shows how loop will execute once even though the condition is initially false.
-
-
+
+
public class DoWhileExample {
public static void main(String[] args) {
- int i = 10;
- do {
+ int i = 10;
+ do { // do-while loop, will run at least once no matter the condition
System.out.println("This runs once, i = " + i);
- } while (i < 5);
+ } while (i < 5); // while i is less than 5
}
}
+
+
+
+
+
+ Rearrange the blocks to create a Java method that accepts a starting balance and a target amount, then calculates how many years it takes for the balance to reach or exceed the target by doubling each year.
+
+
+
+
+
+ public int yearsToTarget(double balance, double target) {
+ int years = 0;
+
+
+ public int yearsToTarget(double balance, double target) {
+ int years;
+
+
+
+
+
+ while (balance < target) {
+
+
+ while (balance >= target) {
+
+
+
+
+
+ balance *= 2;
+ years++;
+ }
+
+
+ balance * 2;
+ years++;
+ }
+
+
+
+
+
+ return years;
+ }
+
+
+ return balance;
+ }
+
+
+
+
+
Summary & Reading Questions
@@ -323,4 +451,4 @@ public class DoWhileExample {
-
\ No newline at end of file
+
diff --git a/source/ch6_definingclasses.ptx b/source/ch6_definingclasses.ptx
index f2e6d55..5042038 100644
--- a/source/ch6_definingclasses.ptx
+++ b/source/ch6_definingclasses.ptx
@@ -4,6 +4,172 @@
Classes in Java
+
+
+
+ Classes and Objects
+
+
+ object-oriented programming OOP
+ Depending on how deep your knowledge of Python and programming in general is, you may or may not be familiar with classes and objects. These two important Object-Oriented Programming (OOP) concepts will briefly be discussed. If you already have a good understanding of classes and objects in Python, this section may be skipped.
+
+
+
+ object
+ attribute
+ instance variable
+ method
+ Objects in the context of programming are instances of classes. Objects contain attributes (also referred to as instance variables), which are data that describe the object or are associated with the object, and methods, which are special functions used by the object. Methods are typically actions the object can perform, or can be used to make changes to the object's attributes.
+
+
+
+ class
+ constructor
+ Classes can be thought of as being similar to blueprints or a recipe; they hold details of how to create an instance of an object. Classes contain a special method called a constructor that is used to create an instance of an object. Once the object is created, it will use the class definition to define its attributes and call methods.
+
+
+
+ The best way to understand classes and objects is to see them in action. Let's define a Dog class in Python:
+
+
+
+
+
+ class Dog:
+ """ A simple Dog class definition. """
+ def __init__(self, name, breed, fur_color):
+ # constructor method to create a Dog object
+ self.name = name
+ self.breed = breed
+ self.fur_color = fur_color
+ self.trained = False # dogs are not trained by default
+ print("Dog named " + self.name + " created!")
+
+ def bark(self):
+ # method to make the dog bark
+ print(self.name + " says woof!")
+
+ def sit(self):
+ # method to make the dog sit
+ if self.trained: # check if the dog has been trained otherwise it will not sit
+ print(self.name + " sits.")
+ else:
+ print(self.name + " has not been trained.")
+
+ def train(self):
+ # method to train the dog, which will set the trained attribute to True
+ self.trained = True
+
+
+
+
+
+ Let's unpack what is going on in . The first line is where we declare the class definition and name it Dog. Next, we have a special method called __init__. This __init__ method is the constructor and is required for every Python class definition. Within the __init__ method, attributes are defined. As you can see, the attributes name, breed, and fur_color must be defined when creating a Dog object using this class definition, but the trained attribute is defined within the constructor and is initialized as False. We can also have the __init__ method run any code, such as the print statement informing us that a Dog object was created.
+
+
+
+ The next three blocks of code are the class's methods. These include bark(self), sit(self), and train(self). As you can see, the class defines attributes (the variables in the __init__ method) and methods for instances of the Dog class.
+
+
+
+ self
+ Within each method, and for each attribute, you will notice the use of self. This is required in Python. self simply indicates that an attribute or method is being used for a specific instance of an object created with a class.
+
+
+
+ Next, we will use this class to create a new Dog object. We will call this new Dog object my_dog:
+
+
+
+
+ class Dog:
+ """ A simple Dog class definition. """
+ def __init__(self, name, breed, fur_color):
+ # constructor method to create a Dog object
+ self.name = name
+ self.breed = breed
+ self.fur_color = fur_color
+ self.trained = False # dogs are not trained by default
+ print("Dog named " + self.name + " created!")
+
+ def bark(self):
+ # method to make the dog bark
+ print(self.name + " says woof!")
+
+ def sit(self):
+ # method to make the dog sit
+ if self.trained: # check if the dog has been trained otherwise it will not sit
+ print(self.name + " sits.")
+ else:
+ print(self.name + " has not been trained.")
+
+ def train(self):
+ # method to train the dog, which will set the trained attribute to True
+ self.trained = True
+
+ # Create a Dog object called my_dog
+ my_dog = Dog("Rex", "pug", "brown")
+
+
+
+
+ In the final line of code in , we have created an object called my_dog. We have initialized its attributes, setting name to Rex, breed to pug, and fur_color to brown.
+
+
+
+ Now that we have created a Dog object using the class we defined, we can utilize the class's methods:
+
+
+
+
+
+ class Dog:
+ """ A simple Dog class definition. """
+ def __init__(self, name, breed, fur_color):
+ # constructor method to create a Dog object
+ self.name = name
+ self.breed = breed
+ self.fur_color = fur_color
+ self.trained = False # dogs are not trained by default
+ print("Dog named " + self.name + " created!")
+
+ def bark(self):
+ # method to make the dog bark
+ print(self.name + " says woof!")
+
+ def sit(self):
+ # method to make the dog sit
+ if self.trained:
+ print(self.name + " sits.")
+ else:
+ print(self.name + " has not been trained.")
+
+ def train(self):
+ # method to train the dog, which will set the trained attribute to True
+ self.trained = True
+
+
+ my_dog = Dog("Rex", "pug", "brown")
+ my_dog.bark() # call the bark method
+ my_dog.sit() # call the sit method
+
+
+
+
+
+
+ When running , the line Rex has not been trained. will appear in the output when calling the sit() method. Try adding a one or more lines of code so that Rex sits. appears in the output!
+
+
+
+
+ Now, we have a full class definition and have utilized its methods. Class definitions in Java will be covered thoroughly in chapter 6. For now, it is important to know that Python programs can be written without using classes at all. Java, on the other hand, requires all code to reside in a class. This will be discussed later in chapter 6.
+
+
+
+
+
+
Defining Classes in Java
@@ -62,11 +228,11 @@
- Here is a mostly complete implementation of a Fraction class in Python that we will refer to throughout this section:
+ is a mostly complete implementation of a Fraction class in Python that we will refer to throughout this section.
-
-
+
+
class Fraction:
def __init__(self, num, den):
@@ -76,37 +242,54 @@
"""
self.num = num
self.den = den
- def __repr__(self):
- if self.num > self.den:
- retWhole = int(self.num / self.den)
- retNum = self.num - (retWhole * self.den)
+ def __repr__(self):
+ """
+ :return: a string representation of the fraction
+ """
+ if self.num > self.den:
+ retWhole = int(self.num / self.den) # find the whole number part
+ retNum = self.num - (retWhole * self.den) # find the numerator part
return str(retWhole) + " " + str(retNum) + "/" + str(self.den)
else:
return str(self.num) + "/" + str(self.den)
def show(self):
+ """
+ :return: print the fraction
+ """
print(self.num, "/", self.den)
def __add__(self, other):
+ """
+ :param other: the fraction to add
+ :return: the sum of the two fractions
+ """
# convert to a fraction
other = self.toFract(other)
- newnum = self.num * other.den + self.den * other.num
- newden = self.den * other.den
+ newnum = self.num * other.den + self.den * other.num # find the new numerator
+ newden = self.den * other.den # find the new denominator
common = gcd(newnum, newden)
return Fraction(int(newnum / common), int(newden / common))
- __radd__ = __add__
+ __radd__ = __add__ # allow the fraction to be added to a number
def __lt__(self, other):
+ """
+ :param other: the fraction to compare
+ :return: whether the fraction is less than the other
+ """
num1 = self.num * other.den
num2 = self.den * other.num
return num1 < num2
def toFract(self, n):
+ """
+ :param n: the number to convert to a fraction
+ :return: the fraction representation of the number
+ """
if isinstance(n, int):
other = Fraction(n, 1)
elif isinstance(n, float):
wholePart = int(n)
- fracPart = n - wholePart
- # convert to 100ths???
- fracNum = int(fracPart * 100)
- newNum = wholePart * 100 + fracNum
- other = Fraction(newNum, 100)
+ fracPart = n - wholePart
+ fracNum = int(fracPart * 100) # convert to 100ths
+ newNum = wholePart * 100 + fracNum # combine the whole and fractional parts
+ other = Fraction(newNum, 100)
elif isinstance(n, Fraction):
other = n
else:
@@ -115,9 +298,12 @@
return other
def gcd(m, n):
"""
- A helper function for Fraction
+ A helper function for Fraction.
+ :param m: the first number
+ :param n: the second number
+ :return: the greatest common divisor
"""
- while m % n != 0:
+ while m % n != 0: # keep going until the gcd is found
oldm = m
oldn = n
m = oldn
@@ -126,6 +312,7 @@
print(sorted([Fraction(5, 16), Fraction(3, 16), Fraction(1, 16) + 1]))
+
data members
@@ -133,57 +320,61 @@
- The declarations of instance variables can come at the beginning of the class definition or the end. Cay Horstman, author of the “Core Java” books puts the declarations at the end of the class. I like them at the very beginning so you see the variables that are declared before you begin looking at the code that uses them. With that in mind the first part of the Fraction class definition is as follows:
+ The declarations of instance variables can come at the beginning of the class definition or the end. Cay Horstman, author of the “Core Java” books puts the declarations at the end of the class. I like them at the very beginning so you see the variables that are declared before you begin looking at the code that uses them. With that in mind shows the first part of the Fraction class definition.
-
-
+
+
- public class Fraction {
- private Integer numerator;
+ public class Fraction {
+ private Integer numerator; // notice the private modifier
private Integer denominator;
}
+
+ private
Notice that we have declared the numerator and denominator to be private.
- This means that the compiler will generate an error if another method tries to write code like the following:
+ This means that the compiler will generate an error if another method tries to write code like .
-
-
+
+
- Fraction f = new Fraction(1,2);
- Integer y = f.numerator * 10;
+ Fraction f = new Fraction(1,2);
+ Integer y = f.numerator * 10; // trying to access the numerator
+
getter method
setter method
Direct access to instance variables is not allowed in Java.
Therefore if we legitimately want to be able to access information such as the numerator or the denominator for a particular fraction we must have a getter method that returns the needed value.
- Hence, it is a very common programming practice to both provide getter methods and setter methods when needed for instance variables in Java.
+ Hence, it is a very common programming practice to both provide getter methods and setter methods when needed for instance variables in Java. shows how the getter and setter methods are written.
-
-
+
+
-public Integer getNumerator() {
+public Integer getNumerator() { // getter method
return numerator;
}
-public void setNumerator(Integer numerator) {
+public void setNumerator(Integer numerator) { // setter method
this.numerator = numerator;
}
-public Integer getDenominator() {
+public Integer getDenominator() { // getter method
return denominator;
}
-public void setDenominator(Integer denominator) {
+public void setDenominator(Integer denominator) { // setter method
this.denominator = denominator;
}
+
@@ -191,22 +382,25 @@ public void setDenominator(Integer denominator) {
Writing a constructor
+ constructor
+
Once you have identified the instance variables for your class the next thing to consider is the constructor.
In Java, constructors have the same name as the class and are declared public.
They are declared without a return type.
So any method that is named the same as the class and has no return type is a constructor.
- Our constructor will take two parameters: the numerator and the denominator.
+ Our constructor will take two parameters: the numerator and the denominator. shows the constructor for the Fraction class.
-
-
+
+
public Fraction(Integer top, Integer bottom) {
- num = top;
+ num = top; // notice the use of num instead of top
den = bottom;
}
+
this
@@ -216,18 +410,19 @@ public Fraction(Integer top, Integer bottom) {
This allows the Java compiler to do the work of dereferencing the current Java object.
Java does provide a special variable called this that works like the self variable.
In Java, this is typically only used when it is needed to differentiate between a parameter or local variable and an instance variable.
- For example this alternate definition of the the Fraction constructor uses this to differentiate between parameters and instance variables.
+ For example, shows an alternate definition of the the Fraction constructor that uses this to differentiate between parameters and instance variables.
-
-
+
+
public Fraction(Integer num, Integer den) {
- this.num = num;
+ this.num = num; // notice how we use this.num instead of num
this.den = den;
}
+
@@ -253,8 +448,8 @@ public Fraction(Integer num, Integer den) {
pass-by-value
- value of the reference
- Java is strictly pass-by-value. For primitive types (like int), a copy of the value is passed. For object types (like our Fraction), a copy of the value of the reference (the memory address) is passed.
+
+ Java is strictly pass-by-value. For primitive types (like int), a copy of the value is passed. For object types (like our Fraction), a copy of the reference(Namely, the memory address) is passed.
@@ -272,21 +467,22 @@ public Fraction(Integer num, Integer den) {
However, if you reassign the parameter to a completely new object inside the method (e.g., otherFrac = new Fraction(0,1);), it would not affect the original variable outside the method, because you are only changing the local copy of the reference.
- Let’s begin by implementing addition in Java:
+ shows the first part of the Fraction class definition.
-
-
+
+
-public Fraction add(Fraction otherFrac) {
+public Fraction add(Fraction otherFrac) {
Integer newNum = otherFrac.getDenominator() * this.numerator +
- this.denominator * otherFrac.getNumerator();
- Integer newDen = this.denominator * otherFrac.getDenominator();
- Integer common = gcd(newNum, newDen);
+ this.denominator * otherFrac.getNumerator(); // notice the use of this.
+ Integer newDen = this.denominator * otherFrac.getDenominator(); // find the new denominator
+ Integer common = gcd(newNum, newDen); // find the greatest common divisor
return new Fraction(newNum/common, newDen/common);
}
+
First you will notice that the add method is declared as public Fraction The public part means that any other method may call the add method.
@@ -296,21 +492,22 @@ public Fraction add(Fraction otherFrac) {
Second, you will notice that the method makes use of the this variable.
In this method, this is not necessary, because there is no ambiguity about the numerator and denominator variables.
- So the following version of the code is equivalent:
+ is an equivalent version of .
-
-
+
+
public Fraction add(Fraction otherFrac) {
Integer newNum = otherFrac.getDenominator() * numerator +
- denominator * otherFrac.getNumerator();
+ denominator * otherFrac.getNumerator(); // notice the absence of this.
Integer newDen = denominator * otherFrac.getDenominator();
Integer common = gcd(newNum, newDen);
return new Fraction(newNum/common, newDen/common);
}
+
The addition takes place by multiplying each numerator by the opposite denominator before adding.
@@ -357,21 +554,22 @@ public Fraction add(Fraction otherFrac) {
To solve the problem of adding an Integer and a Fraction in Java we will overload both the constructor and the add method.
We will overload the constructor so that if it only receives a single Integer it will convert the Integer into a Fraction.
We will also overload the add method so that if it receives an Integer as a parameter it will first construct a Fraction from that integer and then add the two Fractions together.
- The new methods that accomplish this task are as follows:
+ shows the new methods that accomplish this task.
-
-
+
+
-public Fraction(Integer num) {
- this.numerator = num;
+public Fraction(Integer num) {
+ this.numerator = num; // set the numerator to the Integer
this.denominator = 1;
}
-public Fraction add(Integer other) {
- return add(new Fraction(other));
+public Fraction add(Integer other) { // overload the add method when the parameter is an Integer
+ return add(new Fraction(other));
}
+
Notice that the overloading approach can provide us with a certain elegance to our code.
@@ -380,21 +578,21 @@ public Fraction add(Integer other) {
- Our full Fraction class to this point would look like the following.
+ Our full Fraction class to this point would look .
You should compile and run the program to see what happens.
-
-
+
+
public class Fraction {
private Integer numerator;
private Integer denominator;
- public Fraction(Integer num, Integer den) {
+ public Fraction(Integer num, Integer den) { // constructor that takes two Integers
this.numerator = num;
this.denominator = den;
}
- public Fraction(Integer num) {
+ public Fraction(Integer num) { // constructor that takes a single Integer, sets the denominator to 1
this.numerator = num;
this.denominator = 1;
}
@@ -410,10 +608,10 @@ public class Fraction {
Integer common = gcd(newNum,newDen);
return new Fraction(newNum/common, newDen/common );
}
- public Fraction add(Integer other) {
+ public Fraction add(Integer other) { // overload the add method when the parameter is an Integer
return add(new Fraction(other));
}
- private static Integer gcd(Integer m, Integer n) {
+ private static Integer gcd(Integer m, Integer n) { // a helper method for the add method
while (m % n != 0) {
Integer oldm = m;
Integer oldn = n;
@@ -422,39 +620,80 @@ public class Fraction {
}
return n;
}
- public static void main(String[] args) {
+ public static void main(String[] args) { // a main method
Fraction f1 = new Fraction(1,2);
System.out.println(f1.add(1));
}
}
-
-
-
-
- Inheritance
-
-
-
- If you ran the program above you probably noticed that the output is not very satisfying. Chances are your output looked something like this:
+
+
+ If you ran , you probably noticed that the output is not very satisfying. Chances are your output looked something like .
-
-
+
+
Fraction@6ff3c5b5
+
The reason is that we have not yet provided a friendly string representation for our Fraction objects.
Just like in Python, whenever an object is printed by the println method it must be converted to string format.
In Python you can control how that looks by writing an __str__ method for your class.
- If you do not then you will get the default, which looks something like the above.
+ If you do not then you will get the default, which looks something like . We will see how to provide a friendly string representation for our Fraction class in .
-
+
+
+
+ Rearrange the blocks to create a Printer class with two overloaded printData methods—one that accepts an int and another that accepts a String.
+
+
+
+
+ public class Printer {
+
+
+
+
+ public void printData(int number) {
+ System.out.println("Number: " + number);
+ }
+
+
+ public void printData(int number) {
+ System.out.println("Number: " + number);
+
+
+
+
+
+ public void printData(String text) {
+ System.out.println("Text: " + text);
+ }
+
+
+ public void printData(int text) {
+ System.out.println("Text: " + text);
+ }
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+ Inheritance
The Object Class
@@ -462,7 +701,7 @@ Fraction@6ff3c5b5
toString
In Java, the equivalent of __str__ is the toString method.
- Every object in Java already has a toString method defined for it because every class in Java automatically inherits from the Object class.
+ Every object in Java already has a toString method defined for it because every class in Java automatically inherits from the Object class.
The Object class provides default implementations for the following methods.
@@ -526,54 +765,57 @@ Fraction@6ff3c5b5
We are not interested in most of the methods on that list, and many Java programmers live happy and productive lives without knowing much about most of the methods on that list.
- However, to make our output nicer we will implement the toString method for the Fraction class.
- A simple version of the method is provided below.
+ However, to make our output nicer we will implement the toString method for the Fraction class. shows a simple version of the method.
-
-
+
+
public String toString() {
- return numerator.toString() + "/" + denominator.toString();
+ return numerator.toString() + "/" + denominator.toString(); // convert to a string
}
+
+ equals
The other important class for us to implement from the list of methods inherited from Object is the equals method.
In Java, when two objects are compared using the == operator they are tested to see if they are exactly the same object (that is, do the two objects occupy the same exact space in the computer’s memory?).
This is also the default behavior of the equals method provided by Object.
The equals method allows us to decide if two objects are equal by looking at their instance variables.
- However it is important to remember that since Java does not have operator overloading if you want to use your equals method you must call it directly.
+ However it is important to remember that since Java does not have operator overloading if you want to use your equals method you must call it directly.
Therefore once you write your own equals method:
-
-
+
+
-object1 == object2
+object1 == object2 // this checks to see if the two objects are the same object in memory
+
- is NOT the same as:
+ is NOT the same as .
-
-
+
+
-object1.equals(object2)
+object1.equals(object2) // this checks to see if the two objects are equal by looking at their instance variables
+
- Here is an equals method for the Fraction class:
+ is an equals method for the Fraction class.
-
-
+
+
-public boolean equals(Fraction other) {
+public boolean equals(Fraction other) { // check if this fraction is equal to another fraction
Integer num1 = this.numerator * other.getDenominator();
Integer num2 = this.denominator * other.getNumerator();
if (num1 == num2)
@@ -583,6 +825,7 @@ public boolean equals(Fraction other) {
}
+
One important thing to remember about equals is that it only checks to see if two objects are equal – it does not have any notion of less than or greater than.
@@ -601,26 +844,27 @@ public boolean equals(Fraction other) {
If you look at the documentation for Integer you will see that Integer’s parent class is Number.
Number is an abstract class that specifies several methods that all of its children must implement.
In Java an abstract class is more than just a placeholder for common methods.
- In Java an abstract class has the power to specify certain methods that all of its children must implement.
+ In Java an abstract class has the power to specify certain methods that all of its children must implement.
You can trace this power back to the strong typing nature of Java.
- Here is code that makes the Fraction class a child of Number:
+ makes the Fraction class a child of Number.
-
-
+
+
-public class Fraction extends Number {
+public class Fraction extends Number { // fraction class is a child of Number
...
}
+
- extends
- The keyword extends tells the compiler that the class Fraction extends, or adds new functionality to the Number class.
+ extending a class
+ The keyword extends tells the compiler that the class Fraction extends, or adds new functionality to the Number class.
A child class always extends its parent.
@@ -657,26 +901,27 @@ public class Fraction extends Number {
- This really isn’t much work for us to implement these methods, as all we have to do is some type conversion and some division:
+ This really isn’t much work for us to implement these methods, as all we have to do is some type conversion and some division as shown in .
-
-
+
+
-public double doubleValue() {
+public double doubleValue() { // convert to a double
return numerator.doubleValue() / denominator.doubleValue();
}
-public float floatValue() {
+public float floatValue() { // convert to a float
return numerator.floatValue() / denominator.floatValue();
}
-public int intValue() {
+public int intValue() { // convert to an int
return numerator.intValue() / denominator.intValue();
}
-public long longValue() {
+public long longValue() { // convert to a long
return numerator.longValue() / denominator.longValue();
}
+
is-a
@@ -688,34 +933,66 @@ public long longValue() {
- However, and this is a big however, it is important to remember that if you specify Number as the type of a particular parameter then the Java compiler will only let you use the methods of a Number: longValue, intValue, floatValue, and doubleValue.
+ However, and this is a big however, it is important to remember that if you specify Number as the type of a particular parameter then the Java compiler will only let you use the methods of a Number: longValue, intValue, floatValue, and doubleValue.
- Suppose you try to define a method as follows:
+ Suppose you try to define a method as .
-
-
+
+
public void test(Number a, Number b) {
- a.add(b);
+ a.add(b); // this is a bad idea
}
+
The Java compiler would give an error because add is not a defined method of the Number class.
- You will still get this error even if all your code that calls this test method passes two Fractions as parameters (remember that Fraction does implement add).
+ You will still get this error even if all your code that calls this test method passes two Fractions as parameters (remember that Fraction does implement add).
+
+
+
+
+ Construct the toString method for the Fraction class so that printing a
+ fraction shows it in the form numerator/denominator. Drag the blocks into the correct order on the right.
+
+
+
+
+
+ public String toString() {
+
+
+ public void toString() {
+
+
+
+
+
+ return numerator.toString() + "/" + denominator.toString();
+
+
+ numerator.toString() + "/" + denominator.toString();
+
+
+
+
+ }
+
+
+
Interfaces
- Comparable
single inheritance
Lets turn our attention to making a list of fractions sortable by the standard Java sorting method Collections.sort.
In Python, we would just need to implement the __cmp__ method.
@@ -741,11 +1018,11 @@ public void test(Number a, Number b) {
The Comparable interface says that any object that claims to be Comparable must implement the compareTo method.
- Here is an excerpt from the official documentation for the compareTo method as specified by the Comparable interface.
+ Here is an excerpt from the official documentation for the compareTo method as specified by the Comparable interface. shows the excerpt.
-
-
+
+
int compareTo(T o)
Compares this object with the specified object for order. Returns a
@@ -757,37 +1034,42 @@ iff y.compareTo(x) throws an exception.)
...
+
- To make our Fraction class Comparable we must modify the class declaration line as follows:
+ To make our Fraction class Comparable we must modify the class declaration line as shown in .
-
-
+
+
-public class Fraction extends Number implements Comparable<Fraction> {
+public class Fraction extends Number implements Comparable<Fraction> { // fraction class is a child of Number and implements the Comparable interface
...
}
+
The specification Comparable<Fraction> makes it clear that Fraction is only comparable with another Fraction.
- The compareTo method could be implemented as follows:
+ The compareTo method could be implemented as shown in .
-
-
+
+
-public int compareTo(Fraction other) {
+public int compareTo(Fraction other) { // compare this fraction with another fraction
Integer num1 = this.numerator * other.getDenominator();
Integer num2 = this.denominator * other.getNumerator();
return num1 - num2;
}
+
+
+
Static member variables
@@ -795,41 +1077,43 @@ public int compareTo(Fraction other) {
Suppose that you wanted to write a Student class so that the class could keep track of the number of students it had created.
Although you could do this with a global counter variable that is an ugly solution.
The right way to do it is to use a static variable.
- In Python, we could do this as follows:
+ shows how to do this in Python.
-
-
+
+
class Student:
numStudents = 0
- def __init__(self, id, name):
+ def __init__(self, id, name):
self.id = id
self.name = name
- Student.numStudents = Student.numStudents + 1
+ # this is a static variable, that can be accessed without the self prefix
+ Student.numStudents = Student.numStudents + 1
def main():
for i in range(10):
- s = Student(i,"Student-"+str(i))
+ s = Student(i,"Student-"+str(i)) # create a new Student object
print('Number of students:', Student.numStudents)
main()
+
- In Java, we would write this same example using a static declaration.
+ shows how to do this in Java.
-
-
+
+
public class Student {
- public static Integer numStudents = 0;
+ public static Integer numStudents = 0; // static member variable, shared by all instances of the class
private int id;
private String name;
public Student(Integer id, String name) {
this.id = id;
this.name = name;
- numStudents = numStudents + 1;
+ numStudents = numStudents + 1; // a static variable, that can be accessed without the Student prefix
}
public static void main(String[] args) {
for(Integer i = 0; i < 10; i++) {
@@ -840,10 +1124,11 @@ public class Student {
}
+
static member variable
- In this example notice that we create a static member variable by using the static modifier on the variable declaration. Once a variable has been declared static in Java it can be accessed from inside the class without prefixing the name of the class as we had to do in Python.
+ In , notice that we create a static member variable by using the static modifier on the variable declaration. Once a variable has been declared static in Java it can be accessed from inside the class without prefixing the name of the class as we had to do in Python.
@@ -854,10 +1139,14 @@ public class Student {
We have already discussed the most common static method of all, main. However in our Fraction class we also implemented a method to calculate the greatest common divisor for two fractions (gdc). There is no reason for this method to be a member method since it takes two Integer values as its parameters. Therefore we declare the method to be a static method of the class. Furthermore, since we are only going to use this gcd method for our own purposes we can make it private.
+
+ shows the implementation of the static gcd helper method in Java.
+
-
+
+
-private static Integer gcd(Integer m, Integer n) {
+private static Integer gcd(Integer m, Integer n) { // static method to compute the greatest common divisor of two integers
while (m % n != 0) {
Integer oldm = m;
Integer oldn = n;
@@ -868,17 +1157,18 @@ private static Integer gcd(Integer m, Integer n) {
}
+
Full Implementation of the Fraction Class
- Here is a final version of the Fraction class in Java, which includes all the features we discussed:
+ shows a final version of the Fraction class in Java, which includes all the features we discussed:
-
+
import java.util.ArrayList;
import java.util.Collections;
@@ -972,6 +1262,7 @@ public class Fraction extends Number implements Comparable<Fraction> {
}
+
diff --git a/source/ch7_recursion.ptx b/source/ch7_recursion.ptx
index a0d2c01..f04f71c 100644
--- a/source/ch7_recursion.ptx
+++ b/source/ch7_recursion.ptx
@@ -14,29 +14,30 @@
- Let's take the familiar factorial function, which calculates n! (read as "n factorial"), so for example 5! = 5 × 4 × 3 × 2 × 1 = 120. Factorial is a classic example of recursion, where the function calls itself with a smaller value until it reaches a base case.
- In general, n! = n \times (n-1) \times (n-2) \times \cdots \times 2 \times 1,
- or recursively defined as n! = n \times (n-1)! with base cases 0! = 1 and 1! = 1.
+ Let's take the familiar factorial function, which calculates n! (read as "n factorial"), so for example 5! = 5 × 4 × 3 × 2 × 1 = 120. Factorial is a classic example of recursion, where the function calls itself with a smaller value until it reaches a base case.
+ In general, n! = n \times (n-1) \times (n-2) \times \cdots \times 2 \times 1,
+ or recursively defined as n! = n \times (n-1)! with base cases 0! = 1 and 1! = 1.
You may recall mathematical notation using the symbol \sum (Greek letter sigma)
to represent "sum." For example, when we sum all elements in an array, we write
- \sum_{i=0}^{n-1} a_i, where i=0 below the symbol indicates we start at index 0,
+ \sum_{i=0}^{n-1} a_i, where i=0 below the symbol indicates we start at index 0,
n-1 above it means we end at index n-1, and a_i represents the array
- element at each index i. Similarly, \sum_{i=1}^{n} i means "sum all integers
+ element at each index i. Similarly, \sum_{i=1}^{n} i means "sum all integers
i from 1 to n."
Factorial involves multiplication rather than addition, so we use the product symbol
- \prod (Greek letter pi): n! = \prod_{i=1}^{n} i, which means "multiply
+ \prod (Greek letter pi): n! = \prod_{i=1}^{n} i, which means "multiply
all integers i from 1 to n." Both summation and factorial can be expressed
recursively—summation as the first element plus the sum of remaining elements, and factorial
- as n \times (n-1)!.
+ as n \times (n-1)!.
- Here is a Python implementation of factorial using just one function:
+ is the Python implementation of the factorial function. It checks for negative numbers, defines the base case for 0! and 1!, and implements the recursive step.
-
+
+
def factorial(n):
# Check for negative numbers
@@ -54,11 +55,17 @@ print(str(number) + "! is " + str(factorial(number)))
+
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 MathTools with a method factorial, and we call it from the main function.
-
+
+ is the Python implementation of the factorial function as a method within a class. It maintains the same logic as the previous function but is now encapsulated within a class structure.
+
+
+
+
class MTools:
def factorial(self, n):
@@ -81,14 +88,16 @@ def main():
main()
+
See if you can spot the differences in the Java version below.
- Here is the equivalent Java code:
+ is the Java implementation of the factorial function. It follows the same logic as the Python version but adapts to Java's syntax and type system.
-
+
+
public class MTools {
public static int factorial(int n) {
@@ -112,6 +121,7 @@ public class MTools {
}
+
Notice the key differences from Python: instead of def factorial(n):, Java uses public static int factorial(int n) which declares the method's visibility as public, that it belongs to the class rather than an instance (hence, static), 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 {} instead of indentation.
@@ -129,9 +139,10 @@ public class MTools {
- First, let's see what happens if we try to write a recursive array sum function without using a helper method. In this approach, the user must provide the starting index, which is awkward and exposes implementation details:
+ First, let's see what happens if we try to write a recursive array sum function without using a helper method. In this approach, the user must provide the starting index, which is awkward and exposes implementation details. shows a Python version.
-
+
+
class ArrayProcessor:
def sum_array(self, arr, index):
@@ -156,11 +167,13 @@ def main():
main()
+
- This approach has a significant problem, namely that users must remember to start with index 0. Hence, the method signature is cluttered with an implementation detail, and it's easy to make a mistake by passing the wrong starting index. The same awkward pattern appears in Java:
+ 's approach has a significant problem, namely that users must remember to start with index 0. Hence, the method signature is cluttered with an implementation detail, and it's easy to make a mistake by passing the wrong starting index. The same awkward pattern appears in Java as shown in .
-
+
+
public class ArrayProcessor {
public static int sumArray(int[] arr, int index) {
@@ -182,14 +195,16 @@ public class ArrayProcessor {
}
+
Both versions force users to understand and provide implementation details they shouldn't need to know about. Now let's see how helper methods solve this problem by providing a clean, user-friendly interface. Notice how the public method only requires the array itself, and the hidden recursive logic tracks the current index position.
- Here's the improved Python version using a helper method:
+ shows the improved Python version using a helper method.
-
+
+
class ArrayProcessor:
def sum_array(self, arr):
@@ -223,15 +238,17 @@ def main():
main()
+
separation of concerns
The key insight here is called the separation of concerns. The public sum_array method provides a user-friendly interface—callers just pass an array and get the sum. Users don't need to know about indexes or how the recursion works internally. The private _sum_helper method handles the recursive logic with the extra parameter needed to track progress through the array.
- Now let's see the improved Java version using a helper method:
+ The same helper method pattern can be applied in Java, as shown in . The public method sumArray provides a clean interface, while the private helper method sumHelper manages the recursion and index tracking.
-
+
+
import java.util.Arrays;
@@ -263,6 +280,7 @@ public class ArrayProcessor {
}
+
Compare these improved versions with the earlier problematic ones. Notice how much cleaner the method calls become: processor.sum_array(numbers) in Python and sumArray(numbers) in Java. Users no longer need to worry about providing a starting index or understanding the internal mechanics of the recursion. The helper method pattern creates a clear separation between what users need to know (just pass an array) and the implementation details (tracking the index through recursion).
@@ -298,10 +316,11 @@ public class ArrayProcessor {
- The following Python code demonstrates a situation where a function calls itself indefinitely without a base case, leading to a RecursionError due to overflowing the call stack.
+ The following Python code in demonstrates a situation where a function calls itself indefinitely without a base case, leading to a RecursionError due to overflowing the call stack.
-
-
+
+
+
def cause_recursion_error():
"""
This function calls itself without a base case, guaranteeing an error.
@@ -317,12 +336,14 @@ public class ArrayProcessor {
cause_recursion_error()
+
- The following Java code demonstrates a similar situation, where a method calls itself indefinitely without a base case, leading to a StackOverflowError.
+ The following Java code in demonstrates a similar situation, where a method calls itself indefinitely without a base case, leading to a StackOverflowError.
-
-
+
+
+
public class Crash {
public static void causeStackOverflow() {
// The line below will start the infinite recursion.
@@ -340,6 +361,7 @@ public class ArrayProcessor {
}
+
diff --git a/source/ch8_filehandling.ptx b/source/ch8_filehandling.ptx
index ba5d0cf..d9656b0 100644
--- a/source/ch8_filehandling.ptx
+++ b/source/ch8_filehandling.ptx
@@ -7,65 +7,80 @@
Class Imports
- File handling is an integral part of programming. Most programming languages have the ability to create, read from, write to, and delete, files. In Python, most built-in libraries are available without needing to explicitly import additional packages, but some libraries like math do need to be imported. Consider the following.
+ File handling is an integral part of programming. Most programming languages have the ability to create, read from, write to, and delete, files. In Python, most built-in libraries are available without needing to explicitly import additional packages, but some libraries like math do need to be imported. shows an example of importing the math library in Python.
-
+
+
+
import math
- print(math.sqrt(25))
+ print(math.sqrt(25)) # notice the lower case 'm' in math
+
- Delete the first line that says import math and see what happens. The import math is needed. The same program in Java would look like this:
+ Delete the first line that says import math and see what happens. The import math is needed. The same program in Java would look like .
-
+
+
+
import java.lang.Math;
public class SquareRoot {
public static void main(String[] args) {
- System.out.println(Math.sqrt(25));
+ System.out.println(Math.sqrt(25)); // notice the upper case 'M' in Math
}
}
+
+
Note the use of import java.lang.Math; in the above to import the Math class. Unlike Python, Java requires explicit import for most libraries, including the Math class and many classes related to file handling.
- Much like the Math class, in order for your program to work with files you need use import. Java includes a class called File in the io library. This class allows you to create File objects, and use its public methods.
+ Much like the Math class, in order for your program to work with files you need use import. Java includes a class called File in the io library shown in . This class allows you to create File objects, and use its public methods.
-
+
+
import java.io.File;
+
+
- The Scanner class from the util library will need to be imported if there is any need for a program to read a file. It should be noted that this library is unnecessary if the program will not be reading any data from a file.
+ The Scanner class from the util library will need to be imported if there is any need for a program to read a file as shown in . It should be noted that this library is unnecessary if the program will not be reading any data from a file.
-
-
+
+
import java.util.Scanner;
+
- The FileWriter class can be used to write to files. In the same way that the Scanner class isn't needed unless the program will read from a file, the FileWriter class isn't needed unless the program will write to a file.
+ The FileWriter class can be used to write to files as shown in . In the same way that the Scanner class isn't needed unless the program will read from a file, the FileWriter class isn't needed unless the program will write to a file.
-
+
+
import java.io.FileWriter;
+
- Finally, these last two classes provide error handling and must be used in tandem with the File class when reading from or writing to files. IOException handles file creation and writing errors, while FileNotFoundException handles errors when trying to read files.
+ Finally, these last two classes provide error handling and must be used in tandem with the File class when reading from or writing to files as shown in . IOException handles file creation and writing errors, while FileNotFoundException handles errors when trying to read files.
-
+
+
import java.io.IOException;
import java.io.FileNotFoundException;
-
+
+
@@ -73,10 +88,10 @@
- We will now create a File object. It is important to create a meaningful name for the File object. We will call ours myFile, and we will call our class CreateFileObject.
+ We will now create a File object. It is important to create a meaningful name for the File object. We will call ours myFile, and we will call our class CreateFileObject. shows the code to create a File object in Java.
-
-
+
+
import java.io.File;
@@ -90,6 +105,7 @@ public class CreateFile {
}
+
@@ -103,10 +119,10 @@ public class CreateFile {
- First, lets look at the equivalent Python code:
+ shows the equivalent code to create a file in Python.
-
-
+
+
filename = "newfile.txt"
print("Attempting to write to '" + filename + "' using 'w' mode...")
@@ -120,12 +136,13 @@ public class CreateFile {
+
- Now, let's look at Java code that accomplishes the same task:
+ shows the equivalent code to create a file in Java.
-
-
+
+
import java.io.File;
import java.io.IOException;
@@ -148,12 +165,55 @@ public class CreateFile {
}
+
You may have noticed the use of another method from the File class; getName(). This method returns a string containing the name of the file.
+
+
+
+
+ Construct a short Java program that creates a File object for "myfile.txt"
+ and prints it. Drag the blocks into the correct order on the right.
+
+
+
+
+
+ import java.io.File;
+
+
+ import java.io.Scanner;
+
+
+
+
+ public class CreateFile {
+ public static void main(String[] args) {
+
+
+
+
+ File myFile = new File("myfile.txt");
+
+
+ File myFile = new File();
+
+
+
+
+ System.out.println(myFile);
+
+
+
+ }
+ }
+
+
+
@@ -163,9 +223,11 @@ public class CreateFile {
Let’s take a look at how we can use Python to understand how read file contents in Java. In order to read files generally you iterate through each line in the file and read the line's content. In Java, you read files in a very similar way, however in Java we will use the Scanner class in order to iterate through the lines.
- Consider the following Python code example that reads each line of the file and prints it to the console.
+ Consider that reads each line of and prints it to the console.
-
+
+ Data file for reading example
+
1
2
@@ -177,8 +239,9 @@ public class CreateFile {
8
-
-
+
+
+
filename = "myfile.txt"
try:
@@ -192,35 +255,76 @@ public class CreateFile {
print("file could not be opened")
+
- The following Java code functions very similarly to the previous Python. The main difference here is that unlike Python, in Java we use the Scanner object to iterate through and read lines in the file. You will notice that the structure of the Java code is still similar to the Python; Both use a try and catch statement to read the file and catch any errors.
+ functions very similarly to . The main difference here is that unlike Python, in Java we use the Scanner object to iterate through and read lines in the file. You will notice that the structure of the Java code is still similar to the Python; Both use a try and catch statement to read the file and catch any errors.
-
+
+
import java.io.File;
- import java.io.FileNotFoundException;
+ import java.io.FileNotFoundException; // This import is necessary to handle the exception if the file is not found
import java.util.Scanner;
public class ReadFile {
public static void main (String[] args) {
String filename = "myfile.txt";
- try (Scanner fileReader = new Scanner(new File(filename))) {
- while (fileReader.hasNextLine()) {
+ try (Scanner fileReader = new Scanner(new File(filename))) { // try to open the file and create a Scanner object
+ while (fileReader.hasNextLine()) { // while there is a next line in the file
String data = fileReader.nextLine();
System.out.println(data);
}
}
- catch (FileNotFoundException e) {
+ catch (FileNotFoundException e) { // and catch the exception if the file is not found
System.out.println("Error: The file '" + filename + "' was not found.");
}
}
}
+
You may have noticed that there are some new methods you haven't seen yet. The hasNextLine() method checks if there is a next line in the file, and returns false if there isn't. This method allows us to iterate over every line till there is no next line. The nextLine() method of the Scanner object returns the next line in the file as a string.
+
+
+
+
+ Construct the part of a Java program that opens a file with a Scanner and
+ prints each line until there are no more lines. Drag the blocks into the correct order on the right.
+
+
+
+
+
+ try (Scanner fileReader = new Scanner(new File(filename))) {
+
+
+ try (Scanner fileReader = new Scanner(filename)) {
+
+
+
+
+
+ while (fileReader.hasNextLine()) {
+
+
+ while (fileReader.nextLine()) {
+
+
+
+
+ String data = fileReader.nextLine();
+ System.out.println(data);
+
+
+
+ }
+ }
+
+
+
@@ -231,10 +335,11 @@ public class CreateFile {
- Let us create the framework for a class that will write to a file. Let's call this class WriteFile:
+ shows the framework for a class that will write to a file. Let's call this class WriteFile.
-
-
+
+
+
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -245,39 +350,46 @@ public class CreateFile {
}
}
+
- Next, we will create a FileWriter object. Let's call it myWriter. The equivalent Python code to this operation is:
+ Next, we will create a FileWriter object. Let's call it myWriter. shows the code to create a myWriter object in Python.
-
-
+
+
with open("myfile.txt", "w") as myWriter:
+
- The Java code to create a FileWriter object is:
+ shows the Java code to create a FileWriter object. Note that the FileWriter object is created with the name of the file to write to as an argument. If the file does not exist, it will be created. If it does exist, it will be overwritten.:
-
+
+
FileWriter myWriter = new FileWriter("myfile.txt");
+
- In this next step, we will use the write() method from the FileWriter class. This method will take any data within the parenthesis and write that data to the file selected. The write() method takes most standard data types. First, how this step is completed with Python:
+ In this next step, we will use the write() method from the FileWriter class. This method will take any data within the parenthesis and write that data to the file selected. The write() method takes most standard data types. The shows the code to write to a file in Python.
-
-
+
+
my_writer.write("File successfully updated!")
+
- And the Java equivalent. This is almost completely identical except for the second line, which is very important!
+ shows the Java equivalent. This is almost completely identical except for the second line, which is very important!
-
+
+
myWriter.write("File successfully updated!");
myWriter.close();
+
@@ -286,10 +398,11 @@ public class CreateFile {
- Next, we will again add the required try/catch blocks utilizing the IOException class. Just like with creating files, the program will not compile without these crucial additions! We will also add some print statements to inform us of the success of the file write operation. First, a Python example:
+ Next, we will again add the required try/catch blocks utilizing the IOException class. Just like with creating files, the program will not compile without these crucial additions! We will also add some print statements to inform us of the success of the file write operation. shows the code to write to a file in Python.
-
+
+
try:
with open("myfile.txt", "w") as my_writer:
my_writer.write("File successfully updated!")
@@ -299,12 +412,14 @@ public class CreateFile {
import traceback
traceback.print_exc()
+
- And the equivalent Java code:
+ shows the Java equivalent.
-
+
+
try {
FileWriter myWriter = new FileWriter("myfile.txt");
myWriter.write("File successfully updated!");
@@ -315,16 +430,23 @@ public class CreateFile {
e.printStackTrace();
}
+
- And that's it! We will add our code to the foundational code for a complete program. First, an example of equivalent Python code:
+ And that's it! We will add our code to the foundational code for a complete program. First, shows the completed Python code.
-
+
+
+ Data file for writing example
+
-
+
+
+
+
try:
with open("myfile.txt", "w") as my_writer:
@@ -336,16 +458,22 @@ public class CreateFile {
traceback.print_exc()
+
- The completed Java code:
+ shows the completed Java code.
-
+
+ Data file for writing example
+
-
+
+
+
+
import java.io.FileWriter;
import java.io.IOException;
@@ -363,8 +491,10 @@ public class CreateFile {
}
}
}
-
+ ~
+
+
@@ -373,22 +503,30 @@ public class CreateFile {
- Speaking of overwriting data, what if we want to append text to the end of any text already in myfile.txt? To accomplish this, we can pass a boolean argument along with the file name when creating a new data argument:
+ Speaking of overwriting data, what if we want to append text to the end of any text already in myfile.txt? To accomplish this, we can pass a boolean argument along with the file name when creating a new data argument as shown in .
-
+
+
FileWriter myWriter = new FileWriter("myfile.txt", true); // true enables append mode
+
- Now, when we use write() method like before, the text will be appended if there is already tSext in the document. If we were to update our code to include the boolean argument:
+ Now, when we use write() method like before, the text will be appended if there is already tSext in the document. If we were to update our code to include the boolean argument as shown in .
-
+
+
+ Data file for writing example
+
-
+
+
+
+
import java.io.FileWriter;
import java.io.IOException;
@@ -408,42 +546,50 @@ public class CreateFile {
}
+
- Then if we run the program twice, the contents of myfile.txt would be:
+ Then if we run the program twice, the contents of myfile.txt would be as shows.
-
+
+
File successfully updated!File successfully updated!
-
+
+
- This doesn't look very good! If we want each additional write to appear on a new line? A simple solution is to use the \n newline character:
+ This doesn't look very good! If we want each additional write to appear on a new line? A simple solution is to use the \n newline character as shows.
-
+
+
myWriter.write("File successfully updated!\n"); // Added newline character
myWriter.close();
+
- Running the code with the newline character twice will result in the following contents in myfile.txt:
+ Running the code with the newline character twice will result in the following contents in myfile.txt as shows.
-
+
+
File successfully updated!
File successfully updated!
-
+
+
+
Deleting Files
- Lastly, we will take a look at using Java to delete a file. This is pretty straight-forward and follows the structure used to create files. Here is the CreateFile class from before that will be used to create a file that we will soon delete:
+ Lastly, we will take a look at using Java to delete a file. This is pretty straight-forward and follows the structure used to create files. shows the CreateFile class from before that will be used to create a file that we will soon delete:
-
+
import java.io.File;
import java.io.IOException;
@@ -466,15 +612,17 @@ public class CreateFile {
}
+
- And finally, we have Java code that deletes a file. We will call this class DeleteFile:
+ And finally, shows the Java code that deletes a file. We will call this class DeleteFile:
-
-
+
+
+
import java.io.File;
import java.io.IOException;
@@ -499,7 +647,7 @@ public class DeleteFile {
-
+
Note that this is almost identical to the code within the try block of the CreateFile class that we made earlier. The key difference is the use of the delete() method which will delete the file with the name that was linked to the myFile object. Similar to the createNewFile() method, it will return true if the file exists and can be deleted, and false if the file cannot be deleted.
diff --git a/source/ch9_commonmistakes.ptx b/source/ch9_commonmistakes.ptx
index 1a041b9..4dca391 100644
--- a/source/ch9_commonmistakes.ptx
+++ b/source/ch9_commonmistakes.ptx
@@ -23,8 +23,9 @@
- Consider the following example where we have a method that multiplies a number by two. We can add print statements to help us debug the code:
+ Consider the following example where we have a method that multiplies a number by two. We can add print statements to help us debug the code and verify that the method is being called correctly and returning the expected result as shown below in .
+
// DebugExample.java
@@ -45,8 +46,9 @@
}//End of class
+
- In the example above, System.out.println() is used inside both main and multiplyByTwo() to trace what values are being passed and returned. This kind of print-based debugging can quickly reveal logic errors, unexpected behavior, or whether a method is even being called. However, overuse of this technique will often take more time than using the debugging tools that are built into your IDE.
+ In , System.out.println() is used inside both main and multiplyByTwo() to trace what values are being passed and returned. This kind of print-based debugging can quickly reveal logic errors, unexpected behavior, or whether a method is even being called. However, overuse of this technique will often take more time than using the debugging tools that are built into your IDE.
Useful tools in the built-in Java debugger can help you step through your code, inspect variables, and evaluate expressions at runtime. Familiarizing yourself with these tools can greatly enhance your debugging efficiency.
@@ -61,6 +63,7 @@
A common mistake in Java is to forget that every statement must end with a semicolon (;).
+
// Histo.java
@@ -75,8 +78,9 @@
}//End of class
+
- The error "';' expected" on line 7 of Histo.java means that a semicolon is missing at the end of the statement Scanner data = null. In Java, every statement must be terminated with a semicolon (;) to indicate its completion. The arrow points to null because that's where the compiler expected to find the semicolon.
+ The error "';' expected" on line 7 of Histo.java in means that a semicolon is missing at the end of the statement Scanner data = null. In Java, every statement must be terminated with a semicolon (;) to indicate its completion. The arrow points to null because that's where the compiler expected to find the semicolon.
@@ -85,8 +89,9 @@
Forgetting to declare your variables
In Python, you can use a variable without declaring it first, but in Java, you must declare all variables before using them.
- If you try to use a variable that has not been declared, the Java compiler will give you an error message like this:
+ shows If you try to use a variable that has not been declared, the Java compiler will give you an error message like this:
+
import java.util.ArrayList; // Import necessary class
@@ -106,17 +111,69 @@
} // End of class
+
The 'cannot find symbol' error for the variable count on line 6 indicates that count was used before it was declared within the Histo class. In Java, all variables must be explicitly declared with a data type (e.g., int, String, ArrayList<Integer>) before they can be assigned a value or referenced in any way. The arrow in the error message points to where the undeclared variable count was first encountered. To resolve this, count needs to be declared with its appropriate type (e.g., ArrayList<Integer> count;) before any attempt to initialize or use it.
+
+
+
+ Based on , select all of the
+ statements that are true about declaring variables in Java.
+
+
+
+
+
+ Every variable must be declared with a data type before it is used.
+
+
+ Correct! Java requires a variable to be declared with its type before it can be assigned or referenced.
+
+
+
+
+ The "cannot find symbol" error happens because count was used before being declared.
+
+
+ Correct! That error means the compiler reached a variable it has no declaration for.
+
+
+
+
+ Writing ArrayList<Integer> count; before using count would fix the "cannot find symbol" error.
+
+
+ Correct! Declaring count with its type resolves the error.
+
+
+
+
+ Java lets you use a variable without declaring it first, just like Python.
+
+
+ Incorrect. Unlike Python, Java requires all variables to be declared before use.
+
+
+
+
+ The error can be fixed by adding an import statement.
+
+
+ Incorrect. The import is already present; the problem is the missing variable declaration, not a missing import.
+
+
+
+
Not importing a class
- In Python, many classes are available by default. However, in Java, you must explicitly import most classes from external packages that you want to use.
+ In Python, many classes are available by default. However, in Java, you must explicitly import most classes from external packages that you want to use . If you forget to import a class, the compiler will give you an error message like this:
+
@@ -131,8 +188,9 @@
} // End of class
+
- You may notice that this error message looks similar to the previous one, however, it has an entirely different cause. In Java, classes like Scanner that are part of external packages (like java.util) must be explicitly imported into your source file. Java does not automatically recognize these classes. To resolve this error, you need to add an import statement for the Scanner class at the beginning of your Histo.java file, typically import java.util.Scanner;.
+ You may notice that this error message looks similar to the previous one , however, it has an entirely different cause. In Java, classes like Scanner that are part of external packages (like java.util) must be explicitly imported into your source file. Java does not automatically recognize these classes. To resolve this error, you need to add an import statement for the Scanner class at the beginning of your Histo.java file, typically import java.util.Scanner;.
@@ -142,6 +200,7 @@
Unlike Python, where you can create a new object without explicitly using a keyword, Java requires the new keyword to instantiate a new object.
+
// Histo.java // The filename for this example
@@ -158,8 +217,9 @@
} // End of class
+
- This error message occurs when you forget to use the new keyword to instantiate an object.
+ The error message in occurs when you forget to use the new keyword to instantiate an object.
Specifically, on line 8 of Histo.java, data = Scanner(new File("test.dat")); leads to a 'cannot find symbol' error.
While the message states 'symbol: method Scanner(File)', this can be misleading.
Java incorrectly interprets Scanner() as an attempt to call a static method named Scanner within the Histo class
@@ -175,6 +235,8 @@
Java is a statically typed language, meaning you must specify the type of objects that can be stored in a container like an ArrayList. If you forget to declare the type, the compiler will give you an error.
+
+
// UncheckedWarningDemo.java
@@ -194,6 +256,7 @@
} // End of class
+
This is a compiler warning, not an error, indicating a potential type safety issue. It occurs because you are calling the add() method on rawList, which is an ArrayList used as a raw type (i.e., without specifying a generic type like <String> or <Integer>).