Optimized way to create a text menu without creating new objects - java

I have a small program with a text based user menu. A switch case is doing the input validation for me, because the user only enters integers which I validate.
The menu looks like this:
----------------------
(1) Manage articles
(2) Manage customers
(3) Close
----------------------
Please enter your number:
This menu is created through an extra method.
When I enter 1, I call another method which contains another do-while loop, this time validating the article menu and so on. The second menu looks like this:
Manage articles
----------------------
(1) Show
(2) Add
(3) Change
(4) Delete
(5) Back
----------------------
Please enter your number:
But to switch back to the previous menu, I always create a new instance of my class and call the first method to show the first menu.
The result is: when I switch many times between the menus, I always create a new instance of my program.
I think there are better ways to do such a multiple-layer-reading and like to know how to perform better here.
Update:
package articlemanagement.menu;
import articlemanagement.model.Artikel;
import articlemanagement.verwaltung.ArticleManagement;
import java.util.LinkedList;
import java.util.Random;
import java.util.Scanner;
public class UserInterface {
private ArticleManagement articleManagement;
private UserInterface() {
this.articleManagement = new ArticleManagement();
}
public static void main(String[] args) {
UserInterface userInterface = new UserInterface();
userInterface.showDefaultInterface(userInterface);
System.out.println("See you next time!");
}
private void showDefaultInterface(UserInterface userInterface) {
Scanner scanner = new Scanner(System.in);
int input = 0;
do {
System.out.println("Welcome");
System.out.println("----------------------");
System.out.println("(1) Articles");
System.out.println("(2) Customers");
System.out.println("(3) Shop");
System.out.println("(4) End");
System.out.println("----------------------");
System.out.print("Please enter a number:");
input = scanner.nextInt();
switch (input) {
case 1:
userInterface.showArtikelInterface(userInterface);
break;
case 2:
System.out.println("todo");
break;
case 3:
System.out.println("todo");
break;
case 4:
System.out.println("Bye");
break;
default:
break;
}
} while (input != 4);
System.exit(1);
}
/**
* Show overview
*/
private void showArtikelInterface(UserInterface userInterface) {
Scanner scanner = new Scanner(System.in);
do {
System.out.println("Manage your articles");
System.out.println("----------------------");
System.out.println("(1) Show");
System.out.println("(2) Add");
System.out.println("(3) Modify");
System.out.println("(4) Delete");
System.out.println("(5) Go Back");
System.out.println("----------------------");
System.out.print("Bitte geben Sie eine Zahl für Ihr Menü ein:");
int input = scanner.nextInt();
switch (input) {
case 1: // show
zeigeArtikel();
break;
case 2: // add
System.out.println("todo");
break;
case 3: // modify
System.out.println("todo");
break;
case 4: // delete
System.out.println("todo");
break;
case 5: // back
System.out.println("Going back...");
// bad style?
userInterface.showDefaultInterface(userInterface);
break;
default:
break;
}
} while (scanner.nextInt() != 5);
}
}

But to switch back to the previous menu, I always create a new instance of my class and call the first method to show the first menu.
You're not creating a new instance every time. You created exactly one instance in main and that's it. With that being said, there are some odd design choices that you made.
Design
You have a UserInterface class which has the ability to print some text depending on the context. Two general designs would be:
Static approach (utility/handler/manager...)
public class UserInterface {
public static void main(String[] args) {
UserInterface.showDefaultInterface();
}
private static void showDefaultInterface() {
// ...
showArtikelInterface();
// ...
}
private static void showArtikelInterface() {
// ...
showDefaultInterface();
// ...
}
}
or you can create a type to represent the context if you need more flexibility (doesn't seem so):
interface Context {
void show();
}
and
class UserInterface {
static void showContext(Context context) { context.show(); }
}
Instance approach
public class UserInterface {
public static void main(String[] args) {
UserInterface userInterface = new UserInterface();
userInterface.showDefaultInterface();
}
private void showDefaultInterface() {
// ...
showArtikelInterface();
// ...
}
private void showArtikelInterface() {
// ...
showDefaultInterface();
// ...
}
}
But you have a mix which doesn't make sense in which you pass the instance to itself:
UserInterface userInterface = new UserInterface();
userInterface.showDefaultInterface(userInterface);
and same with the showArtikelInterface method. An instance has access to itself, so no reason to do this in your case (a case where an instance method would take instances of its type can be in data structures where you have chains/links/nodes...).
Loop condition
Another odd thing is your while conditions
while (scanner.nextInt() != 5); // and the other one
where it should be > 5 and < 1. Though I guess this is just your current test code.
Shared resources
Last thing is that you can share the Scanner object between methods instead of creating one each time. Promote it to a field (static or not depending on your design choice).

Related

Instantiated object use to display stored information in another class

I instantiated a class so that the information that I will input is stored into it. But I having difficulty in displaying the information that is stored. When I compiled it will say that I havent initialized the variable.
public class REPORTS
{
public static void main(String[]args)
{
Scanner input = new Scanner(System.in);
int x=choices();
STUDENT stud;
EQUIPMENT equip;
RESERVATION reserve;
switch(x)
{
case 1:
{
// Code here for input
stud = new STUDENT(Studid,Studname,Studcourse,Studlevel);
break;
}
case 2:
{
// Code also here for input
equip = new EQUIPMENT(eqpmntid,qty,eqpmntname);
break;
}
case 3:
{
// Same goes for here input
reserve = new RESERVATION(studentid,equipid1,reservationdate,returndate);
break;
}
case 4:
{
stud.display(); // error here variable might not have been initialized
break;
}
case 5:
{
equip.display(); // same goes here
break;
}
case 6:
{
reserve.display(); // and also here
break;
}
}
Here is the detailed error message:
It seems that you have to change your program behavior; There is one possible syntactic way of casting a new Object to Student at beginning of your code but you will probably get a runtime error. To change the behavior you can initialize objects with arguments that are null or empty or dummy objects based on the arguments that your constructor get and then Set the fields to appropriate values in related switch case; For example your first lines should look like this:
Student stud = new Student("", Null, dummyObject);

NullPointerException (Java) [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I've tried looking at posts on this issue but am still having some trouble with this error in my code. So in the fourth line, I create an instance variable called SongDatabase to access the SongDatabase class. But when I get down to the line, SongDatabase.addNewSong(); under case 1, I get a java.lang.NullPointerException: null error.
Interface class:
public class Interface
{
Scanner console = new Scanner(System.in);
private SongDatabase SongDatabase;
public static void main(String[] args) {
Interface intFace = new Interface();
intFace.run();
}
private void run() {
switch (userInput) {
case 1:
SongDatabase.addNewSong();
break;
case 2:
SongDatabase.removeSong();
break;
case 3:
SongDatabase.sortSongs();
break;
default:
System.out.println("Please enter a valid number.");
break;
}
}
SongDatabase class:
public class SongDatabase {
Scanner console = new Scanner(System.in);
private Song song1, song2, song3, song4;
public void addNewSong() {
if (song1 == null) {
song1 = getFromUser();
}
else if (song2 == null) {
song2 = getFromUser();
}
else if (song3 == null) {
song3 = getFromUser();
}
else if (song4 == null) {
song4 = getFromUser();
}
else {
System.out.println("The database is currently full. Please delete a song before adding a new one.");
}
}
I've stepped through the debugger and I know that the instance variable, SongDatabase = null, which is probably causing the error? I previously had a line
SongDatabase SongDatabase = new SongDatabase();
SongDatabase.addNewSong();
instead, but I realised this was creating a new SongDatabase object everytime and wiping what I had stored in there so I had to change it. I'd really appreciate a solution because I have no clue, thanks!
You shouldn't give your instance field the same name as the class because that causes Variable shadowing - Wikipedia says (in part) variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope. At the level of identifiers (names, rather than variables), this is known as name masking. And you could define the reference at declaration like
private SongDatabase songDatabase = new SongDatabase();
Then something like
private void run() {
switch (userInput) {
case 1:
songDatabase.addNewSong();
break;
case 2:
songDatabase.removeSong();
break;
case 3:
songDatabase.sortSongs();
break;
default:
System.out.println("Please enter a valid number.");
break;
}
}
It is null because it is never being instantiated. Create SongDatabase in your main method to get around your original problem:
public static void main(String[] args) {
Interface intFace = new Interface();
SongDatabase = new SongDatabase();
SongDatabase.addNewSong();
intFace.run();
}
To avoid confusion name your variables starting with a lower case letter.
private SongDatabase songDatabase;
This way it is clear that when you write songDatabase you mean the instance and when you write SongDatabase you are referring to the class.
You need to instantiate the instance of the class before you can use it. It seems that you are already aware of this from the question but it is just a matter of where to do it. For a quick fix you can instantiate it at the point where you declare the variable. Later you can look into a better design. Therefore:
private SongDatabase songDatabase = new SongDatabase();
You were getting the NullPointerException as the class variable for SongDatabase have never been instantiated. To initialize the class variables we can use constructor, please see the code details below. Also to avoid the naming confusion we can use this keyword to have better code readability.
import java.util.Scanner;
public class Interface
{
private Scanner console;
private SongDatabase songDatabase;
public Interface()
{
this.songDatabase = new SongDatabase(); // Initialize the SongDatabase class and .
this.console = new Scanner(System.in); // Initialize the console reference with scanner class.
}
public static void main(String[] args)
{
Interface intFace = new Interface();
intFace.run();
}
private void run()
{
System.out.println("1. Add Song");
System.out.println("2. Remove Song");
System.out.println("3. Sort Song");
System.out.print("Please Enter Choice: ");
int userInput = console.nextInt(); // Get the data from user input
switch (userInput)
{
case 1:
this.songDatabase.addNewSong();
break;
case 2:
this.songDatabase.removeSong();
break;
case 3:
this.songDatabase.sortSongs();
break;
default:
System.out.println("Please enter a valid number.");
break;
}
}
}

Cannot make static reference to the non-static method printMenuGetSelection() from the type SpecialAssignment1 [duplicate]

This question already has answers here:
Cannot make a static reference to the non-static method
(8 answers)
Closed 8 years ago.
Pre Edit: The problem is when I mark it as static, so
public static int printMenuGetSelection()
it gives me the message
This Static method cannot hide the instance method from AMenu
I'm writing a Java program that reads files and gives the user multiple options for displaying things about the file. I'm currently writing a menu interface that implements an actual Interface and makes the program easier to use. However, I'm getting an exception when I try to call the menu method in my main method. The error is on the one active line in the main method where I call printMenuGetSelection(), and it says
Cannot make static reference to the non-static method printMenuGetSelection() from the type SpecialAssignment1
How do I fix this bug? here is my program:
import java.util.*;
import java.io.*;
import java.text.*;
public class SpecialAssignment1 implements AMenu {
public static void main(String[] args) throws FileNotFoundException{
printMenuGetSelection();
/*System.out.println(RewardCustomer("transactions1.dat")); //CURRENTLY DISPLAYING TOP 6, DOESN'T WORK WITH TIES OR TOPN < lines
ProcessTransactionsFile("transactions2.dat", 52);*/
}
public int printMenuGetSelection() throws FileNotFoundException{
boolean runProgram = true;
Scanner s = new Scanner(System.in);
printStartMenu();
String startMenuSelection = s.next();
while(runProgram){
if(startMenuSelection.equals("1")){
startMenu1();
} else if(startMenuSelection.equals("2")){
startMenu2();
} else if(startMenuSelection.equals("3")){
startMenu3();
} else if(startMenuSelection.equals("4")){
startMenu4();
} else if(startMenuSelection.equals("5")){
runProgram = false;
} else {
System.out.println("***Selection Invalid!***");
}
}
return 1;
}
public static void printStartMenu(){
System.out.println("**********************************************************");
System.out.println("Main Menu...");
System.out.println(" (1) RewardCustomers");
System.out.println(" (2) ProcessTransactionFiles");
System.out.println(" (3) TopCustomers");
System.out.println(" (4) QueryStatsFile");
System.out.println(" (5) Quit");
System.out.println(" Enter a valid selection: ");
}
public static void startMenu1() throws FileNotFoundException{
boolean runMenu1 = true;
while(runMenu1){
Scanner s = new Scanner(System.in);
System.out.println("Reward Customers Menu...");
System.out.println(" (1) Use transactions1.dat");
System.out.println(" (2) Use transactions2.dat");
System.out.println(" (3) Quit");
System.out.println(" Enter a valid selection: ");
String menu1Selection = s.next();
if(menu1Selection.equals("1")){
System.out.println(RewardCustomer("transactions1.dat"));
} else if(menu1Selection.equals("2")){
System.out.println(RewardCustomer("transactions2.dat"));
} else if(menu1Selection.equals("3")){
runMenu1 = false;
} else {
System.out.println("***Selection Invalid!***");
}
}
}
public static void startMenu2(){
boolean runMenu2 = true;
while(runMenu2){
Scanner s = new Scanner(System.in);
System.out.println("Process Transaction Files Menu...");
System.out.println(" (1) Create transactions2.dat file");
System.out.println(" (2) Display transactions1.dat");
System.out.println(" (3) Display transactions2.dat");
System.out.println(" (4) Query transactions1.dat");
System.out.println(" (5) Query transactions2.dat");
System.out.println(" (6) Quit");
System.out.println(" Enter a valid selection: 4");
String menu2Selection = s.next();
if(menu2Selection.equals("1")){
}
}
}
public static void startMenu3(){
}
public static void startMenu4(){
}
I removed the code not pertaining to the question to make it easier to read, if it's needed I'll put it in. Also, here is the AMenu Interface. Please do not suggest any other changes to my program. If you think it's dumb to have the menu as an Implemented Interface, I 100% agree with you but that's the requirement. For reference, here is the AMenu Interface:
import java.io.FileNotFoundException;
public interface AMenu {
/**
* Prints a menu with selections and logic to return a valid selection.
* #return the selected item
*/
abstract int printMenuGetSelection() throws FileNotFoundException;
/**
* #return the numberOfMenuItems
*/
abstract int getNumberOfMenuItems();
}
Since printMenuGetSelection() is non static, you cannot call it from within the static method main() unless you create an instance of SpecialAssignment1 and call the method on that object.
you need to create an instance of your SpecialAssignment1 then call the method from that, as abstract requires an object.
As other people have said, you need to create an instance of SpecialAssignment1, then call printMenuSelection() on it. Part of what's making this confusing though is that you've stuck the main method inside the menu interface class. This whole thing would make more sense if you had a class SpecialAssignment1 with just the main method and a separate MenuGenerator class with all the menu generation stuff.

Java Switch menu error and how to call a method from another class

Hi Im currently learning Java and Im doing an assignment where I need to *create a Menu that calls several methods. I have 3 classes (Contacto,Agenda and Principal). My assignment is trying to evaluate Constructors and Arrays and some other basic theory.
My menu error is: Principal.java:34: error: cannot find symbol while(opcion!=4).*
I already check and my variable "opcion" is declared.
public class Principal{
private static void imprimeMenu(){
Scanner input = new Scanner(System.in);
String mainMenu = ("Choose an option from the menu: \n"
+ "1. Add contact\n"
+ "2. Find contact\n"
+ "3. Search contact\n"
+ "4. Exit");
do{
System.out.println(mainMenu);
int opcion = input.nextInt();
switch(opcion){
case 1:
break;
case 2:
System.out.println("Search");
break;
case 3:
System.out.println("Erase");
break;
default:
System.out.println("Command not recognize");
break;
}
}
while(opcion!=4);
}
public static void main(String[] args){
imprimeMenu();
}
}
And inside the my cases I need to call 3 methods (Add, Search and Erase contacts) that are inside a class called Agenda. The 3 methods are void and receive a parameter. I tried but I get an error where it says I need some parameters:
case 1:
Agenda.addContacto(); and also tried Agenda.addContacto(contacto);
My Agenda class looks like this
public class Agenda{
private Contacto [] contactos;
private int numContactos;
public Agenda(){
this.contactos = new Contacto[10];
this.numContactos = 0;
}
public Agenda(int x){
this.contactos = new Contacto[x];
this.numContactos = 0;
}
public void addContact(Contacto contact){
if(numContactos<contactos.length){
this.contactos [numContactos] = contact;
numContactos+=1;
}
}
Your problem is that opcion is defined inside the loop, so it's scope ends before the closing while.
Move the definition outside the loop to fix the problem:
int opcion = 0;
do{
System.out.println(mainMenu);
opcion = input.nextInt();
switch(opcion){
case 1:
break;
case 2:
System.out.println("Search");
break;
case 3:
System.out.println("Erase");
break;
default:
System.out.println("Command not recognize");
break;
}
} while(opcion!=4);
The correct call of Agenda.addContacto method is indeed Agenda.addContacto(contacto). You need to make sure that contacto is set to an instance of Contacto object before making the call.
You have 2 issues with these programme
1.You need to declare option variable before the while loop.
2.If you want to call Agenda.anyMethod() you need to create an instance/object of the class otherwise you can declare the class Agenda as static.then you can directly call the method as
Agenda.addContacto();

Make Main Method restart/refresh

My code so far:
import java.util.*;
import java.util.Scanner.*;
public class Project{ // The Main Method
public static void main(String [] args){ // Creates the Main Method
System.out.println("Name a Method (Stability, efficiency ..)"); // Asks the user to select a method
Scanner scan = new Scanner(System.in); // Creates the Scanner
String splash = scan.nextLine(); // Transitions the user to the next line after choosing a method
if(splash.equals("efficiency")) // If users chooses Efficiency then it goes to the Efficiency method
{
efficiency(); // Calls the Efficiency method
}
if(splash.equals("Stability")) // If user chooses Stability then it goes to the Stability Method
{
stable(); // Calls the Stability method
}
else // What happens if the input wasnt recognized
{
System.out.println("I don't recognize this"); // what happens if an irrelevant method is chosen
}
}
}
How would I make it so that instead of:
else // What happens if the input wasnt recognized
{
System.out.println("I don't recognize this"); // what happens if an irrelevant method is chosen
}
It will refresh or restart the main method?
Wrap your code in a while loop which you leave when the user chooses the exit command:
public static void main(String [] args){
while (true) {
System.out.println("Name a Method (Stability, efficiency ..)");
Scanner scan = new Scanner(System.in);
String splash = scan.nextLine();
if (splash.equals("exit")) {
break;
} // else if (splash.equals("efficiency")) ...
}
}

Categories

Resources