views:

71

answers:

2

The recommended way to use the EventActionDispatcher is as follows (per the API docs @ http://struts.apache.org/1.2.9/api/org/apache/struts/actions/EventActionDispatcher.html )

   public class MyCustomAction extends Action {

       protected ActionDispatcher dispatcher = new EventActionDispatcher(this);

       public ActionForward execute(ActionMapping mapping,
                                    ActionForm form,
                                    HttpServletRequest request,
                                    HttpServletResponse response)
                           throws Exception {
           return dispatcher.execute(mapping, form, request, response);
       }
   }

Does doing this publish the reference to "this" before the constructor exits? What are the rules governing field assignments outside of methods.

Thanks in advance.

Sincerely, LES

+1  A: 

In this case (I hope) this does not get published. It's still only reachable through the MyCustomAction instance.

In Java (I believe C# does the opposite), instance field initialisation and instance initialisers are called directly before the (implicit or explicit) call to the super constructor. Therefore you can use this in field initialisation, although your object may not have finished construction.

Publishing this so it it reachable from outside the object during construction is generally a bad idea.

Tom Hawtin - tackline
the order is the parent constructor, instance variables, constructor. It is not safe to use "this" in threads before the constructor has returned.
TofuBeer
The constructor calls the super constructor, so that can't technically be correct. Although the first thing it does is to call the super. There is nothing particularly magical about returning from the constructor to make it thread safe (except for finals).
Tom Hawtin - tackline
+2  A: 

That took 3 people a week to track down once... "this" can be null if the EventActionDispatcher starts a thread or does anything with a thread that causes the "this" to be used.

NEVER pass "this" before the constructor has completed or you run the risk of "this" being null in the case of threading.

What I do is add an "init()" method to my classes that need to do things like that and call it after I create the object.

There are also other subtleties, such as this example:

public abstract class Foo
{
    protected Foo()
    {
        car();
    }

    public abstract void car();
}

public class Bar 
    extends Foo
{
    private final String value;

    public Bar(final String str)
    {
        value = str;
    }

    public void car()
    {
        // this line will crash because value is null
        System.out.println(value.charAt(0));
    }
}

public class Main
{
    public static void main(final String[] argv)
    {
        final Foo foo;

        foo = new Bar("Hello");
    }
}

The safest thing to do is:

  • never use "this" before the constructor has returned
  • never call any of the classes own non-static methods from a constructor unless the class is final.

You can can call final methods, but you have to be sure that they do not call overrideable methods... and that can mean things break down the road... so safer not to do it.

TofuBeer
I suspected this was the case. However, how else could you initialize the dispatcher? Perhaps double-checked lazy initialization in the action's execute method? That could be a bit overkill.This field (dispatcher) is init'd this way all over the code base ... it's a wonder it works!!!
LES2
TofuBeer
this can never be null! There is not much that is magical about leaving the constructor (except for finals), so your rule is way too simplistic.
Tom Hawtin - tackline
As I said, it took 3 people a week to figure out why "this" was null - so there is at least one VM that it can be null.
TofuBeer
@Tom please prove the absence of God. If you can do that then you can prove that this cannot be null. It is possible to prove that something does happen - it is not possible to prove that it will never happen.
TofuBeer
and not to belabor the point :-) I cannot find anything the the language spec or the VM spec that say that "this" cannot be null before the constructor completes. If you know of something that states it *must* not be null please let me know.
TofuBeer