当我尝试添加字符串时,为什么 Java 中的 TreeSet 会出现空指针异常?

发布于 2025-01-15 15:22:12 字数 5126 浏览 1 评论 0原文

我正在开发一个 Java 类项目,但我似乎无法克服这个 NullPointerException。该项目是一个命令行 LinkedIn 程序。我正在实现的方面之一是能够将技能组添加到用户的个人资料中。

我有一个 LinkedInUser 类,其中定义了一个 TreeSet,以用户输入的字符串形式保存这些技能集。我使用 TreeSet,因为作业要求对它们进行排序。

我在 LinkedInUser 类中定义了 TreeSet:

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

用户采取的操作在 AddSkillsetAction 类中定义:

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

他们输入的字符串被传递到 LinkedInUser 类中的 addSkillSet 函数:

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

我不断收到 NullPointerException:

skillsets.add(skillset);

我是什么做错了吗?我已经测试了直到该线的每个级别。我什至使用以下代码测试了 addSkillset 函数内的 TreeSet:

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

它告诉我 TreeSet 为空。我认为用:实例化 Set

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

实际上会创建一个空的 TreeSet,而不是指向空位置。为什么我设置的“技能组”仍然指向空?我在这里做错了什么?

编辑: 以下是完整的类:

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

}

以及添加技能组的类:

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

在我运行并尝试添加技能组后,出现此错误:

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 是:

    skillsets.add(skillset);

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自由范儿 2025-01-22 15:22:12

顺便说一句……你的命名很混乱。 String Skillset; 应该是 String Skill,并且 .addSkill 而不是 .addSkillset,因为您要添加 个人技能而不是添加一套技能。

澄清你的命名可能会澄清你的代码。请注意下面代码中使用的单数 skill 和复数 skills 命名。


您没有提供足够的详细信息来诊断问题。但我可以根据您的描述向您展示一些示例代码。

您的问题可能与您没有正确实例化 TreeSet 有关。请注意,在此代码中,您至少可以选择两个位置来实例化:

  • skills 的声明行上。
  • 在构造函数中。 (代码当前已被注释掉。)

LinkedInUser 类。

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

对于防御性编程,我们返回该集合的副本。 Set.copyOf 返回的这个不可修改的副本没有顺序。在一些实现中,每个迭代器的顺序甚至可以任意改变。如果您想返回有序的 NavigableSet,请执行以下操作:

  • 将方法的返回类型更改为 NavigableSet
  • 更改代码以将实例的集合传递给另一个集合的构造函数。
public NavigableSet < String > getSkills ( ) { return new TreeSet <>(this.skills ); }

用法。

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

运行时。

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

你说:

我想用以下方法实例化集合:

私有集;技能集 = new TreeSet<>();

是的,这确实会实例化一个 TreeSet 对象,并将对该集合的引用存储在名为 skillsets 的变量中。我希望您将该代码放置在错误的位置。再次查看我之前在本答案中建议的两个位置:在声明行或构造函数中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文