2015-05-04 3 views
2

Я пробовал смотреть сообщения по этой проблеме, но у меня все еще есть проблемы с этой ошибкой в ​​моем коде. Итак, в четвертой строке я создаю переменную экземпляра с именем SongDatabase для доступа к классу SongDatabase. Но когда я спускаюсь к линии, SongDatabase.addNewSong(); под case 1, я получаю ошибку java.lang.NullPointerException: null.NullPointerException (Java)

Интерфейс класса:

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 = нуль, что, вероятно, вызывает ошибку? Я раньше была линия

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

вместо этого, но я понял, что это создание нового объекта SongDatabase каждый раз и обтирать, что я там хранятся, поэтому мне пришлось изменить его. Я бы очень признателен за решение, потому что я понятия не имею, спасибо!

+0

Конструкторы в основном используются для инициализации полей классов. Поэтому, надеюсь, вы не пропустите эту часть в будущем, что вы можете фактически инициализировать переменные внутри конструктора, создав ее. –

+1

вы не должны называть класс «Интерфейс», который просто путают, для тех, кто использует интерфейсы. –

ответ

6

Вы не должны дать ваше поле экземпляра такое же имя, как класс, потому что вызывает Variable shadowing - говорит Википедия (частично) переменная затенение происходит, когда переменная, объявленная в определенной области (блок решения, метод или внутренний класс), имеет то же имя, что и переменная, объявленная во внешней области. На уровне идентификаторов (имена, а не переменные) это называется 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; 
    } 
} 
+0

«Вы не должны ...»? Вы не должны давать такой совет, не пытаясь объяснить, почему :-) Существует различие между правилами и соглашениями. – paxdiablo

+0

@paxdiablo лучше? –

+0

Thankyou очень много! Отлично работает – Lachie

2

Это значение null, потому что оно никогда не создается. Создание SongDatabase в основной метод, чтобы получить вокруг исходной задачи:

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

Чтобы избежать путаницы называть переменные, начинающиеся с буквы нижнего регистра.

private SongDatabase songDatabase; 

Таким образом, ясно, что, когда вы пишете songDatabase вы имеете в виду случай, и когда вы пишете SongDatabase вы имеете в виду класс.

Вам необходимо создать экземпляр класса, прежде чем вы сможете его использовать. Кажется, что вы уже знаете об этом из вопроса, но это всего лишь вопрос, где это сделать. Для быстрого исправления вы можете создать экземпляр в том месте, где вы объявляете переменную. Позже вы можете посмотреть лучший дизайн. Поэтому:

private SongDatabase songDatabase = new SongDatabase(); 
1

Вы получали в 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; 
     } 
    } 
}