Hello guys! I'm trying to call a method in main called "buyProduct" which displays all products to the user. I' a getting a NullPointerException though. Here's what I have:

 public static void main(String[] args) {

        OnlineShopping shop = new OnlineShopping();

        ArrayList<Cart> carts = new ArrayList<Cart>();
        ArrayList<Order> orders = new ArrayList<Order>();
        ArrayList<User> users = new ArrayList<User>();
        ArrayList<Product> products = new ArrayList<Product>();

        users.add(new User("Alfred Acosta", "alfred.acosta10@gmail.com", "dlsu1234", "Taft Ave, Manila", "09051234567", 500.00));
        products.add(new Product("Shadow Blade", "User gains invisibility.", 2800.00, 15));
        products.add(new Product("Blink Dagger", "User is able to teleport short distance.", 2250.00, 10));
        products.add(new Product("Healing Salve", "Restores 400 health.", 110.00, 20));
        products.add(new Product("Hand of Midas", "Gives user 190 gold.", 2050.00, 25));

        Scanner sc = new Scanner(System.in);

        System.out.println("1. Log-in. ");
        System.out.println("2. Register. ");
        System.out.print("Input: ");
        int resp1 = sc.nextInt();

        //User choice to 1.) Login or 2.) Register 
        switch(resp1){
            case 1: shop.displayLogin(users);
                break;

            case 2: shop.displayRegistration(users);
                break;

            default: System.out.println("Incorrect input!");    
                break;

        }
        shop.displayUserMenu(users);

    }

        public void displayLogin(ArrayList<User> users){
            Scanner sc = new Scanner(System.in);
            String username = "", password = "";
            System.out.println("-----------------------------");
            System.out.print("Input username: ");
            username = sc.next();

            System.out.print("Input password: ");
            password = sc.next();

            for(int i=0;i<users.size();i++){
                if(users.get(i).getUsername().equals(username) && users.get(i).getPassword().equals(password)){
                    System.out.println("-----------------------------");
                    System.out.println("Welcome back "+users.get(i).getName()+"!");   
                }

                else {
                System.out.println("Incorrect username or password!");
                System.exit(0);
                }        
        }
    }

        public void displayRegistration(ArrayList<User> users){

            Scanner sc = new Scanner(System.in);
            String regName,regUserName, regPassword, regAddress, regContactNo;
            double regDeposit;
            System.out.println("-----------------------------");
            System.out.println("User registration");
            System.out.println("Full name: ");
            regName = sc.nextLine();

            System.out.println("Username: ");
            regUserName = sc.nextLine();

            System.out.println("Password: ");
            regPassword = sc.nextLine();

            System.out.println("Address: ");
            regAddress = sc.nextLine();

            System.out.println("Contact number: ");
            regContactNo = sc.nextLine();

            System.out.println("Intial money deposit: ");
            regDeposit = sc.nextDouble();

            User user = new User(regName,regUserName, regPassword, regAddress, regContactNo, regDeposit);

            for(int i=0;i<users.size();i++){
                if(users.get(i).getName().equals(user.getName()) || users.get(i).getUsername().equals(user.getUsername()) || users.get(i).getContactNo().equals(user.getContactNo()))
                    System.out.println("User exists!");
                else
                    System.out.println("Thank you for registering "+regName+"!");
        }
            users.add(user);
        }

        public void displayUserMenu(ArrayList<User> users){

            Scanner sc = new Scanner(System.in);
            System.out.println("-----------------------------");
            System.out.println("1. Edit Profile");
            System.out.println("2. Deposit Money");
            System.out.println("3. Buy Product");
            System.out.println("4. Remove Product");
            System.out.println("5. Check-out Cart");    
            System.out.print("Input: ");

            int resp = sc.nextInt();

            switch(resp){          
            case 1: 
                users.get(0).displayProfile();
                users.get(0).editProfile();
                break;

            case 2: users.get(0).depositMoney();
                break;

            case 3: users.get(0).buyProduct();

            default: System.out.println("Incorrect input!");    
                break;          
   }            
        }   
        }

And this is my User class:

public class User {

    private String name;
    private String username;
    private String password;
    private String address;
    private String contactNo;
    private double deposit;
    private ArrayList<Cart> cart;
    private ArrayList<Product> products;

    public User(String name, String username, String password, String address, String contactNo, double deposit) {
        this.name = name;
        this.username = username;
        this.password = password;
        this.address = address;
        this.contactNo = contactNo;
        this.deposit = deposit;

    }

    public User() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getContactNo() {
        return contactNo;
    }

    public void setContactNo(String contactNo) {
        this.contactNo = contactNo;
    }

    public double getDeposit() {
        return deposit;
    }

    public void setDeposit(double deposit) {
        this.deposit = deposit;
    }

    public void displayProfile(){

        System.out.println("-----------------------------");
        System.out.println("Full Name: " +name);
        System.out.println("Username: " +username);
        System.out.println("Password: " +password);
        System.out.println("Address: " +address);
        System.out.println("Contact Number: " +contactNo );
        System.out.println("Initial Money Deposit: "+deposit );

    }

    public void editProfile(){
        Scanner sc = new Scanner(System.in);

        System.out.println("-----------------------------");
        System.out.println("Full Name: ");
        this.name = sc.nextLine();

        System.out.println("Password: ");
        this.password = sc.nextLine();

        System.out.println("Address: ");
        this.address = sc.nextLine();

        System.out.println("Contact Number: ");
        this.contactNo = sc.nextLine();

        displayProfile();
    }

    public double depositMoney(){
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter amount to deposit: ");
        double amount = sc.nextFloat();
        this.deposit += amount;

        return deposit;
    }

    public void buyProduct(){
        for(int i=0; i<products.size(); i++)
        products.get(i).getName();
    }

    public void removeProduct(){

    }

    public void checkOut(){

    }   
}

what exactly is the point of this:

for(int i=0;i<users.size();i++){
                if(users.get(i).getName().equals(user.getName()) || users.get(i).getUsername().equals(user.getUsername()) || users.get(i).getContactNo().equals(user.getContactNo()))
                    System.out.println("User exists!");
                else
                    System.out.println("Thank you for registering "+regName+"!");
        }
            users.add(user);

the user is added, no matter whether it already exists or not. Also: use the equals method of User to check this, don't go write it out everywhere you want to check for equality.

It seems to me like you are trying to run buyProduct before you added an element, calling the method on a non-existing User.

Something else that stands out:

case 3: users.get(0).buyProduct();
            default: System.out.println("Incorrect input!");    
                break;  

The way your code is now, each time you (successfully) run buyProduct, you'll print: Incorrect input!

I assume that's not what you need?

For future reference, please be more specific. What is the exact flow you follow (did you already add elements, .... )? What is the exact stacktrace (which line threw the Exception on which variable, ... ) ?

It's information like that we need to be sure of what is going wrong.

I'm sorry if my code is a bit messy. Still kinda new to this.

            for(int i=0;i<users.size();i++){
                if(users.get(i).getName().equals(user.getName()) || users.get(i).getUsername().equals(user.getUsername()) || users.get(i).getContactNo().equals(user.getContactNo()))
                    System.out.println("User exists!");
                else
                    System.out.println("Thank you for registering "+name+"!");
        }
            users.add(user);

With this code, I'm trying to check if the registered user exist. If not, then it adds the newly registered user. Unfortunately, once the user has been registered, I'm not quite sure how access the newly registered user.

            Scanner sc = new Scanner(System.in);
            System.out.println("-----------------------------");
            System.out.println("1. Edit Profile");
            System.out.println("2. Deposit Money");
            System.out.println("3. Buy Product");
            System.out.println("4. Remove Product");
            System.out.println("5. Check-out Cart");    
            System.out.print("Input: ");

            int resp = sc.nextInt();

            switch(resp){          
            case 1: 
                users.get(0).displayProfile(users);
                users.get(0).editProfile(users);
                break;

Which is why I put users.get(0). How can I make it so that I can get display the profile of the newly added user instead of the pre-existing user?

As for this part:

            case 3: {
                for (int i=0; i<products.size();i++){
                    System.out.println("-----------------------------");
                    System.out.println(i+1+".");                    
                    products.get(i).displayProducts(products);
                }
                    }        
                break;

            default: System.out.println("Incorrect input!");    
                break;     

I've edited it earlier. When the user chooses "Buy Product", the program displays all the products with a corresponding number. The user chooses what product they want to buy.

Before editing the code, I was getting a NullException error. It dissappeared when I made some adjustments to my code. My problem now is, how should my buyProduct method look like now with the adjustments I've made? I'm sorry if I'm not making sense; I'm trying to explain the best I can. Thanks!

Which is why I put users.get(0). How can I make it so that I can get display the profile of the newly added user instead of the pre-existing user?

In order to get the 0-indexed element, there still has to be at least one element in the list.

You can try to get the last, instead of the first element. (size - 1 ) => if this equals -1, the list is empty.

With this code, I'm trying to check if the registered user exist. If not, then it adds the newly registered user. Unfortunately, once the user has been registered, I'm not quite sure how access the newly registered user.

Yes, I see that is what you are trying to do. But that's not exactly what you are doing. What you are doing is:
step 1: check whether or not the user already exists in the list
step 2: ignore step 1, and add the user anyway, whether he 's already added before or not.

In order to fix that issue <I'll just use an equals call, as you should, so make sure you have a good implementation of it>:

boolean alreadyAdded = false;
for(int i=0;i<users.size();i++){
                if(users.get(i).equals(user)){
                    System.out.println("User exists!");
                    alreadyAdded = true;
                    break; // no reason to continue iterating, we have our answer
                }
        }
        if ( !alreadyAdded ){
            users.add(user);
        }

You don't want to have the else block, otherwise you'll print "thank you for adding" for each element in the list, except when they're equal. This might end up with an (theoretical) infinite amount of lines "thank you for adding" printed.

If you want to have the last added (assuming you don't sort them)

if ( users.size() != 0 ){
User us = users.get(users.size()-1);
}
// else no users in list

Edited 1 Year Ago by stultuske

Best not to reinvent the wheel. List already has a contains method

boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).

so for clarity and safety...

if (! users.contains(user)) users.add(user);

How can I make it so that I can get display the profile of the newly added user instead of the pre-existing user?

Whether you need to add the user or not, the variable user still refers to the new/current user, so you can use that to display the profile.

Edited 1 Year Ago by JamesCherrill

Hello again! I've edited and tried the code:

            for(int i=0;i<users.size();i++){
                if(!users.contains(user)){
                    users.add(user);
                } 
                else{
                    System.out.println("User exists!");
                    System.exit(0);
                }
            }

But whenever I register a new user, it enters the else statement. Am I doing something wrong?

The loop (line 1) is totally wrong.
First time thru the loop you add the user
Second time thru the loop the user is already in users, so you take the else.

You don't need that loop at all!. Just delete it.

Woops, my bad. I've deleted the for loop already. Just ran the program again and whenever I register a user with the same information, it doesn't enter the else statement.

                if(!users.contains(user))
                    users.add(user);

                else{
                    System.out.println("User exists!");
                    System.exit(0);
                }
            }

the contains method will use the equals method.
If you didn't override it in your User class, it will run the Object version, meaning a referential equality check.
Since they are not the same object, they won't return true with equals, meaning the user will be added anyway.

Make sure to implement your own equals method in the user class (and don't overload the method, override it)

the contains method will use the equals method.

What do you mean?

basically, calling contains can be considered this:

public boolean contains(Object o){
  for ( Object nO : thisList ){
    if ( nO.equals(o) ) return true;
  }
  return false;
}

If your code doesn't have a custom equals method, the basic version, which only tests for referential equality will be used, which doesn't lead to the right result.

Ahhhhh I get it. So if my code needs a custom equals method, should it look like this:

    public boolean contains(ArrayList<User> users){
        for(User user : users){
            if(user.equals(user))
                return true;
        }
        return false;
    }

No no no. That was just a way of explaining how contains works.

It needs to be able to test if any user in the list is the same as the new user. That's where the equals method come in. You need to define an equals method in your User class. This tutorial explains it well.

Ohhhhhh. That was stupid of me lol.

    public boolean equals(User user){
        if(user.equals(user))
            return false;
        else
            return true;
    }

Something like this then?

That will just loop forever calling itself.
You have to read that tutorial properly.

In pseudo code the equals method is going to contain some logic like`:

if (the other's name is the same as this name AND
    other's username is the same as this username AND
    other's contactNo is the same as this contactNo) THEN
        other is the same user as this

The code for that will be something like

if (getName().equals(other.getName() && 
    getUsername().equals(other.getUsername() && 
    getContactNo().equals(other.getContactNo()) 

    return true:
else 
    return false;

There's also some code for other not being a user at all, but have another look at the link I gave you. You can ignore the section on inheritance at the end, but the code immediately before that section is totally relevant.

Edited 1 Year Ago by JamesCherrill

Okay I kinda understand it better now. I have another problem though. I'm confused/stuck on how I should implement my buyProduct method.

            Scanner sc = new Scanner(System.in);
            System.out.println("-----------------------------");
            System.out.println("1. Edit Profile");
            System.out.println("2. Deposit Money");
            System.out.println("3. Buy Product");
            System.out.println("4. Remove Product");
            System.out.println("5. Check-out Cart");    
            System.out.print("Input: ");

            int resp = sc.nextInt();

            switch(resp){          
            case 1: 
                users.get(users.size()-1).displayProfile(users);
                users.get(users.size()-1).editProfile(users);
                break;

            case 2: users.get(0).depositMoney();
                break;

            case 3: {
                for (int i=0; i<products.size();i++){
                    System.out.println("-----------------------------");
                    System.out.println(i+1+".");                    
                    products.get(i).displayProducts(products);
                }               
                    }        
                break;

            default: System.out.println("Incorrect input!");    
                break;          
   }            

When the user selects "Buy Product", the program displays all of the products stored with its corresponding number. The user then choose what product to buy and the quantity they want. The part I'm confused/stuck on is, from the User class, how do I pass the choice of the user between the two classes and store it into their cart? I'm not quite sure how to start coding the buyProduct method. Any suggestions? Thank you!

OK, let's think about it...
What's different between any two "buy product" processes? Only the user.
So we can code it as a method with just one parameter...
void buyProductFor(User u) { ...
in that method we can display the products, get the user's input, update the user's cart, and return.

Alright, I think I've got some sort of idea. I'll code it first. Thank you kind sir!

Edited 1 Year Ago by laguardian: Found a solution

Okay, so I've placed then statement under case 3 under my buyProduct method. I'm getting a NullPointerException though. Also, when I added User user as the parameter for the buyProduct method:

            case 3: users.get(users.size()-1).buyProduct(null);
                break;

But when I code: .buyProduct(user) the compiler says it cannot find symbol.

Here's what I have under buyProduct method now:

    public void buyProduct(User user){
        for (int i=0; i<products.size();i++){
            System.out.println("-----------------------------");
            System.out.println(i+1+".");                    
            products.get(i).displayProducts(products);
    }

I apologize if I'm asking too many questions. I need to finish this program in 2 days lol

With a little tweaking of the code, I was able to have the first part of the buyProduct completed:

    public void buyProduct(ArrayList<Product> products){
        for (int i=0; i<products.size();i++){
            System.out.println("-----------------------------");
            System.out.println(i+1+".");                    
            products.get(i).displayProducts(products);
    }

JamesCherrill, I know you said to use User user as my parameter but I needed to find a way to pass the ArrayList of products to that method.
Here's what I have under case 3:

            case 3: users.get(users.size()-1).buyProduct(products);
                break;

It displays all of the products stored in the list. Is there another way to accomplish this? Or will this be okay?

why don't you put the arraylist as a class variable?

anyway, don't know whether you've noticed this yet:

public boolean equals(User user){
        if(user.equals(user))
            return false;
        else
            return true;
    }

this may be a valid method, but not a valid equals method. for an equals method, as will be used by the contains method, the signature must be:

public boolean equals(Object o)

In your User class just as well, the method must take an argument of the type Object.

If you only have the method as you've written it, the equals method that is inherited will be called (you have an overloaded method, while you need an overridden method).

It would become something like this:

public boolean equals(Object o){
  if ( o == null ){ return false; }
  if ( ! getClass().equals(o.getClass())){
    return false;
  }
  User user = (User)o;
      return this.name.equals(user.getName()) &&                this.userName.equals(user.getUserName()) && this.contactNo.equals(this.getContactNo()));
}

Hello again! I'm trying to figure out how I can addOrders to my list of orders:

    public void addOrder(Product product){
        orders.add(product);

    }

Here's what I coded under buyProduct:

        switch(resp){
            case 1: {
               System.out.print("Quantity: ");
               int quantity = sc.nextInt();
               cart.addOrder(products.get(0));
            }

I'm getting an error in my addOrder. Should I be passing Product product in my addOrder? Because I was thinking in order to add an order, I need the product which I can take from the User class.

Edited 1 Year Ago by laguardian: Something wrong

This question has already been answered. Start a new discussion instead.