方法参数中的final关键字不变

时间:2019-05-10 10:41:18

标签: java parameters final

我对决赛有一些疑问。代码如下

public class Demo {
    private static Thread thread;
    public static void main(String[] args) {
        for (int i = 0; i < 4; i++) {
            fun("url-" + i);
        }
    }
    public static void fun(final String url) {
        if (thread == null) {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(url);
                }
            });
        }
        thread.run();
    }
}

输出:

url-0
url-0
url-0
url-0

为什么?我认为看起来像这样

url-1
url-1
url-3
url-4

3 个答案:

答案 0 :(得分:1)

该参数上的关键字 final 与您观察到的无关。

这实际上发生了什么:您创建一个一个线程对象,该对象是Thread的匿名内部 sub 类的实例。该实例将url-0作为参数。然后,此后,您将调用该线程对象的run()方法4次。因此,同一对象将打印相同的字符串4次。

更准确地说:

  • 第一次输入fun()时,静态thread字段为空
  • 因此将创建一个新实例,并将传入的字符串复制到该(线程的子类)对象的上下文中。该字符串是“ url-0”
  • 然后您对该对象调用run()4次

并且如注释中所概述:仅在线程对象上调用run()不会导致真正的OS线程并行工作。您必须改为致电start()。但是,当然,对于同一线程,重复调用start()绝对没有意义。

因此,为了使您的代码做更多的预期工作,请尝试以下操作:

public class Demo {

  public static void main(String[] args) {
    for (int i = 0; i < 4; i++) {
        fun("url-" + i);
    }
  }
  public static void fun(String url) {
    Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(url);
            }
        });
        thread.start();
  }       
}

答案 1 :(得分:1)

您一次定义了Thread对象。每次fun方法的后续调用都使用该实例。 这与urlfinal

的事实无关

如果将方法实现更改为类似的内容(使thread为局部作用域变量),则会看到预期的输出:

public static void fun(String url) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println(url);
        }
    });
    thread.run();
}

换句话说,当您创建Thread对象时,它会记住传递给它的url的值。而且,由于Thread参数取不同值时没有创建其他url对象,因此只能看到创建对象时传递的url的值,这说明了原因您每次都会看到url-0

答案 2 :(得分:0)

您没有获得预期的输出,因为您仅使用第一个参数'url-0'实例化了Thread仅一次。然后,每次调用方法fun时,您只是在唯一一个创建的线程thread.run()上使用参数'url-0'调用该方法