2013-06-21 2 views
1

Моя цель - иметь класс, содержащий все функции, которые выполняют операции с базой данных чисто и аккуратно, - которые также могут быть вызваны с помощью одной строки кода, например; DbFunctions.AddContact("fName", "lName");Невозможно использовать «это» в статическом контексте

У меня есть класс DBAdapter, который я прочитал в учебнике:

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 
} 

И я создал свой собственный класс для обработки всех вызовов 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; 
    } 
} 

В addContact метод, на строке: db = new DBAdapter(this);, появляется следующая ошибка: Cannot use 'this' in a static context.

Я знаком с концепциями ООП, поэтому я понимаю почему Я получаю эту ошибку - но будучи новым для самой java, я ищу альтернативные методы для достижения того, чего я пытаюсь достичь. Конструктор класса DBAdapter принимает параметр context, но я не уверен, почему, поскольку я сам этого не написал.

Чтобы уточнить: Я понимаю, почему возникает ошибка. Конструктор класса DBAdapter принимает параметр context, и я не знаю, что передать в качестве параметра контекста при его статическом использовании. Я хочу, чтобы класс был статичным, поскольку я не хочу, чтобы он создавал его каждый раз, когда я хочу его использовать.

Я предполагаю, что мой реальный вопрос будет «почему SQLiteOpenHelper требует контекста?»

+0

Если им не так, как в C++, java не подразумевает его отправку. – Infested

+1

@MarcoForberg Я редко использовал 'this' в C#. Ваш комментарий не очень полезен. –

+0

@Teifi, и именно поэтому это комментарий и никакого ответа. Просто интересно, потому что я использую его довольно часто. по крайней мере один раз в каждом классе –

ответ

6

Вы определили static метод здесь:

public static long addContact(String name, String email) 

Статические методы и переменные класса привязаны к классу, а не к какому-либо конкретному экземпляру класса. Вы не можете использовать ключевое слово this внутри него, поскольку оно относится к текущему экземпляру. Одним из вариантов будет объявить метод методом экземпляра, удалив ключевое слово static из объявления метода, если действительно логика метода зависит от состояния текущего экземпляра.

Я считаю, что проблема в использовании this внутри метода static будет то, что во время выполнения, если ваш код вызывает статический метод как ClassName.staticMethodName(), среда выполнения не будет иметь ни малейшего представления о том, как решить this в этом контексте.

+1

Как я уже сказал в своем вопросе, я понимаю, почему я получаю ошибку.Я ищу альтернативные методы достижения своей цели :) –

+0

@Teifi, зачем вам 'this' внутри метода. – NINCOMPOOP

+1

Метод конструктора DBAdapter принимает параметр «context», и я не уверен, почему это необходимо. DBAdapter - пример кода. Если вы можете пролить свет, сделайте это! :) –

1

Вы не можете получить доступ к полям или методам внутри статического метода.

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

Так this ключевое слово это относится к экземпляру класса.

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

Ошибка.

+1

Как я уже сказал, я понимаю, почему возникает ошибка. Я ищу альтернативный метод, чтобы избежать этого. Например, как я могу использовать класс DBAdapter с тем, чтобы проходить в текущем «контексте»? –

+0

Вопрос: java :) –

+0

Хорошо, иди за шаблоном дизайна однопользовательского режима. Это ответ в java.But. В Android мне нужен какой-то простой способ, это мое намерение. :) –

2

this относится к текущему экземпляру этого класса. существуют

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

1

Вы обращаетесь к этим в статической функции, которая не является правильным

сделать функцию нестатическим путем удаления статического модификатора, то он будет работать нормально

+0

Но, конечно, каждый раз, когда я хочу вызвать метод, мне нужно создать экземпляр класса? Я ищу решение, которое позволит мне вызвать метод 'addContact', используя только одну строку кода. –

+0

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

-2

это указатель на объект .. в статике контекст у вас нет объекта.

Почему DatabaseActivy является статическим классом? Итак, сделайте нормальный класс и создайте его объект

+0

Указатель - это концепция C++. Вы должны назвать это ссылкой в ​​Java. –

+0

@Birdy Я пытаюсь создать класс, который позволит мне выполнять эти операции с одной строкой кода. Я пытаюсь избежать необходимости создавать экземпляр класса каждый раз, когда я хочу его использовать. –

+0

чем взять одноэлементный узор: http://www.theserverside.de/singleton-pattern-in-java/ – Birdy

0

Вы не можете использовать «это» в статическом контексте, потому что он подразумевает, что у вас есть экземпляр объекта, и статически вы не можете вызывать экземпляры.

Зачем нужен статический класс?

0

Глядя на этот метод

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

Я не думаю, что вы должны использовать статический класс, статическое поле и статический метод вообще.

Просто создайте экземпляр Activity и поработайте с ним. Если вам нужен один объект Activity через всю вашу программу, используйте Singleton Pattern. Предоставляются примеры Lazy и Eager.

, например, хотят инициализации будет:

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

Что такое одноэлементный шаблон? –

+0

добавлена ​​ссылка на мой ответ – Tala

0

Вы сделали свой класс как статический.

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

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