2013-03-24 6 views
0

Я посмотрел на Why can't I use the keyword "this" when referring to fields in static methods?Каков реальный смысл «этого» в Java?

и подумал, что доступ к статическим членам через эталонную переменную в порядке, но с использованием this для доступа к таким членам не в порядке. Посмотрите на код ниже.

static int month; 

public static void setMonth(int x) 
{ 
Date date = new Date(); 
date.month = x; //fine, why ? 
    this.month = x; //compiler error, why ? 
} 

Это ясно показывает, что this не то же самое в качестве опорной переменной. Если это так, то что это на самом деле? Мне нужно понять истинный смысл this, чтобы понять, почему он не может быть доступен из статического контекста.

Пожалуйста, не указывайте ссылки на случайные блоги или учебные пособия по oracle, в которых говорится, что this не может использоваться из статического контекста - я уже это знаю. Я хочу посмотреть дальше этого и понять, почему его нельзя использовать.

код в связанном вопросе -

public class Date 
{ 

static int month; 

public static void setMonth(int x) 
{ 
this.month = x; //compiler error 
} 

public static int getMonth() 
{ 
return month; //compiles just fine, no error 
} 

} 
+2

Нет никакого «этого» в чем-либо статичном, поскольку вы имеете дело с классом, а не с экземпляром класса. 'this' относится только к экземпляру. – tjb1982

+2

'this' относится к * текущему экземпляру * этого класса. В статическом контексте по определению не существует текущего экземпляра класса. В результате «this' нельзя вызывать в статическом контексте. – Vulcan

ответ

2
public static void setMonth(int x) 
{ 
this.month = x; //compiler error 
} 

this относится к текущему экземпляру объекта. Нет такой вещи в статическом методе, поскольку статический метод связан с классом в целом, а не с каким-либо конкретным экземпляром.

Вы не можете использовать this в статическом методе.

То, что поле, на которое вы ссылаетесь (month), фактически является статическим полем, а не полем экземпляра не имеет значения. Здесь вам не понадобилось бы this, но если вы попытаетесь получить к нему доступ, компилятор остановит вас.

public static int getMonth() 
{ 
return month; //compiles just fine, no error 
} 

month - статическое поле. Подобно статическому методу, он принадлежит самому классу и не нуждается в разрешении экземпляра.

0

Ключевое слово this относится к экземпляру текущего объекта.

Вы не можете использовать его из контекста static, потому что нет примера по определению понятия static в java. Доступ к методу static можно получить по номеру все экземпляры.

Пример

public static final class MyClass { 

    public static final class MyInnerClass { 

     public void doStuff() { 
      System.out.println(this.toString()); 
     } 

     @Override 
     public String toString() { 
      return "MyInnerClass toString."; 
     } 
    } 

    public void doStuff() { 
     System.out.println(this.toString()); 
     new MyInnerClass().doStuff(); 
    } 

    @Override 
    public String toString() { 
     return "MyClass toString."; 
    } 
} 

public static void main(String[] args) throws InterruptedException { 
    new MyClass().doStuff(); 
} 

Выход

MyClass toString. 
MyInnerClass toString. 

Так this в doStuff методом MyClass относится к экземпляру MyClass внутри которого doStuff был вызван.

this в MyInnerClass не относится к экземпляру MyClass а к экземпляру MyInnerClass, из которого его doStuff называлась.

thisвсегда относится к экземпляру объекта, из которого используется ключевое слово. Если экземпляра нет, как и в методе static, ключевое слово this использовать нельзя.

3

Когда вы вызываете нестатический метод, например. myObject.myMethod(), компилятор добавляет дополнительный секретный параметр, оцененный 'myObject', который доступен внутри метода как 'this'.

Когда вы вызываете статический метод, например. MyClass.myStaticMethod(), нет объекта для назначения значения секретного параметра, поэтому нет лишнего секретного параметра, поэтому «this» не может иметь значения внутри статического метода.

+0

EJP - Это аналогия? Если нет, то, пожалуйста, покажите мне источник этой информации. –

+0

@skyscraper Не похоже, факт. Общие знания среди авторов компиляторов. Посмотрите на любой код байта Java для доказательства. – EJP

1

Это действительно очень просто, как только вы понимаете, что означает static.

Ключевое слово this (при использовании таким образом) означает «текущий объект».

Когда вы объявляете метод как static, вы говорите, что метод всегда будет вызываться без назначения определенного объекта в качестве текущего объекта. Итак, когда вы находитесь в методе static, нет «текущего» объекта ... и в качестве логического результата вы не можете использовать this, потому что это не имеет смысла.

Существует только «текущий» объект, если вы находитесь в методе экземпляра или конструкторе . В первом случае «текущий» объект является тем, на который вы вызвали метод. В последнем случае это объект, который вы создаете.


1 ... или блок экземпляр инициализатор

1

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

public class Test { 
    static int month; 
    public static void main(String[] args) { 
    new Test().setMonth(5); 
    System.out.println(month); 
    } 
    public void setMonth(int x) 
    { 
     this.month = x; 
    } 
} 
+1

И он нахмурился и генерирует предупреждение компилятора (по крайней мере, с некоторыми компиляторами). – Thilo

+1

Как и должно быть. Это точно так же, как и любое другое ссылочное выражение. –

1

В коде date.month = x; ТОЧНО эквивалентно Date.month = x; и это то, что компилятор во время компиляции. То, что вы положили на левую сторону, на самом деле не имеет значения. По этой причине доступ к статическому полю или методу с помощью ссылки сильно обескуражен - похоже, что дело слева от точки имеет значение, но это не так; имеет значение только тип времени компиляции. Рассмотрение

(new Date()).month = x; 
((Date)null).month = x; 
// suppose SubDate is a subclass of Date, with its own static "month" field 
((Date)new SubDate()).month = x; 

Все вышеперечисленное делает ТОЧНОЕ то же самое.

Так что, когда вы говорите

и подумал, что доступ к статическим членам через эталонную переменную нормально

Доступ к статическим членам через эталонную переменную никогда не следует использовать. Потому что это огромная иллюзия, которая привела к многочисленным заблуждениям и ошибкам; и, вероятно, никогда не должны быть разрешены на Java.

+0

Можете ли вы привести пример ошибок, вызванных доступом к статическим членам через ссылочную переменную? –

+2

@skyscraper: например, часто на образцах кода вы увидите 'Thread.currentThread(). Sleep (...);' чтобы скрыть текущий поток в течение определенного периода времени. Тогда у вас может возникнуть соблазн сделать 'someOtherThread.sleep (...);' спать какой-то другой поток. Но на самом деле 'Thread.sleep()' является статическим методом, и обе части кода делают одно и то же - спящий текущий поток. Всегда записывая его как 'Thread.sleep (...);' сделает это более понятным. – newacct

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