-2

In one of our Java projects I found the following code for starting a thread:

new WorkerThread(socket).start();

Now according to operator precedence in Java this is wrong! It should be instead:

(new WorkerThread(socket)).start();

Now my question:

Why is it still working? Are there any dangers?

Just for reference, WorkerThread is implemented pretty straightforward:

private class WorkerThread extends Thread
{
    private Socket socket;

    public WorkerThread(Socket socket)
    {
        super();
        this.socket = socket;
    }

    @Override
    public void run()
    {
        try
        {
            /* do stuff... */
        }
        catch (IOException e)
        {
        }
        finally
        {
            socket.close();
        }
    }
}
chrset
  • 581
  • 6
  • 11
  • 2
    Why should be that call wrong according to operator precedence? You create a new object and then you call the start method... – GHajba Apr 20 '16 at 12:47
  • where did you hear that this is wrong? – SomeJavaGuy Apr 20 '16 at 12:48
  • There is nothing wrong with it, it is perfectly valid, according the the Java syntax. – cyroxis Apr 20 '16 at 12:48
  • Am I the only one here who heard about "lexical analysis" in his studies? – chrset Apr 20 '16 at 13:04
  • @chrset nope, but the documentation that you did link in Mena´s answer allows a lot of confusion, especially since you seem to only verify what is written in the third column(`Level`) but do not take note of what is written in the last colum (`Associativity`). All in all, if you invoke a constructor, the `.` followed afterwards doesn´t have a higher precedence. The constructor will return an instance of the object and the follow up method will be invoked on this instance. – SomeJavaGuy Apr 20 '16 at 13:06
  • I found this post that describes it very well: http://stackoverflow.com/a/17587899/1823476. I know it's about JavaScript but I guess the Java grammar is pretty similar in that point. – chrset Apr 20 '16 at 13:25

3 Answers3

1

There aren't any "dangers".

The start method is invoked on the previous object in the chain, which appears to be extending Thread.

This is not about operator precedence but proper parenthesis, which in this case are perfectly fine as is.

You may find other situations where parenthesis are relevant, e.g. when casting and invoking a method to the cast object inline.

Here's a couter-example of parenthesis order relevance when casting:

class A {
    void a(){}
}
class B extends A {
    void b(){}
}

A a = new B();
(B)a.b(); // won't compile
((B)a).b(); // fine
Mena
  • 47,782
  • 11
  • 87
  • 106
  • 1
    @chrset no. It's an instance of `WorkerThread` because you are invoking `new WorkerThread(socket)`, which is an invocation to its constructor thus returning an instance. – Mena Apr 20 '16 at 12:49
  • No because . has a higher precedence as "new". Therefore it first evaluates *WorkerThread(socket).start()* and then *new* – chrset Apr 20 '16 at 12:50
  • @chrset who told you that? – SomeJavaGuy Apr 20 '16 at 12:51
  • Look here: http://introcs.cs.princeton.edu/java/11precedence/. Operator . for accessing object members has the highst precedence – chrset Apr 20 '16 at 12:51
  • 1
    @chrset nope. The invocation is again on the constructor, not on the class. And the article you reference seems to be relevant for mathematical expressions only. – Mena Apr 20 '16 at 12:53
  • @Mena it seems that the table wants to cover up every keyword. But the third column seems to be more important then the first column where the precedence order is defined. Guess that´s somehow where the missinterpretation of precedence came from – SomeJavaGuy Apr 20 '16 at 12:59
  • @KevinEsche you have a sharp eye. Anyway, the linked documentation seems to be mixing up a lot, which as you say, allows some degree of confusion. – Mena Apr 20 '16 at 13:03
1

Operator precedence is not something to ponder over here, as the only operator is the new operator.

So, it creates a new object, and then calls the method start().

dryairship
  • 6,022
  • 4
  • 28
  • 54
1

Well, the website you link to is wrong, or at least incomplete. First of all, the Java Language Specification doesn't explicitly define operator precedence. The operator precedence is defined implicitly by the grammar. The "." operator (although the JLS doesn't call it an operator) also has no single precedence.

For example, the following code is legal and does what you would expect:

class A {
    static class B {
        void f() {
            System.out.println("f()");
        }
    }
}

public class Foo {    
    public static void main(String... args) {
        new A.B().f();
    }
}

The new-expression is paranthesized as follows: (new A.B()).f();. So apparently the dot has both higher and lower precedence than new. The trick is that the dot appears in different rules. In the example, the first dot is generated by the rule ClassOrInterfaceTypeToInstantiate in JLS section 15.9, while the second dot is generated by the rule MethodInvocation in JLS section 15.12.

Hoopje
  • 12,677
  • 8
  • 34
  • 50