1

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");

I have a DBAdapter class which I have read in a 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
}

And I have created my own class to handle all calls to the 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", "joe@bloggs.com");
        db.close();
        return id;
    }
}

In the addContact method, on the line: db = new DBAdapter(this);, I get the following error: Cannot use 'this' in a static context.

I am familiar with OOP concepts so I understand why I am getting this error - but being new to java itself, I am looking for alternate methods on what I'm trying to achieve. The DBAdapter class constructor takes in a context parameter, but I am unsure why as I have not written that class myself.

To Clarify: I understand why the error is occurring. The DBAdapter class constructor takes in a context parameter, and I don't know what to pass in as the context parameter when I'm using it statically. I want the class to be static as I don't want to have to instantiate it every time I want to use it.

I guess my real question would be "why does SQLiteOpenHelper require a context?"

Mike Baxter
  • 6,868
  • 17
  • 67
  • 115
  • if im not wrong as in c++, java doesnt implicitly send this. – Ariel Pinchover Jun 21 '13 at 10:51
  • 1
    @MarcoForberg I've rarely used `this` in C#. Your comment is not really very helpful. – Mike Baxter Jun 21 '13 at 10:55
  • @Teifi and that is why it is a comment and no answer. Just wondering because i use it quite often. at least once in every class – Marco Forberg Jun 21 '13 at 10:58
  • 2
    @Teifi he is merely pointing out that if you have done a fair amount of coding you **should know** the difference between instance methods and static methods. Since you clearly don't know the difference I suggest you take 15 minutes and read up on it. – Klaus Byskov Pedersen Jun 21 '13 at 11:00
  • 2
    @MarcoForberg Like I said; A `fair` amount just means I've written a OK-ish amount of C# code. About 6 months. That does not mean I am an expert - nor did I claim to be one. Its people like you that make stack overflow a very unpleasant website. – Mike Baxter Jun 21 '13 at 11:01
  • @KlausByskovPedersen If you'd read the question properly, you'd see that I **understand the difference between static and non-static** - that is completely elementary. I am looking for alternate solutions as I am so unfamiliar with java itself. – Mike Baxter Jun 21 '13 at 11:02
  • Since this question was so widely misunderstood (my own fault for not explaining my issue well enough) - I have created a more up to date question here. http://stackoverflow.com/questions/17234451/easy-database-access-methods-in-android – Mike Baxter Jun 21 '13 at 11:46

8 Answers8

7

You have defined a static method here :

  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.

I believe the problem in using this inside a static method will be that during runtime if your code calls the static method as ClassName.staticMethodName() , the runtime will have no idea how to resolve this in this context.

AllTooSir
  • 48,828
  • 16
  • 130
  • 164
  • 1
    As I said in my question, I understand why I am getting the error. I'm looking for alternate methods of achieving my goal :) – Mike Baxter Jun 21 '13 at 10:57
  • @Teifi , why do you need `this` inside the method . – AllTooSir Jun 21 '13 at 10:59
  • 1
    The DBAdapter constructor method takes a `context` parameter, and I'm not sure why it is necessary. The DBAdapter is sample code. If you can shed any light please do! :) – Mike Baxter Jun 21 '13 at 11:03
2

this refers to the current instance of that class.

Static methods and objects exist outside of any instance, which is why you are not allowed to use instance specific data, like the current instance, within them

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
1

You cannot cannot access fields or methods inside a Static method .

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

So this keyword this refers to the instance of the class.

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

So error occurs.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    Like I said, I understand why the error occurs. I'm looking for an alternate method to avoid it. Eg, how can I use the DBAdapter class with having to pass in the current `context`? – Mike Baxter Jun 21 '13 at 11:06
  • The question is java :) – Mike Baxter Jun 21 '13 at 11:09
  • Ok,Go for singleton design pattern.This is answer in java.But In Android there must me some easy way,That is my intention. :) – Suresh Atta Jun 21 '13 at 11:11
  • See here for the link,but I guess there is way in Android.See android related anwers :) If not seelink : http://stackoverflow.com/questions/2062520/how-to-create-single-instance-of-class-in-java – Suresh Atta Jun 21 '13 at 11:14
1

You are accessing this in a static function which is not correct

make the function non-static by removing static modifier then it will work fine

Vikalp Jain
  • 1,419
  • 1
  • 11
  • 20
  • But surely then everytime I want to call the method, I would need to instantiate the class? I am looking for a solution that will allow me to call the method `addContact` using only one line of code. – Mike Baxter Jun 21 '13 at 10:59
  • what you can do is create an static instance in same class and call the fucntion using that static instance ... don't create this static method – Vikalp Jain Jun 21 '13 at 16:57
0

You can't use "this" in static context because it implies you have an instance of the object, and statically you can't call to instances.

Why you need a static class?

Charliemops
  • 749
  • 12
  • 30
0

By looking at this method

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

I don't think you should be using static class, static field and static method at all.

Just create an instance of Activity and work with it. If you need one Activity object through all your program - then use Singleton Pattern. Lazy and Eager instantiation examples are provided.

for example eager initialization will be:

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);
} 
}
Tala
  • 8,888
  • 5
  • 34
  • 38
0

You have made your class as static.

Only nested classes can be static. By doing so you can use the nested class without having an instance of the outer class.

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();
}
Nomesh Gajare
  • 855
  • 2
  • 12
  • 28
-2

this is a pointer to an object.. in static context you don't have an object.

why is the DatabaseActivy a static class? So make a normal class and create an object of it

Birdy
  • 355
  • 1
  • 5
  • 15
  • Pointer is a C++ concept. You should call it a reference in Java. – Bruno Brant Jun 21 '13 at 11:00
  • @Birdy I'm trying to create a class which will allow me to perform these database operations with a single line of code. I'm trying to avoid having to instantiate the class everytime I want to use it. – Mike Baxter Jun 21 '13 at 11:08
  • than take the singleton pattern: http://www.theserverside.de/singleton-pattern-in-java/ – Birdy Jun 21 '13 at 11:34