Passing “this” in java constructor

后端 未结 9 687
梦毁少年i
梦毁少年i 2020-11-30 11:39

Look into the following code:

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    
        ClassAHandler handler = new Cl         


        
相关标签:
9条回答
  • 2020-11-30 11:39

    Passing this to another method/object from inside the constructor can be rather dangerous. Many guarantees that objects usually fulfill are not necessarily true, when they are looked at from inside the constructor.

    For example if your class has a final (non-static) field, then you can usually depend on it being set to a value and never changing.

    When the object you look at is currently executing its constructor, then that guarantee no longer holds true.

    As an alternative you could delay the construction of the ClassAHandler object until it is first needed (for example by doing lazy initialization in the getter of that property).

    0 讨论(0)
  • 2020-11-30 11:40

    You may make ClassAHandler an inner class of ClassA. It would have access to the members of ClassA.

    0 讨论(0)
  • 2020-11-30 11:46

    You could use inner classes, there is then a implicit parent-child relationship between the two instances. (But I don't know if it's really better).

    public class ClassA {
        private boolean ClassAattr = false;
    
        public class ClassAHandler extends GeneralHandler {
    
           public ClassAHandler() {
               // can access ClassAattr
           }
        }
    
        public ClassA() {    
            ClassAHandler handler = new ClassAHandler();
        }
    }
    

    If you pass this, the subclass will need to access the parent value with parent.classAattr. We can wonder whether it's correct according to the law of demeter.

    Another option then would be that ClassA pass all the information that ClassAHandler requires in the constructor. If the handler requires the value of ClassAttr, pass it in the constructor.

        public ClassA() {    
            ClassAHandler handler = new ClassAHandler( classAattr );
        }
    

    But the parameter is passed by value so I don't know if it works for you.

    A third option would be to change the design a bit and have the boolean be in the handler. Then ClassA accesses the value of the child with handler.handlerAttr. The child knows nothing about the parent, but the parent can access as much information in the child has he wants. This is better regarding the law of demeter.

    public class ClassAHandler extends GeneralHandler {     
       boolean handlerAttr;
    
       public ClassAHandler() {       
       }
    }
    
    0 讨论(0)
  • 2020-11-30 11:46

    there is nothing wrong with the code you pasted, however you can use a non static inner class to make things (arguably) cleaner:

    public class ClassA {
        private boolean ClassAattr = false;
    
        public ClassA() {    
            ClassAHandler handler = new ClassAHandler();
        }
    
        class ClassAHandler extends GeneralHandler {
    
            // magically sees the instantiating ClassA members and methods
        }
    }
    
    0 讨论(0)
  • 2020-11-30 11:50

    Create a registerHandler(ClassA handler) method.

    There is no way to create a handler for something the handler doesn't know about.

    0 讨论(0)
  • 2020-11-30 11:50

    Write a getter method for ClassAattr, as

                public boolean isClassAattr(){
                     return this.ClassAattr;
                }
    

    So that you can get access it as ca.isClassAattr();

    0 讨论(0)
提交回复
热议问题