2015-06-24 5 views
3

Я знаю Operator Precedence list, но я просто не могу понять, каков приоритет выполнения в этом коде в «LINE 1». Какой объект создается ранее? Например: My String или new Precedence()? Как мы можем применить правило Приоритета Оператора в этом примере?Пример Приоритета Java-оператора

public class Precedence { 
    public String s; 
    public static void main (String ... args){ 
     String a = new Precedence().s="My String"; // LINE 1 
     System.out.println(a); 
    } 
} 

ВЫВОД: My String

+0

Обратите внимание, что приоритет оператора отличается от порядка выполнения. –

+0

Как я могу узнать, что это случай исполнения? –

+0

@ThurfirHawat Я не знаю, как «как я могу узнать, что это случай исполнения» означает, но единственная проблема с приоритетом оператора здесь находится между '=' и '.'. Здесь есть несколько * других * проблем, а именно ассоциативность оператора '=' и тот факт, что 'String' value' 'My String '' создается компилятором и загрузчиком классов, а не этим кодом. – EJP

ответ

3

Этот

String a = new Precedence().s="My String"; // LINE 1 

является local variable declaration statement с выражением инициализации.

Каждый раз, когда он выполняется, деклараторы обрабатываются в порядке от слева направо. Если декларатор имеет инициализатор, инициализатор оценивается и его значение присваивается переменной.

a является декларатором. Он оценивается для создания переменной (самой). Затем вычисляется выражение инициализации.

Это

new Precedence().s = "My String"; 

является an assignment expression. Левую часть оператора оценивают сначала для получения переменной, поэтому сначала оценивается new Precedence(), создает экземпляр класса Precedence, создавая ссылку на объект. Затем оценивается правая сторона присваивания, String буква "My String", поэтому создается ссылка на объект String. Затем присваивание присваивает ссылку объекту String переменной s объекта, на который ссылается значение, возвращаемое выражением создания нового экземпляра.

Наконец, так как

во время выполнения, результатом выражения присваивания является значение переменной после того, как присвоение произошло.

Значение, присвоенное полю s от объекта Precedence также присваивается переменной a.

+0

tnx за этот отличный ответ. –

1

Вот байткодом:

public static transient varargs main([Ljava/lang/String;)V 
    L0 
    LINENUMBER 8 L0 
    NEW Precedence 
    DUP 
    INVOKESPECIAL Precedence.<init>()V 
    LDC "My String" 
    DUP_X1 
    PUTFIELD Precedence.s : Ljava/lang/String; 
    ASTORE 1 

Это показывает следующий порядок выполнения:

  1. Создать Precedence объект.
  2. Назначить: My String постоянный - Precedence.s.
  3. Назначить его также a.
+1

Здесь нет шага, который инициализирует строковую константу. Это должно быть 2. Назначьте константу 'My String'' Precedence.s', а затем 3. Назначьте ее также 'a'. – EJP

+0

где назначается поле 's' локальной переменной' a'. Знаете ли вы, почему не отображается в javap -c? –

+1

Это сделано «ASTORE 1». Не понимаю вторую половину вопроса. –

1

Существует инструмент javap, dissasembler, который покажет вам байт-код, и оттуда вы можете заключить, что такое порядок исполнения.Он выведет комментарии.

$ /usr/lib/jvm/java-7-oracle/bin/javap -c Precedence.class 
Compiled from "Precedence.java" 
public class Precedence { 
    public java.lang.String s; 

    public Precedence(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: return   

    public static void main(java.lang.String...); 
    Code: 
     0: new   #2     // class Precedence 
     3: dup   
     4: invokespecial #3     // Method "<init>":()V 
     7: ldc   #4     // String My String 
     9: dup_x1   
     10: putfield  #5     // Field s:Ljava/lang/String; 
     13: astore_1  
     14: getstatic  #6     // Field java/lang/System.out:Ljava/io/PrintStream; 
     17: aload_1  
     18: invokevirtual #7     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     21: return   
} 

javap является частью JDK, путь находится на Linux, switch -c - дизассемблировать код. Вот определение инструкции ldc, не очевидно, что он делает

push a constant #index from a constant pool (String, int or float) onto the stack 
+0

где назначаются поля 's' локальной переменной' a'. Знаете ли вы, почему не отображается в javap -c? –

+0

@ThufirHawat 'astore_1' хранит строку переменной a, перед тем как' ldc' помещает строку в стек, 'dup_x1' дублирует ее,' putfield' загружает первую копию в objectref, и, наконец, вторая копия переходит к a. Вы можете видеть, что 'aload_1' загружает его для печати. –

Смежные вопросы