2015-02-03 3 views
0

Я изо всех сил пытаюсь изучить Java, и я пытаюсь понять, как работают функции вызова из одного класса в другой. У меня есть два класса, которые я опубликую ниже. Я вижу, что «Нестатический метод не может ссылаться на статический контекст», когда я вызываю H2db.addItems() в классе ToDo, и когда я вызываю ToDo.menu() в классе H2db. Googling показал, что это как-то связано с наличием экземпляра (?), Но я не уверен, что это значит.Как статические функции и экземпляры работают вместе в этом случае?

Класс ToDo:

package com.company; 


import java.io.*; 
import java.lang.reflect.Method; 
import java.sql.*; 
import java.util.ArrayList; 
import java.util.Scanner; 

public class ToDo { 
    //BufferedReader inputread = new BufferedReader(new InputStreamReader(System.in)); 
    Scanner inputread = new Scanner(System.in); 
    ArrayList<String> toDoList = new ArrayList<String>(); 


    public void menu() { 
     clearConsole(); 
     System.out.println("Welcome to the To-Do program."); 
     System.out.println(); 
     System.out.println(); 
     System.out.println("Please select an option from the following menu, using the number.:"); 
     System.out.println("1- View To-Do List"); 
     System.out.println("2- Add Item To List"); 
     System.out.println("3- Remove Item From List"); 
     System.out.println("4- Save List"); 
     System.out.println("5- Load List"); 

     int userinput = inputread.nextInt(); 

     switch (userinput) { 
      case 1: 
       clearConsole(); 
       displayList(true); 
       menu(); 
       break; 
      case 2: 
       clearConsole(); 
       H2db.addItems(); 
       break; 
      case 3: 
       clearConsole(); 
       deleteItem(); 
       break; 
      case 4: 
       clearConsole(); 
       try { 
        saveList(); 
       } 
       catch(IOException e){ 
        return; 
       }; 

      case 5: 
       clearConsole(); 
       try { 
        loadList(); 
       } 
       catch(IOException e){ 
        return; 
       }; 

     } 
    } 

    public void clearConsole() { 
     for (int i = 0; i < 25; i++) { 
      System.out.println(); 
     } 
    } 


    public void addItem() { 
     System.out.println("Please type the item to add to the To-Do List"); 
     //The skip gets over the leftover newline character 
     inputread.skip("\n"); 
     String newItem = inputread.nextLine(); 
     toDoList.add(newItem); 
     System.out.println("Your item has been added! Type any key and press Enter to continue"); 
     String discardMe = inputread.next(); 
     menu(); 
    } 

    public void displayList(boolean finish) { 

     if (toDoList.isEmpty()) { 
      System.out.println("Add an activity."); 

     } else { 
      for (String listItem: toDoList) { 
       System.out.println(listItem); 
      } 
     } 
     if (finish) { 
     System.out.println(); 
     System.out.println("This is your list. Type any key and press Enter to continue"); 
     String discardMe = inputread.next(); 
     } 

    } 

    public void deleteItem() { 
     if (toDoList.isEmpty()) { 
      System.out.println("For fuck's sake, add an activity."); 
     } else { 
      System.out.println("Please choose the number of the line you want to delete:"); 
      displayList(false); 
      int userinput = inputread.nextInt(); 
      int listPos = userinput - 1; 
      toDoList.remove(listPos); 
      System.out.println("That item has been deleted. Type any key and press Enter to continue."); 
      String discardMe = inputread.next(); 
     } 
     menu(); 
    } 

    public void saveList() throws IOException { 
     System.out.println("Saving list..."); 
     PrintWriter writer = new PrintWriter("list.txt", "UTF-8"); 
     for (String listItem : toDoList) { 
      writer.println(listItem); 
     } 
     writer.close(); 
     System.out.println("List saved! Type any key and press Enter to continue"); 
     String discardMe = inputread.next(); 
     menu(); 

    } 

    public void loadList() throws IOException { 
     System.out.println("Loading list..."); 

     File loadFile = new File("list.txt"); 
     Scanner scanner = new Scanner(loadFile); 
     while (scanner.hasNext()) { 
      String item = scanner.nextLine(); 
      toDoList.add(item); 
     } 
     System.out.println("List loaded! Type any key and press Enter to continue"); 
     String discardMe = inputread.next(); 
     menu(); 
     scanner.close(); 
    } 
} 

Класс H2db:

package com.company; 

import java.sql.*; 
import java.util.ArrayList; 
import java.util.Scanner; 


public class H2db { 
    Scanner inputread = new Scanner(System.in); 
    ArrayList<String> toDoList = new ArrayList<String>(); 

    public void connect(){ 

     try { 
      Class.forName("org.h2.Driver"); 
      Connection conn = DriverManager.getConnection("jdbc:h2:~/toDo", "user", ""); 
      Statement stat = conn.createStatement(); 

      stat.execute("CREATE TABLE IF NOT EXIST 'todo'(id int NOT NULL AUTO_INCREMENT primary key, item varchar(255))"); 
     } 
     catch(Exception e) { 
      System.out.println(e.getMessage()); 
     } 

    } 

    public void addItems() { 
     PreparedStatement addstat; 

     try { 
      Class.forName("org.h2.Driver"); 
      Connection conn = DriverManager.getConnection("jdbc:h2:~/toDo", "user", ""); 

      System.out.println("Please type the item to add to the To-Do List"); 
      inputread.skip("\n"); 
      String newItem = inputread.nextLine(); 
      addstat = conn.prepareStatement("INSERT INTO toDo (item)" +"VALUES (?)"); 
      addstat.setString(1, newItem); 
      addstat.executeUpdate(); 

      System.out.println("Your item has been added! Type any key and press Enter to continue"); 
      String discardMe = inputread.next(); 
      ToDo.menu(); 
     } 
     catch(Exception e) { 
      System.out.println(e.getMessage()); 
     } 

    } 
} 

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

+0

Где вы объявляете метод как статический? –

+0

Возможный дубликат [нестатическая переменная не может ссылаться на статический контекст] (http://stackoverflow.com/questions/2559527/non-static-variable-cannot-be-referenced-from-a-static-context) – Johan

+0

@ Сридхар Д.Д. Я не, вот что. Если я попытаюсь изменить метод на статический, все остальное сломается. Есть ли способ использовать его с экземпляром ToDo, чтобы он не был статическим или что-то в этом роде? Как я уже сказал, концепция немного выше меня. –

ответ

1

Я думаю, что вам не хватает оснований объектно-ориентированного программирования. Прежде всего спросите себя: какой объект представляет класс ToDo? Глядя на ваш код, это GUIManager.

GUIManager для правильной работы нуждается в другом объекте, способном хранить данные в db с именем H2DBManager (в настоящее время класс H2db). Это означает, что GUIManager должен создать в своем конструкторе экземпляр H2DBManager, а именно h2DBManager, и при необходимости использовать его обычные методы (а не статические). Когда класс H2DBManager завершил задачу (т. Е. Завершил сохранение чего-либо в методе addItems), поток управления автоматически возвращается в класс GUIManager, поэтому вам не нужно явно вызывать операции GUIManager (статические или нестатические) из класса H2DBManager.

+0

Спасибо, ваш ответ имеет большой смысл, и поскольку он затрагивает основной недостаток в моих мыслях, я выбираю его как правильный ответ. –

0

Похоже, вам нужен только один экземпляр H2db. В этом случае вы могли бы рассмотреть вопрос об использовании одноплодных шаблона, но теперь вы быстро получить все эти работать, просто добавив ключевое слово static в соответствующих местах:

static Scanner inputread = new Scanner(System.in); 
    static ArrayList<String> toDoList = new ArrayList<String>(); 

    public static void connect(){ 

    public static void addItems() { 
+0

Это работало для двух функций, о которых вы упомянули, но, похоже, не помогло при вызове ToDo.menu() из H2db - если я попытаюсь сделать static() static (static), это сломает все. –

+0

@ Vladimir Marenus Если вы измените 'menu()' на 'static', вам придется изменить все остальные методы, называемые' menu() '' static'. – Titus

0

Ответ прост. Если вы хотите вызвать H2db.addItems(), который по имени класса, то ваш метод addItems() в классе H2db должен быть объявлен статическим. Или

вы можете создать экземпляр (объект) класса H2db.

H2db myObject = new H2db(); 
myObject.addItems(); 

При объявлении метода или атрибута static. Затем он становится переменной класса/методом. и его можно назвать H2db.addItems().

Если вы не объявите метод/атрибут static. Затем он становится экземпляром переменной/методом. и может быть вызван, как указано в приведенном выше примере кода. это имя экземпляра (объекта).

+0

Это считается хорошей практикой? Я знаю, что это субъективный вопрос, но он просто «смотрит» на hack-ish для создания объекта каждый раз, когда вам нужно (например) добавить элемент в список. Это необходимо, потому что я делаю другие плохие вещи? Или это действительно способ сделать это? –

+0

Это действительно зависит от контекста. Если вы создаете класс и решаете при разработке классов, что некоторый метод/атрибут должен быть атрибутом класса/методом, вы объявляете его статичным. В противном случае вы считаете его переменной/методом экземпляра и не объявляете его статичным. Например, константы в классе объявляются статическими, поскольку они используются всеми экземплярами (объектами), и никаких изменений в них не требуется. – RehanZahoor

Смежные вопросы