开发者

Java: static-non-static-this problem

$ 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);
        }
    }
}

Update: define "current object"

Constructor created, object created but the this does not refer to the current object "test". It works when I change this to "test" but it does not work with "this". Why?

$ 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; }
}


The keyword this refers to the current object -- something that you don't have, because your method is static. That means it's running on the class itself, not on any object, so any use of this is invalid -- even though the specific variable you're trying to access is static too. The correct way to access a static member is by the class: TestFilter.filterFiles, not this.filterFiles.


Why do I get the error with "this" but not with "TestFilter"?

  • this is used to refer to "instance" attributes or method ( among others ). Instance means a new object exist and each object ( instance ) have a copy of the given attribute.

  • The class name ( in your case TestFilter ) is used to refer to "class" attributes or methods ( those who do not require an instance to extist.

So, in your first line you're declaring filterFiles as a class attribute ( you don't require an instance for that.

See:

private static final FileFilter filterFiles;

This means, you declare class attribute named: filterFiles of type FileFilter which is private and whose reference can't be changed ( because it is final).

Since it is a class attribute you may access it in the main method ( which is a class level method ). This both will work:

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

and

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

But

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

Won't, because this refers to the current instance, but since you're in a class level method ( main ) there is no instance, so, there is no this or in compiler words: non-static variable this cannot be referenced from a static context

Instance attributes are unique per instance. Class level attribute are unique per class.

Consider the following class:

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"

     }
}

I hope this sample make everything clear.


you cannot reference instance variables like the "this" pointer in static functions. Since TestFilter is the class and the filterFiles variable is static, it works, because you can use static vars in static functions.

If TestFilter is something that is supposed to be instantiated as a class, I suggest moving the code inside the main function to the constructor. In that case, you would be able to access "this".


this is a reference to the instance of the object actually used. In a static method the class wasn't instantiated - this has no meaning in this context.


Static members are referenced by Class, not by instance. What this means is that you must use class name to reference the static member, not instance name.

Because this refers to an instance, you get compile error.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜