0

I'm struggling to learn java, and I'm attempting to understand how calling functions from one class to another works. I have two classes, that I'll post below. I'm seeing a "Non-static method cannot be referenced from a static context" when I call H2db.addItems() in the ToDo class, and when I call ToDo.menu() in the H2db class. Googling has revealed that it has something to do with having an instance(?) but I'm not sure what that means.

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

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

    }
}

Any help would be awesome, thanks. I know it's just a gap in knowledge, but I can't seem to grasp whatever this concept is called.

Vladimir Marenus
  • 393
  • 2
  • 3
  • 16
  • Where you are declaring the method as static? – Sridhar DD Feb 03 '15 at 11:18
  • possible duplicate of [non-static variable cannot be referenced from a static context](http://stackoverflow.com/questions/2559527/non-static-variable-cannot-be-referenced-from-a-static-context) – Johan Feb 03 '15 at 11:19
  • @Sridhar DD I'm not, that's the thing. If I try to change the method to static, everything else breaks. Is there a way to use it with an instance of ToDo so that it doesn't have to be static, or something like that? Like I said, the concept is a little beyond me. – Vladimir Marenus Feb 03 '15 at 11:19
  • Because `menu()` is not `static` you can't call it this way `ToDo.menu();` you have to create a `ToDo` object, eg: `new ToDo().menu()` – Titus Feb 03 '15 at 11:20
  • @Titus- That worked, but it feels... hacky? Do I really need to declare an instance of H2db in ToDo and an instance of ToDo in H2db? Or is there some deeper problem with how I'm doing things? – Vladimir Marenus Feb 03 '15 at 11:23
  • @Vladimir Marenus is not hacky, that is how OOP works. A possible problem is the fact that you're not closing the resources that you use, you should take a look at [this](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) – Titus Feb 03 '15 at 11:37

3 Answers3

1

I think you are missing the bases of object oriented programming. First of all ask your self: which object the class ToDo represents? Looking at your code it is a GUIManager.

The GUIManager to work properly needs another object able to store data in the db named H2DBManager (currently the class H2db). This means that the GUIManager must instantiate in his constructor a H2DBManager namely h2DBManager and use its normal methods (not static) when needed. When the class H2DBManager has finished a task (i.e. has finished to store something in the method addItems) the control flow returns automatically to the class GUIManager so you never need to call explicitely the GUIManager operations (static or not static) from the class H2DBManager.

Giovanni
  • 203
  • 1
  • 8
  • Thank you- your answer makes a lot of sense, and because it addresses the underlying flaw in my thinking, I select it as the correct answer. – Vladimir Marenus Feb 03 '15 at 11:40
0

It looks like you need only one instance of H2db. In that case you could consider using the singleton pattern, but as it is now you'd quickly get it all to work by simply adding the keyword static in the appropriate places:

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

    public static void connect(){

    public static void addItems() {
Koen
  • 278
  • 1
  • 7
  • That worked for the two functions you mentioned, but didn't seem to help when calling ToDo.menu() from within H2db- if I try to make menu() static, it breaks everything. – Vladimir Marenus Feb 03 '15 at 11:32
  • @Vladimir Marenus If you change `menu()` to `static` you will have to change all the other methods called by `menu()` to `static`. – Titus Feb 03 '15 at 11:34
0

The answer is simple. If you want to call H2db.addItems() that is by class name then your addItems() method in the H2db class must be declared static. Or

you can create an instance (object) of class H2db.

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

When you declare a method or an attribute static. Then it becomes class variable/method. and can be called as H2db.addItems().

If you don't declare a method/ attribute static. Then it becomes instance variable/ method. and can be called as mentioned in the code sample above. that is by instance(object) name.

RehanZahoor
  • 322
  • 2
  • 12
  • Is that considered good practice? I know that's a subjective question, but it just "looks" hack-ish to create an object every time you need to (for example) add an item to a list. Is this required because I'm doing other bad things? Or is it truly the way to do it? – Vladimir Marenus Feb 03 '15 at 11:33
  • That truely depends on the context. If you are creating a class and you decide when designing your classes that some method/ attribute should be class attribute/method then you declare it static. Otherwise you consider it instance variable/method and don't declare it static. For example, constants in a class are declared static as they are used by all the instances(objects) and no change in them is required. – RehanZahoor Feb 03 '15 at 11:37