Module 4: Strings, User Input, and Comments
Module Overview
In this module, you'll learn about working with strings, gathering user input through the console, and documenting your code with comments in Java.
Learning Objectives
- Declare a variable that is assigned a String literal value
- Use the String class's methods to extract a string at a provided start and end location
- Use the String class's indexOf method to locate the first occurrence of a provided substring
- Implement code to concatenate String objects using the + operator
- Recall that when a non-String value is concatenated with a String object, an implicit conversion of the value to a String object occurs
- Use a StringBuilder to incrementally append values in order to create a String object
- Use String.format() to build a formatted String object with at least one substitution
- Implement code to receive input from the user through the console
- Write code comments to describe the functionality or use of code
- Comment out code to temporarily disable it
Content
Strings
Working with Strings in Java
Strings are sequences of characters and are one of the most commonly used data types in Java. The String
class provides many useful methods for manipulating text.
Creating Strings
// String literal - most common way
String greeting = "Hello, World!";
// Using the String constructor
String message = new String("Welcome to Java");
// Empty string
String empty = "";
String Immutability
Strings in Java are immutable, which means once a String object is created, it cannot be changed. When you perform operations on a String, a new String object is created.
String name = "John";
name = name + " Smith"; // Creates a new String object "John Smith"
// The original "John" string remains unchanged in memory
Common String Methods
length()
- Returns the number of characters in the stringcharAt(int index)
- Returns the character at the specified index (0-based)substring(int beginIndex)
- Returns a new string starting from the specified index to the endsubstring(int beginIndex, int endIndex)
- Returns a new string from beginIndex (inclusive) to endIndex (exclusive)indexOf(String str)
- Returns the index of the first occurrence of the specified substringlastIndexOf(String str)
- Returns the index of the last occurrence of the specified substringtoLowerCase()
- Returns a new string with all characters converted to lowercasetoUpperCase()
- Returns a new string with all characters converted to uppercasetrim()
- Returns a new string with leading and trailing whitespace removedreplace(char oldChar, char newChar)
- Returns a new string with all occurrences of oldChar replaced with newCharcontains(CharSequence s)
- Returns true if the string contains the specified sequencestartsWith(String prefix)
- Checks if the string starts with the specified prefixendsWith(String suffix)
- Checks if the string ends with the specified suffixequals(Object obj)
- Compares this string to another objectequalsIgnoreCase(String anotherString)
- Compares strings, ignoring case differences
Example: Using String Methods
String text = "Java Programming";
// Basic information
int length = text.length(); // 16
char firstChar = text.charAt(0); // 'J'
boolean containsJava = text.contains("Java"); // true
// Extracting substrings
String sub1 = text.substring(5); // "Programming"
String sub2 = text.substring(0, 4); // "Java"
// Finding positions
int indexOfP = text.indexOf("P"); // 5
int indexOfr = text.indexOf("r"); // 7
int lastIndexOfr = text.lastIndexOf("r"); // 9
// Transforming
String upper = text.toUpperCase(); // "JAVA PROGRAMMING"
String lower = text.toLowerCase(); // "java programming"
String replaced = text.replace('a', 'A'); // "JAvA ProgrAmming"
String Concatenation
There are multiple ways to concatenate (join) strings in Java:
// Using the + operator
String firstName = "John";
String lastName = "Smith";
String fullName = firstName + " " + lastName; // "John Smith"
// Using concat() method
String greeting = "Hello, ";
String message = greeting.concat(firstName); // "Hello, John"
// When concatenating with non-String values, Java automatically converts them to strings
int age = 30;
String info = "Age: " + age; // "Age: 30"
double price = 19.99;
String priceTag = "Price: $" + price; // "Price: $19.99"
StringBuilder for Efficient Concatenation
When you need to concatenate many strings (especially in a loop), using the +
operator can be inefficient. StringBuilder
provides a more efficient way:
// Inefficient way for many concatenations
String result = "";
for (int i = 0; i < 10; i++) {
result = result + i; // Creates a new String object each time
}
// Efficient way using StringBuilder
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 10; i++) {
builder.append(i); // Modifies the same StringBuilder object
}
String result = builder.toString(); // Convert to String when finished
String Formatting
Java provides powerful string formatting capabilities:
// Using String.format()
String name = "Alice";
int age = 25;
double height = 5.75;
String formatted = String.format("Name: %s, Age: %d, Height: %.2f feet", name, age, height);
// Result: "Name: Alice, Age: 25, Height: 5.75 feet"
// Common format specifiers
// %s - String
// %d - Decimal integer
// %f - Floating point
// %.2f - Floating point with 2 decimal places
// %n - Platform-specific line separator
// You can also use printf for direct output
System.out.printf("Name: %s, Age: %d%n", name, age);
User Input
Gathering User Input in Java
The Scanner
class is the most common way to read user input from the console in Java.
Setting Up Scanner
// Import the Scanner class
import java.util.Scanner;
// Create a Scanner object to read from System.in (keyboard)
Scanner scanner = new Scanner(System.in);
Reading Different Types of Input
// Reading a string (whole line)
System.out.print("Enter your name: ");
String name = scanner.nextLine(); // Reads the entire line
// Reading a word (reads until whitespace)
System.out.print("Enter a word: ");
String word = scanner.next();
// Reading numbers
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // Reads an integer
System.out.print("Enter your height: ");
double height = scanner.nextDouble(); // Reads a double
// Reading a boolean
System.out.print("Are you a student? (true/false): ");
boolean isStudent = scanner.nextBoolean(); // Reads a boolean
Important Considerations
When mixing calls to nextLine()
with other methods like nextInt()
, be aware of this common issue:
// This can cause problems
System.out.print("Enter your age: ");
int age = scanner.nextInt(); // Reads the number but leaves the newline character
System.out.print("Enter your name: ");
String name = scanner.nextLine(); // This immediately reads the leftover newline character!
// The solution: add an extra nextLine() call after nextInt()
System.out.print("Enter your age: ");
int age = scanner.nextInt();
scanner.nextLine(); // Consume the leftover newline
System.out.print("Enter your name: ");
String name = scanner.nextLine(); // Now this works as expected
Handling Input Errors
When reading user input, it's important to handle potential errors. For example, if the user enters text when you're expecting a number:
// Basic error handling with try-catch
Scanner scanner = new Scanner(System.in);
int number = 0;
try {
System.out.print("Enter a number: ");
number = scanner.nextInt();
System.out.println("You entered: " + number);
} catch (Exception e) {
System.out.println("That's not a valid number!");
}
Reading from a File
Scanner can also be used to read from files:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
try {
File file = new File("data.txt");
Scanner fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
System.out.println(line);
}
fileScanner.close();
} catch (FileNotFoundException e) {
System.out.println("File not found!");
}
Closing the Scanner
It's good practice to close the Scanner when you're done with it to free up resources:
scanner.close();
Complete Example: Basic Calculator
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter first number: ");
double num1 = scanner.nextDouble();
System.out.print("Enter an operator (+, -, *, /): ");
scanner.nextLine(); // Consume newline
char operator = scanner.nextLine().charAt(0);
System.out.print("Enter second number: ");
double num2 = scanner.nextDouble();
double result = 0;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
} else {
System.out.println("Error: Division by zero");
scanner.close();
return;
}
break;
default:
System.out.println("Error: Invalid operator");
scanner.close();
return;
}
System.out.println(num1 + " " + operator + " " + num2 + " = " + result);
scanner.close();
}
}
Comments
Code Comments in Java
Comments are used to explain code, make it more readable, and provide additional information that might not be immediately evident from the code itself. They are ignored by the compiler.
Types of Comments in Java
Java supports three types of comments:
1. Single-line Comments
Used for brief explanations. Everything after //
to the end of the line is a comment.
// This is a single-line comment
int count = 10; // Initialize count to 10
2. Multi-line Comments
Used for longer explanations that span multiple lines. Everything between /*
and */
is a comment.
/* This is a multi-line comment
that spans multiple lines
and can provide detailed explanations */
int result = calculateTotal();
3. JavaDoc Comments
Special documentation comments that can be used to generate API documentation. They start with /**
and end with */
.
/**
* Calculates the sum of two integers.
*
* @param a The first integer
* @param b The second integer
* @return The sum of a and b
*/
public int add(int a, int b) {
return a + b;
}
Best Practices for Comments
- Be Clear and Concise: Write comments that clearly explain what the code is doing without being overly verbose.
- Comment Why, Not What: Focus on explaining why something is done a certain way, rather than what the code is doing (which should be clear from the code itself).
- Update Comments: Keep comments up-to-date when you change the code.
- Use JavaDoc for Public APIs: Use JavaDoc comments for classes, methods, and fields that are part of your public API.
- Don't Over-Comment: Too many comments can clutter the code and make it harder to read.
Common JavaDoc Tags
@param
- Describes a method parameter@return
- Describes what a method returns@throws
or@exception
- Describes exceptions that might be thrown@see
- Provides a reference to another class or method@since
- Specifies when this feature was added@deprecated
- Indicates that a method is deprecated and should no longer be used
Using Comments to Temporarily Disable Code
Comments can be used to "comment out" code, temporarily disabling it without deleting it:
// This code is currently disabled
// System.out.println("This won't be executed");
/* Multiple lines of code can be disabled this way
int a = 5;
int b = 10;
System.out.println(a + b);
*/
Example: Well-Commented Code
/**
* A simple Student class to represent student information.
*
* @author Your Name
* @version 1.0
* @since 2023-04-15
*/
public class Student {
// Student's name
private String name;
// Student's ID (unique identifier)
private int id;
// GPA on a 4.0 scale
private double gpa;
/**
* Constructs a new Student with the specified name, ID, and GPA.
*
* @param name The name of the student
* @param id The unique ID of the student
* @param gpa The GPA of the student on a 4.0 scale
*/
public Student(String name, int id, double gpa) {
this.name = name;
this.id = id;
// Ensure GPA is within valid range
if (gpa < 0.0 || gpa > 4.0) {
throw new IllegalArgumentException("GPA must be between 0.0 and 4.0");
}
this.gpa = gpa;
}
/**
* Returns whether the student is on the honor roll.
* A student is on the honor roll if their GPA is 3.5 or higher.
*
* @return true if the student is on the honor roll, false otherwise
*/
public boolean isOnHonorRoll() {
return gpa >= 3.5; // Honor roll threshold is 3.5
}
/* This method was replaced with a more efficient implementation
public String getFullInfo() {
return "Name: " + name + ", ID: " + id + ", GPA: " + gpa;
}
*/
/**
* Returns a string representation of the student.
*
* @return A string containing the student's name, ID, and GPA
*/
@Override
public String toString() {
return String.format("Student[name=%s, id=%d, gpa=%.2f]", name, id, gpa);
}
}
Curated Content
Video Tutorials
Guided Project
Project Overview
In this guided project, you'll apply your knowledge of strings, user input, and comments to create interactive programs:
Secret Strings
This project focuses on string manipulation and involves:
- Encrypting and decrypting messages using string operations
- Working with substring extraction and concatenation
- Using string methods to analyze and modify text
- Implementing proper code documentation with comments
Chess Strings
This project demonstrates practical applications of strings in a chess game context:
- Representing chess positions using string notation
- Parsing user input to make chess moves
- Validating input strings against expected patterns
- Using StringBuilder for efficient string operations
- Adding comprehensive documentation using JavaDoc comments
By completing these projects, you'll gain practical experience with the core concepts of this module and see how they can be applied to solve real problems.
Mastery Task 3 - String Manipulation
Mastery Task Guidelines
Mastery Tasks are opportunities to test your knowledge and understanding through code. When a mastery task is shown in a module, it means that we've covered all the concepts that you need to complete that task. You will want to make sure you finish them in a timely fashion to stay on track and complete the sprint.
Each mastery task must pass 100% of the automated tests and code styling checks. Your code must be your own. If you have any questions, feel free to reach out for support.
AppSettings Update
Go to com.adventure.settings.AppSettings
and update the story to MT3_TestDirections
.
String Interpolation and Manipulation
Strings can be taken apart and put together in order to handle user inputs, provide outputs, format values properly, and so much more. In this assignment, we'll be taking user inputs and breaking them into manageable pieces as well as providing formatted outputs.
Working Classes
We will be working with the following classes:
- GameInputProcessor (
adventure.GameInputProcessor
) - Player (
adventure.player.Player
)
GameInputProcessor
The GameInputProcessor class prompts the user for input and then structures it in such a way that the game can understand what it needs to do next.
You'll first want to gather user inputs in the prompt()
method. Here you'll want to use the Scanner class to gather and return user inputs. Once you have Scanner taking in inputs, you can test it by running the game (run it from the Main class). If the app crashes after entering your name, it's not working right.
Next, you'll need to implement the buildSimpleCommand()
method which will return a Command object that the game can use. buildSimpleCommand()
will split the user input into two parts: the verb and the object.
After you break up the user input, you can construct the Command object by passing it the verb (the first word) and the object (the remaining string, which in the case of this method, will always be blank).
For the buildCommandWithObject()
method, you will want to get the verb the same way as before, but also supply the rest of the string as the object.
Player
With the commands now returning their proper object, we're going to implement one of the commands: move.
In the Player class, you'll find the move()
method. Here you'll want to take the direction that is given and if it's "east", you'll want to increment the currentLocationIndex. If the direction is "west", you'll want to decrement the 'currentLocationIndex'.
Since you can't always move east or west in the game, an extra parameter is provided that lets you know if the value is invalid (isValid). If the value is invalid, you'll need to send the user the following message: "{DIRECTION} is not a valid direction".
Testing
To run the tests for this assignment, run the following:
./gradlew test --tests com.adventure.MT3
or by right-clicking the MT3 file and selecting "Run 'MT3'"
You can check your code styling by running the linter with the following command:
./gradlew checkstyleMain
You can run the game by going to the Main class and clicking on the run icon to the left of the main()
method.