Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor handling exception and using this keyword Java

I have two constructors for my class, one that takes File object and the other takes a String object, and I want to use the this keyword. The function with the implementation is the one with File as parameter, and the one with String will call this. Now I want to check for exception in the constructor that takes String but I get error, that this should be the first line. How can I check for errors then call this.

Here is my code:

public Test (String filename) {
    if (filename == null)
        throw new NullPointerException("The String you entered is null.");
    if (filename.isEmpty())
        throw new IllegalArgumentException("The String you entered is empty.");

    this(new File(filename)); // error
}

public Test (File f) {
    /* implementation here */
}

This is the exact error: Constructor call must be the first statement in a constructor

like image 589
hakuna matata Avatar asked Nov 03 '22 23:11

hakuna matata


1 Answers

Unfortunately, this is impossible in Java thanks to their arbitrary restrictions. You have two main possibilities.

The more idiomatic Java technique is to wrap everything in a factory function so you can catch the exception. Factory functions are also useful because they let you create objects polymorphically, and help hide the details of what object is actually created.

public static Test create(String filename){
    if (filename == null)
        throw new NullPointerException("The String you entered is null.");
    if (filename.isEmpty())
        throw new IllegalArgumentException("The String you entered is empty.");
    return new Test(filename);
}

private Test (String filename) {
    this(new File(filename)); 
}

public Test (File f) {
    /* implementation here */
}

The other option is to write the constructor in bytecode, where there are no such restrictions present. Unfortunately, bytecode is less readable and maintainable, so you'll probably want to minimize the amount of bytecode in a primarily Java app. You might also be able do this in a non Java language like AspectJ.

Edit: If you're not actually trying to catch the exceptions, then there's a third possibility. You can insert arbitrary code before the super constructor call by creating a separate function which performs the checks and then passing it as a dummy argument to the super constructor call. Since arguments are evaluated first, your code will run first, but this is a bit of a hack.

public Test (String filename) {
    this(doChecks(filename), new File(filename));
}

private static Void doChecks(String filename){
    if (filename == null)
        throw new NullPointerException("The String you entered is null.");
    if (filename.isEmpty())
        throw new IllegalArgumentException("The String you entered is empty.");
    return null;
}

public Test (Void dummy, File f) {
    this(f);
}

public Test (File f) {
    /* implementation here */
}
like image 128
Antimony Avatar answered Nov 14 '22 23:11

Antimony