简体   繁体   English

在java构造函数中传递“this”

[英]Passing “this” in java constructor

Look into the following code: 查看以下代码:

public class ClassA {
    private boolean ClassAattr = false;

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

public class ClassAHandler extends GeneralHandler {
    ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
    }
}

I need to access ClassAattr on some ClassAHandler methods, among other attributes. 我需要在一些ClassAHandler方法和其他属性中访问ClassAattr Is there a way to do so without passing the origin class in the handler constructor. 有没有办法在没有在处理程序构造函数中传递原始类的情况下这样做。 I don't really like how this solution "looks". 我真的不喜欢这个解决方案“看起来”。

Passing this to another method/object from inside the constructor can be rather dangerous. 通过this从构造内部另一种方法/对象可以是相当危险的。 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. 例如,如果您的类具有final (非static )字段,那么您通常可以依赖于它被设置为值并且永远不会更改。

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). 作为替代方案,您可以延迟构造ClassAHandler对象,直到它首次需要为止(例如,通过在该属性的getter中进行延迟初始化)。

Create a registerHandler(ClassA handler) method. 创建registerHandler(ClassA处理程序)方法。

There is no way to create a handler for something the handler doesn't know about. 没有办法为处理程序不知道的东西创建处理程序。

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 . 如果传递this ,子类将需要使用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. 另一个选择是ClassA传递ClassAHandler在构造函数中需要的所有信息。 If the handler requires the value of ClassAttr , pass it in the constructor. 如果处理程序需要ClassAttr的值, ClassAttr在构造函数中传递它。

    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. 第三种选择是稍微改变设计并将boolean放在处理程序中。 Then ClassA accesses the value of the child with handler.handlerAttr . 然后ClassA访问与孩子的价值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 . 这对于demeter定律更好。

public class ClassAHandler extends GeneralHandler {     
   boolean handlerAttr;

   public ClassAHandler() {       
   }
}

This page has a very good explanation of why letting the "this" reference escape is a bad idea: 这个页面有一个非常好的解释,为什么让“this”引用转义是一个坏主意:

http://www.ibm.com/developerworks/java/library/j-jtp0618.html#2 http://www.ibm.com/developerworks/java/library/j-jtp0618.html#2

Check the "Don't publish the "this" reference during construction" section 检查“不要发布”这个“施工期间的参考”部分

public class ClassA {
    private boolean ClassAattr = false;
        public ClassA() {    
        ClassAHandler handler = new ClassAHandler(this);
        classAttr = true;
    }
}

public class ClassAHandler extends GeneralHandler {
    ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
        System.out.println(ca.classAttr);
    }
}

So I have added the statement classAttr = true; 所以我添加了语句classAttr = true;

The System.out.println statement will print false . System.out.println语句将打印false This is because the construction of ClassA was not complete at that point. 这是因为那时ClassA的构建还不完整。

So my suggestion is to add another method in classA which will create the ClassAHandler and then the classAHandler will receive fully constructed ClassA object 所以我的建议是在classA添加另一个方法,它将创建ClassAHandler ,然后classAHandler将接收完全构造的ClassA对象

So that the code will look like. 所以代码看起来像。

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    

        classAttr = true;
    }

    public init() {
        ClassAHandler handler = new ClassAHandler(this);
    }
}

So that the code sequence will be new ClassA().init() and will work perfectly 这样代码序列将是new ClassA().init()并且将完美地工作

If I understand correctly, you need the handler to have a reference to ClassA , but you don't want to set this up from within the constructor of ClassA ? 如果我理解正确,你需要处理程序来引用ClassA ,但是你不想在ClassA的构造函数中设置它? If that is the case, then you could separate construction from "wiring up" using a factory pattern, which will prevent your ClassA from needing to know about the ClassAHandler class. 如果是这种情况,那么您可以使用工厂模式将构造与“连接”分开,这将阻止您的ClassA需要了解ClassAHandler类。 Kind of like this: 有点像这样:

public class ClassA {

    private boolean ClassAattr = false;

    public ClassA() {
    }

}


public class ClassAHandler {

    private ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
    }

}


public HandlerFactory {

    public ClassAHandler createClassAHandler(ClassA classa) {
        ClassAHandler handler = new ClassAHandler(classa);
        return handler;
    }

}

Write a getter method for ClassAattr, as 为ClassAattr写一个getter方法,如

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

So that you can get access it as ca.isClassAattr(); 这样你就可以像ca.isClassAattr()那样访问它;

You may make ClassAHandler an inner class of ClassA. 您可以将ClassAHandler作为ClassA的内部类。 It would have access to the members of ClassA. 它可以访问ClassA的成员。

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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