Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Try / Catch in Constructor - Recommended Practice?

Something I've always been curious of

public class FileDataValidator {  private String[] lineData;  public FileDataValidator(String[] lineData){      this.lineData = lineData;     removeLeadingAndTrailingQuotes();      try     {         validateName();         validateAge();         validateTown();     }     catch(InvalidFormatException e)     {         e.printStackTrace();     }  }  //validation methods below all throwing InvalidFormatException 

Is is not advisable to include the try/catch block within my Constructor? I know I could have the Constructor throw the Exception back to the caller. What do you guys prefer in calling methods like I have done in Constructor? In the calling class would you prefer creating an instance of FileDataValidator and calling the methods there on that instance? Just interested to hear some feedback!

like image 752
deanmau5 Avatar asked May 28 '13 15:05

deanmau5


People also ask

Can you have a try catch in a constructor?

Yes, we can write try catch and finally block in a constructor ant it works properly.

Is it good practice to throw exception in constructor?

The short answer to the question “can a constructor throw an exception in Java” is yes! Of course, properly implementing exceptions in your constructors is essential to getting the best results and optimizing your code.

Can we use try catch in constructor C++?

Try/catch blocks should generally be within a function or method, you have it immediately after the public keyword. If you're throwing an exception from the constructor, you don't catch it in the constructor. Instead you catch it in the code that called the constructor ( main in this case).


1 Answers

In the code you show, the validation problems don't communicate back to the code that is creating this object instance. That's probably not a GOOD THING.

Variation 1:

If you catch the exception inside the method/constructor, be sure to pass something back to the caller. You could put a field isValid that gets set to true if all works. That would look like this:

private boolean isValid = false;  public FileDataValidator(String[] lineData){      this.lineData = lineData;     removeLeadingAndTrailingQuotes();      try     {         validateName();         validateAge();         validateTown();         isValid = true;     }     catch(InvalidFormatException e)     {         isValid = false;     } }  public boolean isValid() {     return isValid; } 

Variation 2:

Or you could let the exception or some other exception propagate to the caller. I have shown it as a non-checked exception but do whatever works according to your exception handling religion:

public FileDataValidator(String[] lineData){      this.lineData = lineData;     removeLeadingAndTrailingQuotes();      try     {         validateName();         validateAge();         validateTown();     }     catch(InvalidFormatException e)     {         throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());     }  } 

Variation 3:

The third method I want to mention has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.

String[] lineData = readLineData(); FileDataValidator onePerson = new FileDataValidator(); try {     onePerson.build(lineData); } catch (InvalidDataException e) {     // What to do it its bad? } 

Here is the class code:

public FileDataValidator() {     // maybe you need some code in here, maybe not }  public void build(String[] lineData){      this.lineData = lineData;     removeLeadingAndTrailingQuotes();      try     {         validateName();         validateAge();         validateTown();     }     catch(InvalidFormatException e)     {         throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());     }  } 

Of course, the build() function could use a isValid() method that you call to see if its right but an exception seems the right way to me for the build function.

Variation 4:

The fourth method I want to mention is what I like best. It has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.

This sort of follows the way JaxB and JaxRS work, which is a similar situation to what you have.

  1. An external source of data - you have a file, they have an incoming message in XML or JSON format.
  2. Code to build the objects - you have your code, they have their libraries of code working according the specifications in the various JSRs.
  3. Validation is not tied to the building of the objects.

The calling code:

String[] lineData = readLineData(); Person onePerson = new Person(); FileDataUtilities util = new FileDataUtilities(); try {     util.build(onePerson, lineData);     util.validate(onePerson); } catch (InvalidDataException e) {     // What to do it its bad? } 

Here is the class code where the data lives:

public class Person {     private Name name;     private Age age;     private Town town; ... lots more stuff here ... } 

And the utility code to build and validate:

public FileDataValidator() {     // maybe you need some code in here, maybe not }  public void build(Person person, String[] lineData){      this.lineData = lineData;     removeLeadingAndTrailingQuotes();     setNameFromData(person);     setAgeFromData(person);     setTownFromData(person); }  public boolean validate(Person person) {      try     {         validateName(person);         validateAge(person);         validateTown(person);         return true;     }     catch(InvalidFormatException e)     {         throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());     }  } 
like image 116
Lee Meador Avatar answered Oct 10 '22 17:10

Lee Meador