Skip to content

Commit e1d46b9

Browse files
authored
1861 exception handling (exercism#2022)
* Adding CalculatorConundrum exercise for exception-handling concept exercise. * moved into reference/java * Made changes iter 1. * shifted calculation from constructor to CalculatorConundrum.calculate() * 2nd iter changes * removed cause from some of thrown exceptions, updated readme, added config.json * added newline * Modified instructions.md, Added missing files * Modifying docs, config.json, renamed introduction.md
1 parent 5177d35 commit e1d46b9

File tree

12 files changed

+442
-0
lines changed

12 files changed

+442
-0
lines changed

config.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,20 @@
8585
],
8686
"status": "active"
8787
},
88+
{
89+
"slug": "calculator-conundrum",
90+
"name": "Calculator Conundrum",
91+
"uuid": "9e62feec-c2c3-4fd6-94f5-0574cc65447d",
92+
"concepts": [
93+
"exception-handling"
94+
],
95+
"prerequisites": [
96+
"conditionals",
97+
"switch-case",
98+
"basics"
99+
],
100+
"status": "wip"
101+
},
88102
{
89103
"slug": "squeaky-clean",
90104
"name": "Squeaky Clean",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Hints
2+
3+
## 1. Implement the method calculate to support a few basic operations
4+
5+
* Use a `switch-case` block to match different operations and implement them using the `SimpleOperation` class.
6+
7+
## 2. Handle illegal operations
8+
9+
10+
* Check for `null` operations before the switch.
11+
* Add a case to the switch for the empty String.
12+
* Use a default for anything else at the end of the switch.
13+
* Throw an `IllegalOpertionException` with appropriate messages in different cases.
14+
15+
## 3. Handle the thrown DivideByZero exceptions
16+
17+
* Use a `try-catch` block to catch `ArithmeticException`
18+
* Pass both the `message` and the `ArithmeticException` as the `cause` parameter when throwing the exception.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Instructions
2+
3+
In this exercise you will be building error handling for a simple integer calculator.
4+
To make matters simple, methods for calculating addition, multiplication and division are provided.
5+
6+
The goal is to have a working calculator that returns a String with the following pattern: `16 + 51 = 67`, when provided with arguments `16`, `51` and `+`.
7+
8+
```java
9+
CalculatorConundrum obj = new CalculatorConundrum();
10+
11+
obj.calculate(16, 51, "+"); // => returns "16 + 51 = 67"
12+
13+
obj.calculate(32, 6, "*"); // => returns "32 * 6 = 192"
14+
15+
obj.calculate(512, 4, "/"); // => returns "512 / 4 = 128"
16+
```
17+
18+
## 1. Implement the method calculate to support a few basic operations
19+
20+
The main method for implementation in this task will be the `CalculatorConundrum.calculate()` method.
21+
It takes three arguments.
22+
The first two arguments are integer numbers on which an operation is going to operate.
23+
The third argument is of type String and for this exercise it is necessary to implement the following operations:
24+
25+
- addition using the `+` String
26+
- multiplication using the `*` String
27+
- division using the `/` String
28+
29+
## 2. Handle illegal operations
30+
31+
All the following cases need to throw an `IllegalOperationException`:
32+
33+
* when the `operation` argument is `null`, with the String `Operation cannot be null` as the`message` parameter
34+
* when the `operation` is the empty String, with the String `Operation cannot be empty` as the `message` parameter
35+
* when the `operation` argument is anything other than `+`, `*`, or `/`, with the String `{invalidOperation} operation does not exist` as the `message` parameter
36+
37+
## 3. Handle the thrown DivideByZero exceptions
38+
39+
Dividing by zero throws an `ArithmeticException` which the calculator needs to catch and then throw an `IllegalOperationException` with the message `Divide by zero operation illegal` and the `ArithmeticException` as its cause.
40+
This should be handled using a `try-catch` block.
41+
Any other exception should not be handled by the `CalulatorConundrum.calculate()` method.
42+
43+
```java
44+
CalculatorConundrum.calculate(512, 0, "/"); // => throws IllegalOperationException with message "Division by zero is not allowed."
45+
```
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Exception Handling in Java
2+
3+
Exception Handling in Java is one of the powerful mechanism to handle errors so that the normal flow of the application can be maintained.
4+
Good exception handling can re-route the program to give the user still a positive experience.
5+
6+
## Why use Exception Handling with an example
7+
8+
```java
9+
public static List<Player> getPlayers() throws IOException {
10+
Path path = Paths.get("players.dat");
11+
List<String> players = Files.readAllLines(path);
12+
13+
return players.stream()
14+
.map(Player::new)
15+
.collect(Collectors.toList());
16+
}
17+
```
18+
19+
This code chooses not to handle the IOException, passing it up the call stack instead.
20+
In an idealized environment, the code works fine.
21+
22+
But what might happen in production if players.dat is missing?
23+
24+
```log
25+
Exception in thread "main" java.nio.file.NoSuchFileException: players.dat <-- players.dat file doesn't exist
26+
at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
27+
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
28+
// ... more stack trace
29+
at java.nio.file.Files.readAllLines(Unknown Source)
30+
at java.nio.file.Files.readAllLines(Unknown Source)
31+
at Exceptions.getPlayers(Exceptions.java:12) <-- Exception arises in getPlayers() method, on line 12
32+
at Exceptions.main(Exceptions.java:19) <-- getPlayers() is called by main(), on line 19
33+
```
34+
35+
We must handle these conditions because they affect the flow of the application negatively and form exceptions.
36+
37+
## Types of Java Exceptions
38+
39+
There are mainly two types of exceptions: checked and unchecked. An error is considered as the unchecked exception. However, according to Oracle, there are three types of exceptions namely:
40+
41+
1. Checked Exception
42+
2. Unchecked Exception
43+
3. Error
44+
45+
### 1. Checked Exception
46+
The classes that directly inherit the Throwable class except RuntimeException and Error are known as checked exceptions.
47+
For example, IOException, SQLException, etc. Checked exceptions are checked at compile-time.
48+
49+
### 2. Unchecked Exception
50+
The classes that inherit the RuntimeException are known as unchecked exceptions.
51+
For example, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, etc.
52+
Unchecked exceptions are not checked at compile-time, but they are checked at runtime.
53+
54+
### 3. Error
55+
Error is irrecoverable.
56+
Some example of errors are OutOfMemoryError, VirtualMachineError, AssertionError etc.
57+
58+
## Handling Exceptions
59+
60+
### Try-Catch block
61+
62+
The `try` statement allows you to define a block of code to be tested for errors while it is being executed.
63+
64+
The `catch` statement allows you to define a block of code to be executed, if an error occurs in the try block.
65+
66+
For example:
67+
```java
68+
public int getPlayerScore(String playerFile) {
69+
try {
70+
Scanner contents = new Scanner(new File(playerFile));
71+
return Integer.parseInt(contents.nextLine());
72+
} catch (FileNotFoundException noFile) {
73+
throw new IllegalArgumentException("File not found", noFile);
74+
}
75+
}
76+
```
77+
78+
### The Throw/Throws keyword
79+
80+
If a method does not handle a checked exception, the method must declare it using the `throws` keyword.
81+
The `throws` keyword appears at the end of a method's signature.
82+
83+
You can throw an exception, either a newly instantiated one or an exception that you just caught, by using the `throw` keyword.
84+
85+
#### Example
86+
```java
87+
import java.io.*;
88+
public class className {
89+
90+
public void deposit(double amount) throws RemoteException {
91+
// Method implementation
92+
throw new RemoteException();
93+
}
94+
// Remainder of class definition
95+
}
96+
```
97+
98+
### Finally
99+
100+
The `finally` statement (optional) lets you execute code, after `try...catch`, **regardless of the result**.
101+
102+
#### Example
103+
104+
```java
105+
public class Main {
106+
public static void main(String[] args) {
107+
try {
108+
int[] myNumbers = {1, 2, 3};
109+
System.out.println(myNumbers[10]);
110+
} catch (Exception e) {
111+
System.out.println("Something went wrong.");
112+
} finally {
113+
System.out.println("The 'try catch' is finished.");
114+
}
115+
}
116+
}
117+
```
118+
119+
The output will be:
120+
121+
```
122+
Something went wrong.
123+
The 'try catch' is finished.
124+
```
125+
126+
## User-Defined Exceptions
127+
128+
You can create your own exceptions in Java.
129+
Keep the following points in mind when writing your own exception classes −
130+
131+
* All exceptions must be a child of Throwable.
132+
133+
* If you want to write a checked exception that is automatically enforced by the Handle or Declare Rule, you need to extend the Exception class.
134+
135+
* If you want to write a runtime exception, you need to extend the RuntimeException class.
136+
137+
We can define our own Exception class as below:
138+
139+
```java
140+
class MyException extends Exception {
141+
}
142+
```
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"blurb": "Learn about exception-handling by making a simple calculator.",
3+
"authors": [
4+
"rv02",
5+
"jmrunkle"
6+
],
7+
"files": {
8+
"solution": [
9+
"src/main/java/CalculatorConundrum.java"
10+
],
11+
"test": [
12+
"src/test/java/CalculatorConundrumTest.java"
13+
],
14+
"exemplar": [
15+
".meta/src/reference/java/CalculatorConundrum.java"
16+
],
17+
"editor": [
18+
"src/main/java/IllegalOperationException.java",
19+
"src/main/java/SimpleOperation.java"
20+
]
21+
},
22+
"forked_from": [
23+
"csharp/calculator-conundrum"
24+
]
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Design
2+
3+
## Learning Objectives
4+
5+
* Know the concept of exception handling in java
6+
* Know how to implement and handle exception in different ways
7+
8+
## Out of scope
9+
10+
* finally
11+
12+
## Concepts
13+
14+
* exception-handling
15+
* try-catch
16+
* throw and throws keyword
17+
* user-defined exceptions
18+
19+
## Prerequisites
20+
21+
* `basics`: know how to define methods.
22+
* `conditionals`: know how to do conditional logic.
23+
* `switch-case`: know how to work with a switch-case conditionals.
24+
25+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
public class CalculatorConundrum {
2+
3+
public String calculate(int operand1, int operand2, String operation) {
4+
int result;
5+
if (operation == null) {
6+
throw new IllegalOperationException("Operation cannot be null");
7+
}
8+
switch (operation) {
9+
case "+":
10+
result = SimpleOperation.addition(operand1, operand2);
11+
break;
12+
case "*":
13+
result = SimpleOperation.multiplication(operand1, operand2);
14+
break;
15+
case "/":
16+
try {
17+
result = SimpleOperation.division(operand1, operand2);
18+
} catch (ArithmeticException e) {
19+
throw new IllegalOperationException("Divide by zero operation illegal", e);
20+
}
21+
break;
22+
case "":
23+
throw new IllegalOperationException("Operation cannot be empty");
24+
default:
25+
throw new IllegalOperationException(String.format("%s operation does not exist", operation));
26+
}
27+
return String.format("%d %s %d = %s", operand1, operation, operand2, result);
28+
}
29+
30+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apply plugin: "java"
2+
apply plugin: "eclipse"
3+
apply plugin: "idea"
4+
5+
// set default encoding to UTF-8
6+
compileJava.options.encoding = "UTF-8"
7+
compileTestJava.options.encoding = "UTF-8"
8+
9+
repositories {
10+
mavenCentral()
11+
}
12+
13+
dependencies {
14+
testImplementation "junit:junit:4.13"
15+
testImplementation "org.assertj:assertj-core:3.15.0"
16+
}
17+
18+
test {
19+
testLogging {
20+
exceptionFormat = 'short'
21+
showStandardStreams = true
22+
events = ["passed", "failed", "skipped"]
23+
}
24+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class CalculatorConundrum {
2+
3+
public String calculate(int operand1, int operand2, String operation) {
4+
throw new UnsupportedOperationException("Please implement the CalculatorConundrum.calculate() method");
5+
}
6+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class IllegalOperationException extends RuntimeException {
2+
3+
public IllegalOperationException(String errorMessage) {
4+
super(errorMessage);
5+
}
6+
7+
public IllegalOperationException(String errorMessage, Throwable cause) {
8+
super(errorMessage, cause);
9+
}
10+
}
11+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class SimpleOperation {
2+
public static int division(int operand1, int operand2)
3+
{
4+
return operand1 / operand2;
5+
}
6+
7+
public static int multiplication(int operand1, int operand2)
8+
{
9+
return operand1 * operand2;
10+
}
11+
12+
public static int addition(int operand1, int operand2)
13+
{
14+
return operand1 + operand2;
15+
}
16+
}
17+

0 commit comments

Comments
 (0)