Не можна використовувати "цей" в статичному контексті

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

У мене є клас 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
}

І я створив свій клас для обробки всіх дзвінків до DBA-пакета:

    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); , я отримую таку помилку: Неможливо використати "цей" в статичному контексті .

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

Щоб з'ясувати: Я розумію, чому відбувається помилка. Конструктор класу DBAdapter приймає параметр контекст , і я не знаю, що пройти як параметр контексту, коли я використовую його статично. Я хочу, щоб клас був статичним, тому що я не хочу, щоб я мав інстанцію, коли я хочу його використовувати.

Я думаю, що моє справжнє питання буде "чому SQLiteOpenHelper вимагає контексту?"

1
@MarcoForberg Я рідко використовував цей в C #. Ваш коментар не дуже корисний.
додано Автор Mike Baxter, джерело
@ МаркоФорберг Як я вже сказав; Сума fair просто означає, що я написав правильну суму коду C #. Близько 6 місяців. Це не означає, що я експерт - і не претендував на те, щоб бути одним. Це люди, як ви, які роблять переповнення стек на дуже неприємному веб-сайті.
додано Автор Mike Baxter, джерело
@KlausByskovPedersen Якщо ви правильно прочитали це питання, ви побачите, що я розумію різницю між статичними та нестатичними - це абсолютно елементарно. Я шукаю альтернативні рішення, оскільки я так незнайомий з самим Java.
додано Автор Mike Baxter, джерело
Оскільки це питання було так широко неправильно зрозуміле (моя власна вина, бо я не пояснив мою проблему досить добре) - я створив більш актуальний питання тут. stackoverflow.com/questions/17234451/ …
додано Автор Mike Baxter, джерело
@Teifi він просто вказує на те, що якщо ви зробили достатню кількість кодування, слід знати різницю між методами екземпляра та статичними методами. Оскільки ви явно не знаєте різниці, я пропоную вам взяти 15 хвилин і прочитати про це.
додано Автор Klaus Byskov Pedersen, джерело
@Teifi і саме тому це коментар і немає відповіді. Просто цікаво, тому що я використовую його досить часто. принаймні один раз у кожному класі
додано Автор Marco Forberg, джерело
якщо я не помиляюся, як у C + +, Java не посилається неявно.
додано Автор Infested, джерело

8 Відповіді

Ви визначили метод static тут:

  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.

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

7
додано
Метод конструктора DBAdapter приймає параметр context , і я не знаю, чому це необхідно. DBAdapter - код зразка. Якщо ви можете пролити будь-яке світло, будь ласка! :)
додано Автор Mike Baxter, джерело
Як я вже сказав у своєму запитанні, я розумію, чому я отримую помилку. Я шукаю альтернативні способи досягнення своєї мети :)
додано Автор Mike Baxter, джерело
@Teifi, чому вам потрібен цей всередині методу.
додано Автор NINCOMPOOP, джерело

this refers to the current instance of that class.

Статичні методи та об'єкти існують поза будь-яким інстантом, тому вам не дозволяється використовувати в ньому конкретні дані, наприклад, поточний екземпляр

2
додано

це покажчик на об'єкт .. у статичному контексті у вас немає об'єкта.

чому DatabaseActivy статичний клас? Отже, зробіть нормальний клас і створіть його об'єкт

2
додано
@Birdy Я намагаюся створити клас, який дозволить мені виконувати ці операції з одним рядком коду. Я намагаюся уникати необхідності інсценировать клас кожен раз, коли я хочу використовувати його.
додано Автор Mike Baxter, джерело
ніж взяти єдиний малюнок: theserverside.de/singleton-pattern-in-java
додано Автор Birdy, джерело
Покажчик - це поняття C ++. Ви повинні називати це посиланням в Java.
додано Автор Bruno Brant, джерело

Ви не можете отримати доступ до полів або методів у статичному методі.

 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 з необхідністю передати поточний контекст ?
додано Автор Mike Baxter, джерело
Питання в java :)
додано Автор Mike Baxter, джерело
Дивіться тут для посилання, але я думаю, є спосіб в Android. Див. Андроїд пов'язані аварії :) Якщо не seelink: stackoverflow.com/questions/2062520/ …
додано Автор ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, джерело
Гаразд, ідіть за єдиним дизайном шаблону. Це відповідь на java. Але в Android має бути простий спосіб, це мій намір. :)
додано Автор ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, джерело

Ви отримуєте доступ до цього статичної функції, яка не є правильною

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

1
додано
Але, звичайно, тоді кожен раз, коли я хочу називати метод, мені потрібно буде проаналізувати цей клас? Я шукаю рішення, яке дозволить мені викликати метод addContact , використовуючи лише одну рядок коду.
додано Автор Mike Baxter, джерело
що ви можете зробити, це створити статичний екземпляр у тому ж класі і викликати fucntion, використовуючи цей статичний екземпляр ... не створюйте цей статичний метод
додано Автор Vikalp Jain, джерело

Дивлячись на цей метод

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

Я не думаю, що вам слід взагалі використовувати статичний клас, статичне поле та статичний метод.

Просто створіть екземпляр діяльності та працюйте з ним. Якщо вам потрібен один об'єкт активності через всю вашу програму, то використовуйте Pattern Singleton . Приклади екземплярів Lazy and 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
додано
Що таке одиночна картина?
додано Автор Mike Baxter, джерело
додала посилання на мою відповідь
додано Автор 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();
}
0
додано
ІТ КПІ - Java
ІТ КПІ - Java
436 учасників

android_jobs_ua
android_jobs_ua
120 учасників

Публикуем вакансии и запросы на поиск работы по направлению Android. Здесь всё: full-time, part-time, remote и разовые подработки.

Mobile Dev Jobs UA
Mobile Dev Jobs UA
20 учасників

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin, RN и т.д.