Java Thread, как получается ответ А? - PullRequest
3 голосов
/ 28 сентября 2010

Вопрос от http://www.javacertifications.net/javacert/scjp1.6Mock.jsp

Вопросы нет -20

Что выводится для кода ниже?

public class Test extends Thread
{   
    static String sName = "good";
    public static void main(String argv[])
    {
        Test t = new Test();
        t.nameTest(sName);
        System.out.println(sName);    
    }
    public void nameTest(String sName)
    {
        sName = sName + " idea ";
        start();
    }
    public void run()
    {
        for(int i=0;i  <  4; i++)
        {
            sName = sName + " " + i;

        }
    }
}

опции Хороший Б) хорошая идея В) хорошая идея хорошая идея Правильный ответ: A

Пояснения: изменение значения в локальных методах не изменится в глобальном в случае String (потому что объект String является неизменным).

Ответы [ 8 ]

8 голосов
/ 28 сентября 2010

Ни один из ответов не является правильным, и нет единственного правильного ответа.

Вопрос очень плохой, потому что он смешивает две совершенно разные проблемы:

  • Параметр sName метода nameTest() скрывает статическую переменную с тем же именем, и изменения в локальной переменной не действуют.
  • nameTest() запускает поток, который изменяет статическую переменнуюв его методе run(), а метод main() печатает переменную, не дожидаясь завершения этого потока.Это известно как состояние гонки : в значительной степени совпадение, какое состояние переменной будет напечатано - возможно любое из следующих действий:
    • хорошо
    • хорошо 0
    • хорошо 0 1
    • хорошо 0 1 2
    • хорошо 0 1 2 3
3 голосов
/ 28 сентября 2010

Обратите внимание, что метод nameTest имеет параметр String sName, который эффективно скрывает члена класса static с тем же именем. Итак, линия

sName = sName + " idea ";

обозначает, а изменяет параметр локального метода вместо static члена класса . Чтобы получить доступ к члену класса из метода, он должен быть дополнен именем класса, т.е. Test.sName.

В методе run член static sName изменяется, однако, в конечном итоге он становится чем-то вроде "good 0 1 2 3". Тем не менее, существует условие гонки между основным потоком, который (неявно) запускает поток t, затем печатает значение sName, и дочерним потоком, который изменяет это же значение. Поскольку синхронизация не задействована, вполне возможно, что основной поток напечатает значение до того, как будет изменено другим потоком (т.е. "хорошо"). Результатом также может быть «хороший 0», «хороший 0 1» и т. Д. Однако из всех перечисленных только «хороший» указан. Так что A является единственным возможным ответом .

1 голос
/ 28 сентября 2010

Метод nameTest изменяет локальный параметр sName вместо статического параметра.следовательно, вывод «Хороший».

Для изменения статического параметра, я думаю, вам нужно использовать Test.sName

1 голос
/ 28 сентября 2010

Ответ на этот метод:

public void nameTest(String sName){
        sName = sName + " idea ";
         start();
}

Там назначение sName относится к входному параметру sName, а не к статическому значению Test.sName.

Итак, когда при методе run() вы получаете доступ к статическому члену, вы получите начальное значение ("good")

0 голосов
/ 28 сентября 2010

Фактически запущенная программа возвращает

хорошо 0 1 2 3

(на самом деле выписал и попытался запустить его в Java ... вы должны попробовать).

Проходя через программу, мы можем думать об этом так:

В функции nameTest sName является локальной строковой переменной.

Как сказано в объяснении, строки являются неизменяемыми, поэтому объединение строк с «идеей» создаст новый экземпляр строки - «хорошая идея» - и назначит его локальной переменной sName. Переменная класса sName (я думаю, ее не следует называть глобальной) в результате останется «хорошей».

Затем он запускает функцию потока, используя start (), которая вызывает run ().

В функции run () мы делаем конкатенацию еще раз, но на этот раз мы присваиваем переменной класса sName.

Поэтому, когда функция run () возвращается, переменная класса sName изменяется, и распечатка будет отражать это.

0 голосов
/ 28 сентября 2010

В методах вы всегда имеете дело с локальной ссылкой COPY (если вы задаете ее как аргумент).Вы изменили ссылку COPY, но источник остается прежним.ответ может быть good, good 0, good 0 1 и т. д.

0 голосов
/ 28 сентября 2010

Это выведет «хорошо» Когда вы вызываете nameTest (sName), вы передаете только копию ссылки, поэтому любые изменения происходят, когда в контексте nameTest вы работаете с другой переменной. Это означает, что любая попытка переназначения этой переменной не вступит в силу вне nameTest. Глобальная статическая переменная sName также скрыта параметром sName. Если бы строка не была неизменной, в них можно было бы внести изменения.

0 голосов
/ 28 сентября 2010

В этом случае существует ловушка в методе nameTest.Обратите внимание, что имя параметра метода совпадает с именем статической переменной.

В Java разрешение переменных говорит о том, что в этом случае осуществляется доступ к параметру, а статическая переменная его «скрыта».Если вы хотите получить доступ к статической переменной, вы должны использовать Test.sName.

Таким образом, в этом примере «идея» никогда не добавляется к статической переменной sName.Единственный доступный ответ, который не включает «идею», это А, поэтому 1 - хороший ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...