【问题标题】:NullPointerException (Java) [duplicate]NullPointerException(Java)[重复]
【发布时间】:2015-05-04 00:57:58
【问题描述】:

我已尝试查看有关此问题的帖子,但我的代码中的此错误仍然存​​在一些问题。所以在第四行,我创建了一个名为SongDatabase 的实例变量来访问SongDatabase 类。但是当我下线时,case 1 下的SongDatabase.addNewSong();,我得到一个 java.lang.NullPointerException: null 错误。

接口类:

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

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

我已经通过调试器,我知道实例变量 SongDatabase = null,这可能是导致错误的原因?我之前有一条线

SongDatabase SongDatabase = new SongDatabase();
SongDatabase.addNewSong();

相反,但我意识到这是每次都创建一个新的 SongDatabase 对象并擦除我存储在其中的内容,因此我必须对其进行更改。我真的很感激一个解决方案,因为我不知道,谢谢!

【问题讨论】:

  • 构造函数主要用于初始化类字段。所以希望你以后不会错过这部分,你可以在构造函数中通过创建一个变量来实际初始化变量。
  • 对于那些使用接口的人来说,你不应该将类命名为“接口”,这只会让人感到困惑

标签: java variables methods null instance


【解决方案1】:

您不应该为您的实例字段提供与类相同的名称,因为这会导致 Variable shadowing - Wikipedia 说(部分)变量阴影在变量发生时发生在某个范围内(决策块、方法或内部类)声明的变量与在外部范围内声明的变量具有相同的名称。在标识符(名称,而不是变量)级别,这被称为name masking。您可以在声明中定义引用,例如

private SongDatabase songDatabase = new SongDatabase();

然后类似

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

【讨论】:

  • “你不应该……”?你不应该在没有尝试解释原因的情况下给出这样的建议 :-) 规则和约定之间是有区别的。
  • 非常感谢!效果很好
  • 我正在努力寻找一个实际案例,其中使用变量遮蔽类会产生不利影响。尽管可能有一些我没有考虑过的边缘情况,但它似乎仍然可以正常工作。我会说最好避免混淆:-)但无论如何这仍然是个好建议。可能想参考docs.oracle.com/javase/tutorial/java/nutsandbolts/… 作为信息来源。
【解决方案2】:

它是空的,因为它从未被实例化。在您的主要方法中创建 SongDatabase 以解决您原来的问题:

public static void main(String[] args) {
    Interface intFace = new Interface();
    SongDatabase = new SongDatabase();
    SongDatabase.addNewSong();
    intFace.run();
}

【讨论】:

    【解决方案3】:

    为避免混淆,请以小写字母开头的变量命名。

     private SongDatabase songDatabase;
    

    这样很明显,当你写 songDatabase 时,你指的是实例,而当你写 SongDatabase 时,你指的是类。

    您需要先实例化该类的实例,然后才能使用它。您似乎已经从问题中意识到了这一点,但这只是在哪里做的问题。为了快速修复,您可以在声明变量的位置实例化它。稍后您可以研究更好的设计。因此:

     private SongDatabase songDatabase = new SongDatabase();
    

    【讨论】:

      【解决方案4】:

      您将NullPointerException 作为SongDatabase 的类变量从未被实例化。要初始化类变量,我们可以使用构造函数,请参阅下面的代码详细信息。同样为了避免命名混乱,我们可以使用这个关键字来获得更好的代码可读性。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多