No se puede usar 'esto' en un contexto estático

My aim is to have a class containing all functions which perform database operations cleanly and neatly - which can also be called with a single line of code, eg; DbFunctions.AddContact("fName", "lName");

Tengo una clase DBAdapter que he leído en un tutorial:

public class DBAdapter {
static final String KEY_ROWID = "_id";
static final String KEY_NAME = "name";
static final String KEY_EMAIL = "email";
static final String TAG = "DBAdapter";

static final String DATABASE_NAME = "MyDB";
static final String DATABASE_TABLE = "contacts";
static final int DATABASE_VERSION = 1;

static final String DATABASE_CREATE =
        "create table contacts (_id integer primary key autoincrement, "
        + "name text not null, email text not null);";

final Context context;
DatabaseHelper DBHelper;
SQLiteDatabase db;

public DBAdapter(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}

private static class DatabaseHelper extends SQLiteOpenHelper
{
    DatabaseHelper(Context context)
    {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
        try
        {
            db.execSQL(DATABASE_CREATE);
        }
        catch (SQLException ex)
        {
            ex.printStackTrace();
        }
    }
}

//---opens the database---
public DBAdapter open() throws SQLException
{
    db = DBHelper.getWritableDatabase();
    return this;
}

//---closes the database---
public void close()
{
    DBHelper.close();       
}   

// some other database functions here... inserts, updates etc
}

Y he creado mi propia clase para manejar todas las llamadas al DBAdapter:

    public static class DatabasesActivity extends Activity
{       
    static DBAdapter db;

   //Called when activity is first created
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public static long addContact(String name, String email)
    {
        if (db == null) {
            db = new DBAdapter(this);//<--- compiler error here
        }

        db.open();
        long id = db.insertContact("Joe Bloggs", "[email protected]");
        db.close();
        return id;
    }
}

En el método addContact , en la línea: db = new DBAdapter (this); , obtengo el siguiente error: No puedo usar 'this' en un contexto estático .

Estoy familiarizado con los conceptos de POO, por lo que entiendo por qué estoy recibiendo este error, pero como soy nuevo en Java, estoy buscando métodos alternativos para lo que estoy tratando de lograr. El constructor de la clase DBAdapter toma un parámetro de context , pero no estoy seguro de por qué, ya que no he escrito esa clase.

Para aclarar: Entiendo por qué está ocurriendo el error. El constructor de la clase DBAdapter toma un parámetro context , y no sé qué pasar como parámetro de contexto cuando lo estoy usando de forma estática. Quiero que la clase sea estática, ya que no quiero tener que crear instancias cada vez que quiero usarla.

Supongo que mi verdadera pregunta sería "¿por qué SQLiteOpenHelper requiere un contexto?"

1
@MarcoForberg Raramente he usado este en C #. Tu comentario no es realmente muy útil.
agregado el autor Mike Baxter, fuente
@MarcoForberg Como dije; Una cantidad de fair simplemente significa que he escrito una cantidad correcta de código C #. Alrededor de 6 meses. Eso no significa que yo sea un experto, ni dije que lo fuera. Su gente como usted hace que el desbordamiento de pila sea un sitio web muy desagradable.
agregado el autor Mike Baxter, fuente
@KlausByskovPedersen Si hubiera leído la pregunta correctamente, vería que entiendo la diferencia entre estática y no estática , eso es completamente elemental. Estoy buscando soluciones alternativas ya que no estoy tan familiarizado con Java en sí.
agregado el autor Mike Baxter, fuente
Dado que esta pregunta fue tan mal entendida (es mi culpa no haber explicado suficientemente bien mi problema). He creado una pregunta más actualizada aquí. stackoverflow.com/questions/17234451/…
agregado el autor Mike Baxter, fuente
@Teifi simplemente está señalando que si ha hecho una buena cantidad de codificación, debería saber la diferencia entre los métodos de instancia y los métodos estáticos. Como claramente no sabes la diferencia, te sugiero que tomes 15 minutos y léaslo.
agregado el autor Klaus Byskov Pedersen, fuente
@Teifi y por eso es un comentario y no hay respuesta. Solo me lo pregunto porque lo uso bastante a menudo. al menos una vez en cada clase
agregado el autor Marco Forberg, fuente
si no estoy equivocado como en c ++, java no envía esto implícitamente.
agregado el autor Infested, fuente

8 Respuestas

Has definido un método static aquí:

  public static long addContact(String name, String email)

Static methods and class variables are tied to the Class and not to any specific instance of the Class. You cannot use the this keyword inside it as it refers to the current instance. One of the choice will be to declare the method as instance method removing the static keyword from the method declaration, if indeed the method logic depends on the state of the current instance.

Creo que el problema al usar this dentro de un método static será durante el tiempo de ejecución si su código llama al método estático como ClassName.staticMethodName() , el tiempo de ejecución no tendrá idea de cómo resolver this en este contexto.

7
agregado
El método constructor DBAdapter toma un parámetro context , y no estoy seguro de por qué es necesario. El DBAdapter es código de ejemplo. Si puedes arrojar alguna luz por favor hazlo! :)
agregado el autor Mike Baxter, fuente
Como dije en mi pregunta, entiendo por qué me está dando el error. Estoy buscando métodos alternativos para lograr mi objetivo :)
agregado el autor Mike Baxter, fuente
@Teifi, ¿por qué necesita this dentro del método?
agregado el autor NINCOMPOOP, fuente

this refers to the current instance of that class.

Los métodos y objetos estáticos existen fuera de cualquier instancia, por lo que no se le permite usar datos específicos de la instancia, como la instancia actual, dentro de ellos.

2
agregado

este es un puntero a un objeto ... en un contexto estático no tiene un objeto.

¿Por qué la DatabaseActivy es una clase estática? Así que haz una clase normal y crea un objeto de ella.

2
agregado
@Birdy Estoy tratando de crear una clase que me permita realizar estas operaciones de base de datos con una sola línea de código. Estoy tratando de evitar tener que crear una instancia de la clase cada vez que quiero usarla.
agregado el autor Mike Baxter, fuente
que tomar el patrón de singleton: theserverside.de/singleton-pattern-in-java
agregado el autor Birdy, fuente
El puntero es un concepto de C ++. Deberías llamarlo una referencia en Java.
agregado el autor Bruno Brant, fuente

No puede acceder a campos o métodos dentro de un método estático.

 Static methods do not point to any instance of the enclosing class.

Así que esta palabra clave se refiere a la instancia de la clase.

In a static context:
you won't have instance reference to current instance.

Así se produce el error.

1
agregado
Como he dicho, entiendo por qué se produce el error. Estoy buscando un método alternativo para evitarlo. Por ejemplo, ¿cómo puedo usar la clase DBAdapter con tener que pasar en el contexto actual?
agregado el autor Mike Baxter, fuente
La pregunta es java :)
agregado el autor Mike Baxter, fuente
Consulte aquí para ver el enlace, pero creo que hay una forma en Android. Vea las respuestas relacionadas con Android :) Si no se ve, stackoverflow.com/questions/2062520/…
agregado el autor ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, fuente
Ok, ve por el patrón de diseño de singleton. Esta es la respuesta en java. Pero en Android me debe de alguna manera fácil, esa es mi intención. :)
agregado el autor ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, fuente

Usted está accediendo a esto en una función estática que no es correcta

haga que la función no sea estática eliminando el modificador estático, entonces funcionará bien

1
agregado
Pero seguramente entonces, cada vez que quiera llamar al método, ¿necesito crear una instancia de la clase? Estoy buscando una solución que me permita llamar al método addContact utilizando solo una línea de código.
agregado el autor Mike Baxter, fuente
lo que puede hacer es crear una instancia estática en la misma clase y llamar a la función usando esa instancia estática ... no cree este método estático
agregado el autor Vikalp Jain, fuente

Mirando este método

// Called when activity is first created
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

No creo que debas usar clase estática, campo estático y método estático en absoluto.

Solo crea una instancia de Activity y trabaja con ella. Si necesita un objeto Activity a través de todo su programa, use Singleton Pattern . Se proporcionan ejemplos de ejemplificación perezosa y ansiosa.

por ejemplo una inicialización impaciente será:

public class DatabaseActivity extends Activity {
private static final DatabaseActivity INSTANCE= new DatabaseActivity();

private DatabaseActivity() {}

public static DatabaseActivity getInstance() {
    return INSTANCE;
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);    //calls nonstatic method onCreate from Activity class
    setContentView(R.layout.activity_main);
} 
}
0
agregado
¿Cuál es un patrón de singleton?
agregado el autor Mike Baxter, fuente
enlace añadido a mi respuesta
agregado el autor Tala, fuente

No puede usar "esto" en un contexto estático porque implica que tiene una instancia del objeto, y estáticamente no puede llamar a las instancias.

¿Por qué necesitas una clase estática?

0
agregado

Has hecho tu clase como estática.

Sólo las clases anidadas pueden ser estáticas. Al hacerlo, puede usar la clase anidada sin tener una instancia de la clase externa.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}
0
agregado