Java: static-non-static is 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);
}
}
}
Refresh: define "current object"
A constructor created, an object created, but this
not related to the current "test" object. It works when I change it to "test", but it doesn't 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; }
}
source to share
Why am I getting an error with "this" but not with "TestFilter"?
-
this
used to refer to attributes or methods of an instance (among others). Instance means that a new object exists and each object (instance) has a copy of the given attribute. -
class name
(in your caseTestFilter
) is used to refer to attributes or methods of a class (those that don't require an instance to be exposed.
So, in your first line, you are declaring filterFiles
as a class attribute (you don't need an instance for that.
Cm:
private static final FileFilter filterFiles;
This means that you are declaring a class attribute with a name: of filterFiles
type FileFilter
, which is private
and the reference to which cannot be changed (as it is final
).
Since it is a class attribute , you can access it in a method main
(which is a class level method). This will work:
for(File f : file.listFiles(TestFilter.filterFiles)){
and
for(File f : file.listFiles(filterFiles)){
But
for(File f : file.listFiles(this.filterFiles)){
It won't because it this
refers to the current instance, but since you are in a class-level method (main) there is no instance, so there is no this
or in the words of the compiler: a static variable that cannot be referenced from a static context
Instance attributes are unique to each instance. The class level attribute is unique for each 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"
}
}
Hope this pattern makes it clear.
source to share
The keyword this
refers to the current object - something you don't have because your method is static. This means that it works on the class itself and not on any object, so any use this
is invalid, even if the particular variable you are trying to access is also static. The correct way to access a static member belongs to the: class TestFilter.filterFiles
, not this.filterFiles
.
source to share
you cannot reference instance variables such as the "this" pointer in static functions. Since TestFilter is a class and filterFiles variable is static, it works because you can use static vars in static functions.
If TestFilter is what you intend to create as a class, then I suggest moving the code inside the main function to the constructor. In this case, you will be able to access "this".
source to share