2013-04-05 2 views
10

При исследовании another question, я с удивлением обнаружил, что следующий код Java компилируется без ошибок:Использование this.var во время инициализации Var в

public class Clazz { 
    int var = this.var + 1; 
} 

В моей JDK6, var инициализируется в 1.

Имеет ли вышеуказанный код хорошо определенную семантику, или его поведение не определено? Если вы говорите, что это четко определено, процитируйте соответствующие части JLS.

+0

Что здесь не так? –

+0

@Sudhanshu: 'var' используется для инициализации' var'. – NPE

+0

Во-первых, this.var = 0, то вы добавите его на 1, тогда это станет 1 –

ответ

4

Он упоминается мимоходом в примере 8.3.2.3-1 в section 8.3.2.3. В тексте на примере

class Z { 
    static int peek() { return j; } 
    static int i = peek(); 
    static int j = 1; 
} 
class Test { 
    public static void main(String[] args) { 
     System.out.println(Z.i); 
    } 
} 

надпись говорит:

... переменная инициализатор I использует метод класса заглядывать, чтобы получить доступ к значению переменной J , прежде чем J было инициализируется его инициализатором переменной, после чего он по-прежнему имеет значение по умолчанию (§4.12.5).

Это должно отображаться непосредственно в вашей ситуации.

+0

Блестящий, это он, спасибо. – NPE

0

Introduction of Chapter 16

Глава 16 описывает точный способ, в котором язык обеспечивает , что локальные переменные определенно установить перед использованием. В то время как все остальные переменные автоматически инициализируются значением по умолчанию, язык программирования Java не автоматически инициализирует локальные переменные во избежание маскировки ошибок программирования.

3

Chapter 8.3.2.2. paragraph 2:

инициализации выражения для переменных экземпляра разрешено ссылаться на текущий объект этого (§15.8.3) и использовать ключевое слово супер (§15.11.2, §15.12).

Хотя следующий пункт добавляет:

Использование переменных экземпляра, чьи заявления появляются текстуально после использования иногда ограничено, даже если эти переменные экземпляра находятся в области видимости. См. Раздел 8.3.3.3 для точных правил, регулирующих прямую ссылку на переменные экземпляра.

-1

В этом нет ничего плохого. это ключевое слово относится к текущему объекту и используется для различения локальной переменной и переменной экземпляра. Значение локальной переменной также может быть присвоено переменной экземпляра, и наоборот. Это означает, что мы можем присвоить значение переменной экземпляра локальной переменной.

см. Главу 4.12.3 Виды переменных от http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf (стр. 80). Пример также приведен здесь.

 **Example 4.12.3-1. Different Kinds of Variables** 
     class Point { 
     static int numPoints; // numPoints is a class variable 
     int x, y; // x and y are instance variables 
     int[] w = new int[10]; // w[0] is an array component 
     int setX(int x) { // x is a method parameter 
     int oldx = this.x; // oldx is a local variable 
     this.x = x; 
     return oldx; 
     } 
    } 
+1

ОП вопрос другой. Вопрос касается «прямых ссылок». Вопрос OP не говорит о локальной переменной и переменной экземпляра. – AmitG

0

Использование simple имя не допускается в случае forward references согласно JSL. Таким образом, для использования таких переменных необходимо использовать .

class UseBeforeDeclaration { 
    int h = j++; // error - `j` read before declaration 
    int l = this.j * 3; // ok - not accessed via simple name 
    int j; 
} 
+1

Это было определено в вопросе, связанном в начале этого вопроса. Что NPE спрашивает: есть ли у нас гарантия того, что 'var' будет один после' int var = this.var + 1; 'и почему? – assylias

0

Поскольку все нелокальных переменных присваивается начальное значение (и присвоение происходит, прежде чем все остальное), нет никаких проблем, чтобы читать их в любое время.

Спецификация выборочно запрещает некоторые обращения в некоторых ситуациях, полагая, что такие обращения, скорее всего, являются ошибками программирования. Но если бы они были разрешены, у них была бы определенная семантика.

На самом деле программист может легко обойти ограничения и «косвенно» получить доступ к полю в любом случае; семантика этого доступа такая же, как и «прямой» доступ, если это разрешено.

int var = this.var + 1;  // suppose javac forbids this 

int var = this.getVar() + 1; // but can javac forbid this? 
Смежные вопросы