Кажется, не могу понять, в чем проблема. у меня есть это сообщение об ошибке Exception в потоке «main» java.lang.NullPointerException

У меня эта проблема, и я застрял в ней часами. Я здесь новенький и надеюсь, что вы, ребята, сможете помочь.

Я думал, что проблема в объявлении массива или чего-то в этом роде, но я не могу это исправить.

Моя идея состояла в том, чтобы разделить коды на три разные части для построения, отображения и основного метода, но, видимо, в процессе возникла ошибка.

private static void constructArray(Customer [] c){
    c = new Customer[3];
    ArrayList<ItemInfo> cust1 = new ArrayList<>();
    cust1.add(new ItemInfo("Mutton", 1, 19.85));
    cust1.add(new ItemInfo("Stationery",2,17.66));
    
    ArrayList<ItemInfo> cust2 = new ArrayList<>();
    cust2.add(new ItemInfo("Fishball",1,12.07));
    cust2.add(new ItemInfo("T Bone Steak",3, 19.20));
    cust2.add(new ItemInfo("Stationery", 2, 12.25));
    
    ArrayList<ItemInfo> cust3 = new ArrayList<>();
    cust3.add(new ItemInfo("Crab", 2, 14.08));
    
    c[0] = new Customer(cust1, "cheque");
    c[1] = new Customer(cust2, "cash");
    c[2] = new CustomerPlus(cust3, "Paynow", true);
}

private static void displayArray(Customer [] c){
     c = new Customer[3];
     for(Customer cust : c){
        if(cust instanceof CustomerPlus){
            CustomerPlus plus = (CustomerPlus) cust;
            plus.addItem(new ItemInfo("Cigarette",2,12.96));
            System.out.printf("Mode of payment:%s%nInvoice no:%04d%n%n", plus.getPaymentmode(), plus.getNumber());
            System.out.printf("%s%19s%10s%13s%n","Item","Quantity","Price","Sub Total");
            System.out.println(plus);
            System.out.printf("Total payment: %.2f%n", plus.computePayment());
            if(plus.getAdult())
               System.out.println("Customer: adult");
            System.out.println("-----------------------------------------");
               
        }

        else{
           System.out.printf("Mode of payment:%s%nInvoice no:%04d%n%n", cust.getPaymentmode(), cust.getNumber());
           System.out.printf("%s%19s%10s%13s%n","Item","Quantity","Price","Sub Total");
           System.out.println(cust);
           System.out.printf("Total payment: %.2f%n", cust.computePayment());
           System.out.println("-----------------------------------------");
        }
    }

}


public static void main(String[] args){
    main m = new main();
    Customer [] c = new Customer[3];
    constructArray(c);
    displayArray(c);
    
   
    
}
#
Источник
  • 1
    Вы перезаписываете массив, который входит в качестве параметра c новым пустым массивом. Вы делаете это как в displayArray() и в constructArray() . Зачем ты это делаешь?
  • 0
    Во второй строке каждого метода вы переопределяете массив, переданный в качестве аргумента, с помощью: c = new Customer[3]; .
  • 0
    о, изначально я думал, что проблема в том, что длина не была установлена, поэтому я написал эту часть.
  • 1
    поскольку вы используете только статические методы, вам не нужно делать main m = new main (); m, как видите, нигде не используется. Предполагая, что ваш класс называется 'main', обычно имена классов в Java начинаются с верхнего регистра, поэтому 'Main'
  • 0
    @AdriaanKoster, спасибо, я учту.
  • 1
    Небольшое побочное предложение. Возможно, вы захотите воздержаться от использования instanceof, поскольку это считается запахом кода.
Codelisting
за 1 против

Вот, в конечном счете, причина NPE:

private static void displayArray(Customer [] c){
     c = new Customer[3];
     for(Customer cust : c){

Вы инициализируете c как новый пустой массив клиентов. Все позиции в этом новом массиве будут иметь значение null.

Затем вы пытаетесь перебрать их и получить доступ к полям каждого клиента. Это не удастся, потому что значения равны нулю.

Вот отредактированная версия вашего кода:

public class Main {

    // methods which create a value should preferably return
    // their result rather than updating their input
    // for reasons of code readability
    private static Customer[] constructArray() {
        Customer[] customers = new Customer[3];

        // add the items directly to the customer instead of creating a list first
        customers[0] = new BasicCustomer("cheque");
        customers[0].addItem(new ItemInfo("Mutton", 1, 19.85));
        customers[0].addItem(new ItemInfo("Stationery", 2, 17.66));

        customers[1] = new BasicCustomer("cash");
        customers[1].addItem(new ItemInfo("Fishball", 1, 12.07));
        customers[1].addItem(new ItemInfo("T Bone Steak", 3, 19.20));
        customers[1].addItem(new ItemInfo("Stationery", 2, 12.25));

        customers[2] = new PlusCustomer("Paynow", true);
        customers[2].addItem(new ItemInfo("Crab", 2, 14.08));

        return customers;
    }

    private static void displayArray(Customer[] customers) {
        for (Customer customer : customers) {

            if (customer instanceof PlusCustomer) {
                // why kill your plus customers? ;-)
                customer.addItem(new ItemInfo("Cigarette", 2, 12.96));
            }

            // presentation logic moved into the Customer classes
            // this keeps the Main class focused on the high level
            // process and the Customer classes focused on doing
            // customer logic (cohesion, information hiding)
            // If you find yourself using instanceof always
            // stop and think if you can solve the same issue
            // using polymorphism
            System.out.println(customer);
        }
    }

    public static void main(String[] args) {
        Customer[] customers = constructArray();
        displayArray(customers);
    }
}

Базовый класс Customer:

public class Customer {

    private final List<ItemInfo> items = new ArrayList<>();
    private final String paymentMode;

    public Customer(String paymentMode) {
        this.paymentMode = paymentMode;
    }

    public void addItem(ItemInfo item) {
        items.add(item);
    }

    public double computePayment() {
        double total = 0.0;
        for (ItemInfo item : items) {
            total += item.getTotal();
        }
        return total;
    }

    public int getNumber() {
        return items.size();
    }

    public String getPaymentmode() {
        return paymentMode;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("Mode of payment:%s%n", getPaymentmode()));
        sb.append(String.format("Invoice no:%04d%n%n", getNumber()));
        String itemFormat = "%-20s %-10s %-10s %-10s %n";
        sb.append(String.format(itemFormat, "Item", "Quantity", "Price", "Sub Total"));
        sb.append(String.format("%n"));
        for (ItemInfo item : items) {
            sb.append(String.format(itemFormat, item.getName(), item.getAmount(), item.getPrice(), item.getTotal()));
        }
        sb.append(String.format("%n"));
        sb.append(customPresentation());
        sb.append(String.format("Total payment: %.2f%n", computePayment()));
        return sb.toString();
    }

    /**
     * Sub classes can override this method to provide their own custom part of the presentation logic
     *
     * @return
     */
    String customPresentation() {
        return "";
    }
}

PlusCustomer должен вызвать суперконструктор, чтобы передать способ оплаты. Осталось реализовать только поле для взрослых.

public class PlusCustomer extends Customer {

    private final boolean adult;

    public PlusCustomer(String paymentMode, boolean adult) {
        super(paymentMode);
        this.adult = adult;
    }

    public boolean getAdult() {
        return adult;
    }

    @Override
    String customPresentation() {
        return String.format("Customer: %s%n", getAdult() ? "adult" : "minor");
    }
}

ItemInfo вычисляет свою сумму. Кстати, обычно вам следует избегать использованияdouble для таких вычислений в Java это очень неточно. Лучше использовать BigDecimal.

public class ItemInfo {

    private final String name;
    private final int amount;
    private final double price;

    public ItemInfo(String name, int amount, double price) {
        this.name = name;
        this.amount = amount;
        this.price = price;
    }


    public String getName() {
        return name;
    }

    public int getAmount() {
        return amount;
    }

    public double getPrice() {
        return price;
    }

    public double getTotal() {
        return price * amount;
    }
}

Выход:

Mode of payment:cheque
Invoice no:0002

Item                 Quantity   Price      Sub Total  

Mutton               1          19.85      19.85      
Stationery           2          17.66      35.32      

Total payment: 55.17
---------------------------------------

Mode of payment:cash
Invoice no:0003

Item                 Quantity   Price      Sub Total  

Fishball             1          12.07      12.07      
T Bone Steak         3          19.2       57.599999999999994 
Stationery           2          12.25      24.5       

Total payment: 94.17
---------------------------------------

Mode of payment:Paynow
Invoice no:0002

Item                 Quantity   Price      Sub Total  

Crab                 2          14.08      28.16      
Cigarette            2          12.96      25.92      

Total payment: 54.08
Customer: adult
---------------------------------------
  • 0
    привет, спасибо за указатель и помощь мне в этом.
за 1 против

Это сложно, но проблема в этой строке:

Customer [] c = new Customer[3];

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

Customer [] c = new Customer[3];
for(int i = 0; i < c.length; ++i){
   c[i] = new Customer();
}
  • 1
    Спасибо, я смог исправить это с вашей помощью и другими. Действительно ценю это.
  • 0
    На самом деле это неверный ответ. Вам не нужно зацикливаться, вы также можете назначить три значения напрямую, как уже делает существующий код. Проблема в том, что массив повторно инициализируется в каждом методе, в результате чего значения массива становятся нулевыми, что приводит к NPE
Codelisting
Популярные категории
На заметку программисту