Simple object oriented console calculator I'd like to learn OOP. Could someone check my code and tell me how to improve it?  

package com.company;

import java.util.InputMismatchException;
import java.util.Scanner;

public class CalculatorApp {
    private static Scanner scanner = new Scanner(System.in);
    public static void main(String[] args) {
        System.out.println("Write two numbers and +, -, * or / sign");
        char operator = 0;
        double firstNum = 0;
        double secondNum = 0;
        try {
            firstNum = scanner.nextDouble();
            secondNum = scanner.nextDouble();
            operator = scanner.next().charAt(0);
        } catch (InputMismatchException ime) {
            System.out.println("invalid input");
        } finally {
            if (operator != '+' &amp; operator != '-' &amp; operator != '*' &amp; operator != '/') {
                throw new InputMismatchException();
            }
            Calculator calculator = new Calculator(firstNum, secondNum,    operator);
            System.out.println(calculator.makeCalculation());
        }
    }
}


Calculator class:

package com.company;

import java.util.HashMap;
import java.util.Map;

public class Calculator {
    private char operation;
    private double operand1;
    private double operand2;
    private Map&lt;Character, Operation&gt; operationMap = new HashMap&lt;&gt;();

    public Calculator(double operand1, double operand2, char operation) {
        this.operand1 = operand1;
        this.operand2 = operand2;
        this.operation = operation;

        operationMap.put('+', new Addition());
        operationMap.put('-', new Subtraction());
        operationMap.put('*', new Multiplication());
        operationMap.put('/', new Division());
    }

    public double makeCalculation() {
        Operation operationMapValue = null;
        if (operationMap.containsKey(operation)) {
            operationMapValue = operationMap.get(operation);
            System.out.println(operationMap.get(operation));
        } else {
            System.out.println("Invalid sign");
        }
        return operationMapValue.calculateResult(operand1, operand2);
    }
}


Operation interface:

package com.company;

public interface Operation {
    double calculateResult(double left, double right);
}


One of implementing classes:

package com.company;

public class Addition implements Operation {
    @Override
    public double calculateResult(double left, double right) {
        return left + right;
    }
}


And Tests:

package com.company;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    Calculator calc = new Calculator(6.0, 2.0, '+');

    @Test
    void addsTwoNumbers() {
        assertEquals(8.0, calc.makeCalculation());
    }

    Calculator calc2 = new Calculator(6.0, 2.0, '-');
    @Test
    void subtractsTwoNumbers() {
        assertEquals(4.0, calc2.makeCalculation());
    }

    Calculator calc3 = new Calculator(6.0, 2.0, '*');
    @Test
    void multipliesTwoNumbers() {
        assertEquals(12.0, calc3.makeCalculation());
    }

    Calculator calc4 = new Calculator(6.0, 2.0, '/');
    @Test
    void dividesTwoNumbers() {
        assertEquals(3.0, calc4.makeCalculation());
    }
}
Exception handling

try {
    ...          
} catch (InputMismatchException ime) {
     System.out.println("invalid input");
} finally {
     if (operator != '+' &amp; operator != '-' &amp; operator != '*' &amp; operator != '/') {
         throw new InputMismatchException();
     }
     Calculator calculator = new Calculator(firstNum, secondNum,    operator);
     ...
}


That's pretty weird.

It makes no sense to continue the computation if the Scanner throws. What is the point of having a finally block that throws the same exception? I would rather let the exception pass through instead of catching and rethrowing (the original exception is likely to contain a more meaningful message, too).

Variable scope

Try and use the narrowest possible scope. For instance, here:

Calculator calc = new Calculator(6.0, 2.0, '+');

@Test
void addsTwoNumbers() {
     assertEquals(8.0, calc.makeCalculation());
}


there's no point in making calc a field. It can (and should) be just a local variable in the addsTwoNumbers() method. The same is true for other calc's and test methods.

Class design

I don't think that the Calculator is a good name for your class. I would expect a calculator to be able to be instantiated once and then evaluate results of different expression. Something like this:

Calculator calculator = new Calculator();
double sum = calculator.evaluateExpression(x, y, '+');
double difference = caclulator.evaluateExpression(x, y, '-');


I'd change it this way or rename this class to Expression.

Object reuse

Creating four new objects for each operation per each expression evaluation can be costly and is unreasonable because the operation are stateless.

You can use a static factory to reuse the same Operation objects in different expressions.