NullPointerException (Java) [duplicate] - java

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

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

Optimized way to create a text menu without creating new objects

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).

String refusing to be stated when it has already been initiated and assigned

I'm trying to take in the user's rock, paper, scissor choice (which is entered as either r, p , or s), but when I try to change and call it, it gives me an error.
Here is my code:
package labs10;
import java.util.Scanner;
import static java.lang.System.*;
public class RPSRunner
{
public static void main(String args[])
{
Scanner kb = new Scanner(System.in);
String full;
String response;
String player = "";
out.print("Select [R,P,S] :: ");
response = kb.next();
if (response.equals("R")) {
full = "Rock";
} else if (response.equals("P")) {
full = "Paper";
} else if (response.equals("S")) {
full = "Scissors";
}
out.println("Player chooses " + full);
RockPaperScissors game = new RockPaperScissors();
game.setPlayers(response);
game.determineWinner();
out.println(game);
}
}
and my error is
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The local variable full may not have been initialized
at labs10.RPSRunner.main(RPSRunner.java:25)
String full;
You declare full with no initial value. If the user types R, P, or S you assign it a value. But what if they type something else? Then full will still be uninitialized. The compiler doesn't like that.
Either assign it a value initially...
String full = null;
...or add a final else clause to handle all other user input.
if (response.equals("R")) {
full = "Rock";
} else if (response.equals("P")) {
full = "Paper";
} else if (response.equals("S")) {
full = "Scissors";
} else {
full = null;
}
Well, if response is neither "R", "P" or "S", full won't be initialized at the point you try to print it with out.println("Player chooses " + full);.
You must assign a default value to it in this case (or throw an exception).

Java - Calling private arraylist from class [duplicate]

This question already has answers here:
Is it possible in Java to access private fields via reflection [duplicate]
(3 answers)
Closed 7 years ago.
My template opens with a menu of options and the user inputs something between 1-3 to select one of the three options.
When the user chooses option 1, it asks them to input a number teamNumber. One must instantiate the class Team, then it writes it to an arraylist.
If there is at least one number in numberList, the user can select option 2. It asks them to input any of the numbers from the arraylist and searches it. If the number they input is found, then you input a String teamMemberFirstName and a char firstInitialLastName. Then it will write the input to a private arraylist located in another class TeamMember.
Once they have input the info in option 1 and 2, they can choose option 3. It allows you to print the list of inputted names based on which team number you put them on.
I am not sure how, in option 3, to call the private arraylist from the TeamMember class teamList. Any guidance on how to proceed with this step? My code is below.
Main class:
public class Main {
public static void main(String[] args) {
int choosing;
Scanner scan = new Scanner(System.in);
String input;
int teamNumber;
boolean stayInLoop;
ArrayList<Team> numberList = new ArrayList<Team>();
do {
stayInLoop = true;
System.out.println("1. Add a new team");
System.out.println("2. Add a new team member");
System.out.println("3. View teams");
input = scan.nextLine();
if (input.equals("1")) {
System.out.println("Enter a team number:");
teamNumber = scan.nextInt();
scan.nextLine();
Team addTeam = new Team(teamNumber);
numberList.add(addTeam);
}
if (input.equals("2")){
boolean foundIt = false;
boolean valid = true;
System.out.println("Team number:");
teamNumber = scan.nextInt();
scan.nextLine();
for (int a = 0; a < numberList.size() && foundIt == false; a++){
Team addTeam = numberList.get(a);
if (addTeam.findTeam() == teamNumber) {
foundIt = true;
System.out.println("Enter first name of team member:");
String teamMemberFirstName = scan.nextLine();
System.out.println("Enter first initial of last name:");
char firstInitialLastName = scan.nextLine().charAt(0);
TeamMember inputTeamMember = new TeamMember(teamMemberFirstName, firstInitialLastName);
inputTeamMember.addMember(inputTeamMember, valid = true);
System.out.println("Success!");
}
}
if (foundIt == false) {
System.out.println("Try again.");
}
}
if (input.equals("3")){
for (int a = 0; a < numberList.size(); a++) {
Team addTeam = numberList.get(a);
//Not sure what to put where there are ????'s - I tried a few ideas and stuff I found online, but nothing worked
//I assume I call the method/class here????
System.out.println("Team: " + addTeam.findTeam() + " Members: " +
"I will put the member called from the arraylist here????");
}
}
}while (stayInLoop == true;)
}}
TeamMember class:
public class TeamMember {
private final String teamMemberFirstName;
private final char firstInitialLastName;
private ArrayList<TeamMember> teamList = new ArrayList<>();
public TeamMember(String teamMemberFirstName, char firstInitialLastName) {
this.teamMemberFirstName = teamMemberFirstName;
this.firstInitialLastName = firstInitialLastName;
}
public int addMember(TeamMember member, boolean valid) {
valid = teamList.add(member);
return teamList.size();
}
}
You cannot directly access private fields from other classes. Either move your list to the Team class or create a getter to retrieve the list.
In a public class, you can return a private object in a public method. This seems like the easiest way in this project. Add a new method to your TeamMember class, and have it return teamList:
//inside your TeamMember class, anywhere after you assign the private variable
public static ArrayList show(){
//the static keyword, in short, will make the method callable without a class instance.
return teamList;
}
Since the TeamMember method show() is now static, you should be able to simply call TeamMember.show() and get the ArrayList.
Important note: In order for this to work, you must make the private arraylist static too. A static object cannot call a non-static object.
This will turn it into private static ArrayList<TeamMember> teamList = new ArrayList<>();
In the Main class, like I said above, simply call TeamMember.show(). You do not need to create an instance.
If you change your teamList to public instead of private your Main class will be able to access the variable. When you make something private in Java you're basically making that instance variable accessible only through the class that it's instantiated in. If you want the variable to be visible to other classes for reference you should make it public
Since the assignment calls for it, you're going to need to define a getter and setter for your 'teamList' variable.
public void setArray(ArrayList newTeamList){
teamList = newTeamList;
}
public ArrayList getArray(){
return teamList;
}
This'll allow you to access the private variable through the methods

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

Categories

Resources