【问题标题】:Starting a thread in Java and operator precedence在 Java 中启动线程和运算符优先级
【发布时间】:2016-04-20 12:45:54
【问题描述】:

在我们的一个 Java 项目中,我发现了以下用于启动线程的代码:

new WorkerThread(socket).start();

现在根据 Java 中的operator precedence 这是错误的!应该是:

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

现在我的问题:

为什么它仍然有效?有什么危险吗?

仅供参考,WorkerThread 的实现非常简单:

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();
        }
    }
}

【问题讨论】:

  • 为什么根据运算符优先级调用错误?您创建一个新对象,然后调用 start 方法...
  • 你从哪里听说这是错误的?
  • 没有什么问题,完全有效,符合Java语法。
  • 我是这里唯一一个在他的研究中听说过“词法分析”的人吗?
  • @chrset 不,但是您在 Mena 的答案中链接的文档会引起很多混乱,尤其是因为您似乎只验证了第三列中写的内容(Level)但是不要记下最后一列 (Associativity) 中写的内容。总而言之,如果您调用构造函数,则后面的 . 没有更高的优先级。构造函数将返回对象的一个​​实例,并在此实例上调用后续方法。

标签: java multithreading


【解决方案1】:

嗯,您链接到的网站是错误的,或者至少是不完整的。首先,Java 语言规范没有明确定义运算符优先级。运算符优先级由语法隐式定义。 “.”运算符(尽管 JLS 不称其为运算符)也没有单一优先级。

例如,下面的代码是合法的,并且符合你的预期:

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

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

new-表达式的括号如下:(new A.B()).f();。显然,点的优先级高于new。诀窍是点出现在不同的规则中。在示例中,第一个点由JLS section 15.9 中的规则ClassOrInterfaceTypeToInstantiate 生成,而第二个点由JLS section 15.12 中的规则MethodInvocation 生成。

【讨论】:

    【解决方案2】:

    这里不需要考虑运算符优先级,因为唯一的运算符是new 运算符。

    所以,它创建一个新对象,然后调用方法start()

    【讨论】:

      【解决方案3】:

      没有任何“危险”。

      在链中的前一个对象上调用start 方法,该对象似乎扩展了Thread

      这与运算符优先级无关,而是关于正确的括号,在这种情况下,它完全没问题。

      您可能会发现括号相关的其他情况,例如内联转换和调用转换对象的方法时。

      这是一个在强制转换时括号顺序相关性的例子:

      class A {
          void a(){}
      }
      class B extends A {
          void b(){}
      }
      
      A a = new B();
      (B)a.b(); // won't compile
      ((B)a).b(); // fine
      

      【讨论】:

      • @chrset 没有。这是WorkerThread 的一个实例,因为您正在调用new WorkerThread(socket),这是对其构造函数的调用,因此返回了一个实例。
      • 不,因为 .作为“新”具有更高的优先级。因此它首先评估 WorkerThread(socket).start() 然后 new
      • @chrset 谁告诉你的?
      • 看这里:introcs.cs.princeton.edu/java/11precedence。操作员 。用于访问对象成员的优先级最高
      • @chrset 不。调用再次在构造函数上,而不是在类上。而且您引用的文章似乎仅与数学表达式有关。
      猜你喜欢
      • 2011-09-16
      • 2012-12-13
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      相关资源
      最近更新 更多