Java: статическая-нестатическая-эта проблема - PullRequest
2 голосов
/ 13 апреля 2010
$ javac TestFilter.java 
TestFilter.java:19: non-static variable this cannot be referenced from a static context
        for(File f : file.listFiles(this.filterFiles)){
                                    ^
1 error
$ sed -i 's@this@TestFilter@g' TestFilter.java 
$ javac TestFilter.java 
$ java TestFilter
file1
file2
file3

TestFilter.java

import java.io.*;
import java.util.*;

public class TestFilter {
    private static final FileFilter filterFiles;

    // STATIC!
    static{
        filterFiles = new FileFilter() {
            // Not Static below. When static, an error:
            // "accept(java.io.File) in  cannot implement 
            // accept(java.io.File) in java.io.FileFilter; 
            // overriding method is static"
            //
            // I tried to solve by the change the problem at the bottom.

            public boolean accept(File file) {
                return file.isFile();
            }
        };
    }

   // STATIC!
    public static void main(String[] args){
        HashSet<File> files = new HashSet<File>();
        File file = new File(".");

            // IT DID NOT WORK WITH "This" but with "TestFilter".
            // Why do I get the error with "This" but not with "TestFilter"?

        for(File f : file.listFiles(TestFilter.filterFiles)){
            System.out.println(f.getName());
            files.add(f);
        }
    }
}

Обновление: определить "текущий объект"

Конструктор создан, объект создан, но this не ссылается на текущий объект «тест». Это работает, когда я изменяю это на «тест», но не работает с «этим». Почему?

$ javac TestFilter.java 
TestFilter.java:28: non-static variable this cannot be referenced from a static context
        for(File f : this.getFiles()){
                     ^
1 error
$ cat TestFilter.java 
import java.io.*;
import java.util.*;

public class TestFilter {

    private static final FileFilter filterFiles;
    private HashSet<File> files;

    static{
        filterFiles = new FileFilter() {
            public boolean accept(File file) {
                return file.isFile();
            }
        };
    }

    TestFilter(){
        files = new HashSet<File>();
        File file = new File(".");

        for(File f : file.listFiles(filterFiles)){
            files.add(f);
        }
    }

    public static void main(String[] args){

        // CONSTRUCTOR with no pars invoked and object "test" created here!

        TestFilter test = new TestFilter();

        // Why does it not work with "this"? 
        // "test" is surely the current object.

        for(File f : this.getFiles()){
            System.out.println(f.getName());    
        }
    }

    public HashSet<File> getFiles() { return files; }
}

Ответы [ 5 ]

12 голосов
/ 13 апреля 2010

Ключевое слово this относится к текущему объекту - то, чего у вас нет, потому что ваш метод статичен. Это означает, что он работает на самом классе, а не на каком-либо объекте, поэтому любое использование this недопустимо - , даже если конкретная переменная, к которой вы пытаетесь обратиться, тоже статическая. Правильный способ доступа к статическому члену - класс: TestFilter.filterFiles, а не this.filterFiles.

6 голосов
/ 13 апреля 2010

Почему я получаю ошибку с «this», а не с «TestFilter»?

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

  • class name (в вашем случае TestFilter) используется для ссылки на "классовые" атрибуты или методы (те, кому не требуется экземпляр для существования.

Итак, в первой строке вы объявляете filterFiles атрибутом класса (для этого вам не нужен экземпляр.

См:

private static final FileFilter filterFiles;

Это означает, что вы объявляете атрибут class с именем: filterFiles типа FileFilter, который равен private и чья ссылка не может быть изменена (потому что это final).

Поскольку это атрибут class , вы можете получить к нему доступ с помощью метода main (который является методом уровня класса). Это оба будут работать:

for(File f : file.listFiles(TestFilter.filterFiles)){

и

for(File f : file.listFiles(filterFiles)){

Но

for(File f : file.listFiles(this.filterFiles)){

Не будет, потому что this относится к текущему экземпляру, но, поскольку вы находитесь в методе уровня класса (main), экземпляра нет, поэтому нет this или в словах компилятора: нестатическая переменная, на которую нельзя ссылаться из статического контекста

Атрибуты экземпляра уникальны для каждого экземпляра. Атрибут уровня класса уникален для каждого класса.

Рассмотрим следующий класс:

import static java.lang.System.out;
class Employee  {
     // class level counter. It exist regardless of the instances created.
     public static int employeeCount = 0;
     // instance attribute. Each one is different from others instances
     private String employeeName;

     // Class level method, can be invoked without instance.
     public static Employee createEmployee( String withName ) {

         Employee e = new Employee();
         // Set the name to the instance
         e.employeeName = withName;
         // Increments the class counter
         Employee.employeeCount++;
         return e;
     }
     // Object constructor.
     public Employee() {
          out.println("Constructor invoked!!! A new object has born, yeah!");
     }
     // Instance method "toString()"
     public String toString() {
         // Uses "this" to refer instance level method
         return this.emploeeName;
     }

     // Test
     public static void main( String [] args ) {

          // The counter already exist
          out.printf("Employees created %d%n", Employee.employeeCount );
          // Create employee a
          Employee a = Employee.createEmployee("Oscar");
          // Its name now exists 
          out.printf("Employee name: %s %nEmployees created %d%n",
                      a.employeeName,  Employee.employeeCount );
          // Create employee b with a new name 
          Employee b = Employee.createEmployee("HH");
          out.printf("Employee name: %s %nEmployees created %d%n", 
                      b.employeeName,  Employee.employeeCount );
          // Now both employees exist, each one with a name 
          out.printf("a=%s, b=%s%n, a, b );// invoke toString method which in turn uses "this"

     }
}

Надеюсь, этот пример прояснит все.

0 голосов
/ 13 апреля 2010

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

Поскольку this ссылается на экземпляр, вы получаете ошибку компиляции.

0 голосов
/ 13 апреля 2010

это ссылка на экземпляр фактически используемого объекта. В статическом методе класс не был создан - это не имеет смысла в этом контексте.

0 голосов
/ 13 апреля 2010

вы не можете ссылаться на переменные экземпляра, такие как указатель "this" в статических функциях. Поскольку TestFilter является классом, а переменная filterFiles является статической, она работает, поскольку вы можете использовать статические переменные в статических функциях.

Если TestFilter - это что-то, для чего создается экземпляр класса, я предлагаю перенести код внутри функции main в конструктор. В этом случае вы сможете получить доступ к «этому».

...