简体   繁体   中英

Throw Exception then Call Constructor?

So I'm building a test library that I will mainly use for personal use however I have a question.

With Java, if you have 2 or more constructors in your class, if you wish to call one from another, it must be the first thing you do. This is problematic for me as I have the below setup.

public Constructor(TypeA a, TypeB b, TypeC c) {
    if (c.getData() == null) throw new IllegalArgumentException("");
    this(a, b, c.getOtherData());
}

public Constructor(TypeA a, TypeB b, TypeD d) {
    // stuff happens
}

How can I do this, avoiding the, "Constructor call must be the first statement in a constructor" error?

You cannot do what you want with constructors. Instead use a static factory method like this:

public static TypeThing buildMyThing(TypeA a, TypeB b, TypeC c) {
    if (c.getData() == null) throw new IllegalArgumentException("");
    return new TypeThing(a, b, c.getOtherData());
}

public Constructor(TypeA a, TypeB b, TypeD d) {
    // stuff happens
}

One option (probably bad): Check for getData == null and throw the exception as first thing in c.getOtherData()`. That would be the first method being executed.

Other Option: Have a method like,

helper() {
    if (getData() == null) throw new Exception();
    return getOtherData();
}

and from you constructor, call c.helper() instead of c.getOtherData()

How about creating a static factory method?

public static Constructor newInstance(TypeA a, TypeB b, TypeC c) {
    if (c.getData() == null) throw new IllegalArgumentException("");
    return new Constructor(a, b, c);
}

private Constructor(TypeA a, TypeB b, TypeC c) {
    this(a, b, c.getOtherData());
}

private Constructor(TypeA a, TypeB b, TypeD d) {
    // stuff happens
}

You could have an additional private construtor. Im assuming you've simplified the code a bit too much here. You are saying if something is null then throw - else you something else.

public Constructor(TypeA a, TypeB b, TypeC c) {
   this(a, b, c.getData(), c.getOtherData()); //calls the private ctor
}

public Constructor(TypeA a, TypeB b, TypeD d) {
    // stuff happens  
}

private Constructor(TypeA a, TypeB b, TypeD d1, TypeD d2) {
    // stuff happens  
}

or you could just pass in TypeC

 private Constructor(TypeA a, TypeB b, TypeC) {
    // now do you null check here.
}

Java does cause some pains sometimes! and then this rule is one of them. In specific answer to your question about the compile error - you cant :(

Try moving the exception thrown to the beginning of the second constructor. That will achieve the exact same thing. If there are multiple paths to that constructor, you could make an additional parameter that signals logical path.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM