-1

I'm working on a project for a Java class, and I can't seem to get past this NullPointerException. The project is a command-line LinkedIn program. One of the aspects I'm implementing is the ability to add a skillset to a user's profile.

I have a LinkedInUser class in which I define a TreeSet to hold these skillsets in the form of Strings entered by the user. I'm using TreeSet, because the assignment requires them to be sorted.

I define the TreeSet in the LinkedInUser class here:

private Set<String> skillsets = new TreeSet<>();

The action the user takes is defined in the AddSkillsetAction class:

String skillset;
    
System.out.println("Enter a skillset to add to your list:");
skillset = scanner.nextLine();

loggedInUser.addSkillset(skillset);
System.out.println(skillset + " has been added to your skillsets.");

And the String they enter is passed to the addSkillSet function in the LinkedInUser class:

public void addSkillset(String skillset) {
    skillsets.add(skillset);
}

I keep getting a NullPointerException on the line:

skillsets.add(skillset);

What am I doing wrong? I've tested every level up to that line. I even tested the TreeSet inside the addSkillset function with this code:

if(skillsets == null) {
   System.out.println("The TreeSet is null.")
}

It's telling me the TreeSet is null. I thought instantiating the Set with:

private Set<String> skillsets = new TreeSet<>();

would actually create an empty TreeSet, instead of it pointing to a null location. Why is my set "skillsets" still pointing to null? What am I doing wrong here?

EDIT: Here are the full classes:

package edu.institution.asn2;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class LinkedInUser extends UserAccount implements Comparable<LinkedInUser>, Serializable {

    private static final long serialVersionUID = 75648957489235739L;
    private String type;
    private List<LinkedInUser> connections = new ArrayList<>(); 
    private Set<String> skillsets = new TreeSet<>();
    
    public LinkedInUser(String username, String password) {
        super(username, password);
    }
    
    @Override
    public void setType(String type) {
        this.type = type;
    }
    
    public String getType() {
        return this.type;
    }
    
    // Add a connection to user's list
    public void addConnection(LinkedInUser user) throws LinkedInException {
        int index = connections.indexOf(user);
        if (index >= 0) {
            throw new LinkedInException("You are already connected with this user.");
        }
        else {
            connections.add(user);
        }
    }
    
    // Remove a connection from the user's connection list
    public void removeConnection(LinkedInUser user) throws LinkedInException {
        int index = connections.indexOf(user);
        if (index < 0) {
            throw new LinkedInException("You are NOT connected to this user.");
        }
        else {
            connections.remove(index);
        }
    }
    
    // Return a copy of the ArrayList of connections
    public List<LinkedInUser> getConnections() {
        ArrayList<LinkedInUser> copy = new ArrayList<>(connections);
        return copy;
    }
    
    // Return the number of connections
    public int getNumberOfConnections() {
        return connections.size();
    }
    
    // Return the skillsets
    public Set<String> getSkillsets(){
        return skillsets;
    }
    
    // Add a skillset
    public void addSkillset(String skillset) {
        skillsets.add(skillset);
    }
    
    // Remove a skillset
    public void removeSkillset (String skillset) {
        if(skillsets.contains(skillset)){
            skillsets.remove(skillset);
        } else {
            System.out.println(skillset + " is not in your skills list.");
        }
    }
    
    // Override the compareTo function
    @Override
    public int compareTo(LinkedInUser user) {
        int i = this.getUsername().compareToIgnoreCase(user.getUsername());
        return i;
    }

}

And the class to add a skillset:

package edu.institution.actions.asn7;

import java.util.Scanner;

import edu.institution.ApplicationHelper;
import edu.institution.UserRepository;
import edu.institution.actions.MenuAction;
import edu.institution.asn2.LinkedInUser;

public class AddSkillsetAction implements MenuAction {

    @Override
    public boolean process(Scanner scanner, UserRepository userRepository, LinkedInUser loggedInUser) {
        String skillset;
        
        System.out.println("Enter a skillset to add to your list:");
        skillset = scanner.nextLine();
        
        loggedInUser.addSkillset(skillset);
        System.out.println(skillset + " has been added to your skillsets.");
        
        ApplicationHelper.incrementSkillsetCount(skillset);
        
        return true;
    }
}

After I run and try to add a skillset, I get this error:

Exception in thread "main" java.lang.NullPointerException
    at edu.institution.asn2.LinkedInUser.addSkillset(LinkedInUser.java:69)
    at edu.institution.actions.asn7.AddSkillsetAction.process(AddSkillsetAction.java:19)
    at edu.institution.ApplicationController.process(ApplicationController.java:61)
    at edu.institution.LinkedInCLI.main(LinkedInCLI.java:39)

LinkedInUser.java:69 is:

    skillsets.add(skillset);
zimmermr
  • 1
  • 2
  • Hi @Zimmermr - where is `loggedInUser` assigned a value - that's possibly what the null pointer exception is from. – Mr R Mar 21 '22 at 01:08
  • loggedInUser is a non-null LinkedInUser passed to the process function. I just added the full code for both functions. – zimmermr Mar 21 '22 at 01:20

1 Answers1

0

By the way… Your naming is confusing. String skillset; should be String skill, and .addSkill not .addSkillset, because you are adding individual skills rather than adding a set.

Clarifying your naming may clarify your code. Notice the singular skill and plural skills naming used in code below.


You did not provide enough details to diagnose the problem. But I can show you some example code based on your descriptions.

Your problem may be related to your not properly instantiating the TreeSet. Notice in this code that you have a choice of at least two places in which to instantiate:

  • On the declaration line of skills.
  • In the constructor. (Code currently commented-out.)

The LinkedInUser class.

package work.basil.linkedin;

import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;

public class LinkedInUser
{
    private String name;
    private NavigableSet < String > skills = new TreeSet <>();

    // Constructor
    public LinkedInUser ( final String name )
    {
        this.name = name;
//        this.skills = new TreeSet <>() ;
    }

    // Modifiers

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

    public void addSkill ( String skill ) { this.skills.add( skill ); }

    // Getters

    public String getName ( ) { return name; }

    public Set < String > getSkills ( ) { return Set.copyOf( this.skills ); }  // Return a unmodifiable copy of the set. (defensive programming)
}

For defensive programming, we return a copy of the set. This unmodifiable copy returned by Set.copyOf has no order. In some implementations, the order may even change arbitrarily for each iterator. If you want to return an ordered NavigableSet instead, do this:

  • Change the return type of the method to NavigableSet.
  • Change the code to pass the instance’s set to the constructor of another set.
public NavigableSet < String > getSkills ( ) { return new TreeSet <>(this.skills ); }

Usage.

LinkedInUser alice = new LinkedInUser( "Alice" );
LinkedInUser bob = new LinkedInUser( "Bob" );

alice.addSkill( "Yodeling" );
alice.addSkill( "Tap Dancing" );
bob.addSkill( "Juggling" );

System.out.println( alice.getName() + " does " + alice.getSkills() );
System.out.println( bob.getName() + " does " + bob.getSkills() );

System.out.println( List.of( alice , bob ) );

When run.

Alice does [Yodeling, Tap Dancing]
Bob does [Juggling]
[LinkedInUser{name='Alice', skills=[Tap Dancing, Yodeling]}, LinkedInUser{name='Bob', skills=[Juggling]}]

You said:

I thought instantiating the Set with:

private Set<String> skillsets = new TreeSet<>();

Yes, that would indeed instantiate a TreeSet object, and store a reference to that set in a variable named skillsets. I expect you are placing that code in the wrong location. Again, look at the two locations I suggested earlier in this Answer: on declaration line, or in constructor.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154