Java design for dimensions and units I created this abstract class:

public abstract class MeasurementType {
  protected String name;
  protected String[] units;

  public MeasurementType() {}

  public MeasurementType(String name) {
    this.name = name;
  }

  protected void setName(String name) {
    this.name = name;
  }

  protected String getName() {
    return name;
  }

  protected void setUnits(String[] values) {
    this.units = values;
  }
}


Then I thought to create to other classes that were its subtypes:

public class Acceleration extends MeasurementType {
  private String name;

  public Acceleration () {
    super();
  }

  public Acceleration(String name) {
    super();
  }
}

public class Density extends MeasurementType {
  private String name;

  public Density() {
    super();
  }

  public Density(String name) {
    super();
  }
}


Plenty to choose from but these were the first two types that cam to my mind, the first question might be what the need for the subtypes are since there isn't anything in those classes that differentiates them apart enough (at least in my implementations) to give them the right to exist as their own entities, but for the sake of the example, lets say they had their own arrays containing units for each distinct type, so density would have kilograms, grams etc.. and acceleration would have mph, kmph etc..

Finally, I have this run class which I quickly made up:

public class run {

  public run() {}

  public static MeasurementType testType() {
    Acceleration a = new Acceleration("meters per second");
    return (MeasurementType) a;
  }

  public static void main(String[] args) {
    MeasurementType mt = testType();
    System.out.println(mt.getClass().toString());
    System.out.println(mt.getClass().getName());

    String type = "acceleration";
    String[] units = new String[8];

    Object mType;
    if(type.equals("acceleration")) {
      mType = new Acceleration();
    } else if(type.equals("density")) {
      mType = new Density();
    } else {
      mType = new Object();
    }

    System.out.println(mType.getName());
  }
}


This is where I encountered the problem that I was thinking about. I was using strings to determine the type that I would instantiate, but the problem is, by default right at the end of the conditional statements I instantiate Object because otherwise the compiler would complain that the mType variable wouldn't have been initialised. I can't create a MeasurementType object since it is an abstract class.

I guess this is more of a design question, but is there a better way of determining the class to instantiate? Please assume that the String type = "acceleration" came from a drop down or somewhere from some user interface, I have just hard coded it in because it isn't really necessary for the question.

Could someone please shed some light on this design fault as I see it please?
Using strings in themselves to determine the MeasurementType isn't the biggest problem, but you really don't need to create classes and subclasses and stuff for this.

Instead, use an enum!

public enum MeasurementType {
    DENSITY, ACCELERATION;
}


In this case you can use this code to grab the MeasurementType:

String type = ...;
MeasurementType mType = MeasurementType.valueOf(type.toLowerCase());


Note however that this will throw an exception if the type is not found. So instead, you might want to consider using a Map&lt;String, MeasurementType&gt; where you add all known MeasurementTypes (preferably in a static initializer block), or you can loop through MeasurementType.values() and scan for the one with the right name.

Also remember that enums can have methods, implement interfaces, override methods, and contain fields.

As I'm not sure what your ultimate goal is, here's an example of what an enum can do:

public enum MeasurementType {
    DENSITY("test"),
    ACCELERATION("test2") {
        @Override
        public int transform(int value) {
            return 0;
        }
    },
    SOMETHING_ELSE("test3")
    ;

    private final String test;

    private MeasurementType(String test) {
        this.test = test;
    }

    public int transform(int value) {
        return value;
    }
}