Java OOP Temperature Converter I am doing a college exercise and would like to know how to improve the execution of the idea. The idea is to create a program that converts temperature measurements.

Main.java

package app.cnv;

public class Main {
  public static void main(String[] args) {
    Celsius celsius = new Celsius(37);

    System.out.println(celsius.convert(new Fahrenheit()));

    Fahrenheit fahrenheit = new Fahrenheit(98.6);

    try {
      System.out.println(fahrenheit.convert(new Celsius()));
    } catch (AbsoluteZeroException e) {
      System.out.println(e.getMessage());
    }
  }
}


Temperature.java

package app.cnv;

public abstract class Temperature {
  public abstract double convert(Temperature to) throws AbsoluteZeroException;
}


Celsius.java

package app.cnv;

public class Celsius extends Temperature {
  double celsius;

  Celsius() {
  }

  Celsius(double celsius) {
    this.celsius = celsius;
  }

  @Override
  public double convert(Temperature to) {
    if (to instanceof Fahrenheit) {
      return (celsius * 9) / 5 + 32;
    }
    return celsius;
  }
}


Fahrenheit.java

package app.cnv;

public class Fahrenheit extends Temperature {
  double fahrenheit;

  Fahrenheit() {
  }

  Fahrenheit(double fahrenheit) {
    this.fahrenheit = fahrenheit;
  }

  @Override
  public double convert(Temperature to) throws AbsoluteZeroException {
    if (to instanceof Celsius) {
      if (fahrenheit &lt; -459.67) {
        throw new AbsoluteZeroException("The temperature cannot be less than absolute zero.");
      } else {
        return ((fahrenheit - 32) * 5) / 9;
      }
    }
    return fahrenheit;
  }
}


AbsoluteZeroException.java

package app.cnv;

public class AbsoluteZeroException extends Exception {
  public AbsoluteZeroException(String err) {
    super(err);
  }
}
What if I add a class Kelvin without modifying the other classes? When I convert Celsius to Kelvin then, your code says that 20 °C = 20 K, which is simply wrong.

Your whole approach is doomed to fail. What you should do instead is to define one reference temperature scale. I would take Kelvin for that. Then, for every other temperature scale, have methods fromKelvin and toKelvin. That's all. This approach is well-known from constructing compilers, which has the same problem of several similar source languages and several different target machines.

For converting between arbitrary temperature scales you can have a helper method in the Temperature class like this:

public static Temperature convert(Temperature from, TemperatureScale to) {
    double kelvin = from.toKelvin();
    return to.fromKelvin(kelvin);
}


You can see that there are two completely different classes involved:


A temperature scale, like Kelvin or Fahrenheit
A specific temperature, consisting of a temperature scale and a value, like 293 Kelvin




Regarding the exception class: There is no good reason to give it a String parameter. The name of the class is already expressive enough. Therefore you should remove that parameter and just throw new AbsoluteZeroException(). You should probably rename it to BelowAbsoluteZeroException. Or you should just take the predefined IllegalArgumentException and be fine. In many cases you don't need to invent your own exception classes.