Why do this() and super() have to be the first statement in a constructor?

前端 未结 21 1931
北荒
北荒 2020-11-21 23:10

Java requires that if you call this() or super() in a constructor, it must be the first statement. Why?

For example:

public class MyClass {
    publi         


        
21条回答
  •  天涯浪人
    2020-11-21 23:32

    Tldr:

    The other answers have tackled the "why" of the question. I'll provide a hack around this limitation:

    The basic idea is to hijack the super statement with your embedded statements. This can be done by disguising your statements as expressions.

    Tsdr:

    Consider we want to do Statement1() to Statement9() before we call super():

    public class Child extends Parent {
        public Child(T1 _1, T2 _2, T3 _3) {
            Statement_1();
            Statement_2();
            Statement_3(); // and etc...
            Statement_9();
            super(_1, _2, _3); // compiler rejects because this is not the first line
        }
    }
    

    The compiler will of course reject our code. So instead, we can do this:

    // This compiles fine:
    
    public class Child extends Parent {
        public Child(T1 _1, T2 _2, T3 _3) {
            super(F(_1), _2, _3);
        }
    
        public static T1 F(T1 _1) {
            Statement_1();
            Statement_2();
            Statement_3(); // and etc...
            Statement_9();
            return _1;
        }
    }
    

    The only limitation is that the parent class must have a constructor which takes in at least one argument so that we can sneak in our statement as an expression.

    Here is a more elaborate example:

    public class Child extends Parent {
        public Child(int i, String s, T1 t1) {
            i = i * 10 - 123;
            if (s.length() > i) {
                s = "This is substr s: " + s.substring(0, 5);
            } else {
                s = "Asdfg";
            }
            t1.Set(i);
            T2 t2 = t1.Get();
            t2.F();
            Object obj = Static_Class.A_Static_Method(i, s, t1);
            super(obj, i, "some argument", s, t1, t2); // compiler rejects because this is not the first line
        }
    }
    

    Reworked into:

    // This compiles fine:
    
    public class Child extends Parent {
        public Child(int i, String s, T1 t1) {
            super(Arg1(i, s, t1), Arg2(i), "some argument", Arg4(i, s), t1, Arg6(i, t1));
        }
    
        private static Object Arg1(int i, String s, T1 t1) {
            i = Arg2(i);
            s = Arg4(s);
            return Static_Class.A_Static_Method(i, s, t1);
        }
    
        private static int Arg2(int i) {
            i = i * 10 - 123;
            return i;
        }
    
        private static String Arg4(int i, String s) {
            i = Arg2(i);
            if (s.length() > i) {
                s = "This is sub s: " + s.substring(0, 5);
            } else {
                s = "Asdfg";
            }
            return s;
        }
    
        private static T2 Arg6(int i, T1 t1) {
            i = Arg2(i);
            t1.Set(i);
            T2 t2 = t1.Get();
            t2.F();
            return t2;
        }
    }
    

    In fact, compilers could have automated this process for us. They'd just chosen not to.

提交回复
热议问题