NullPointerException che non riesco ad eliminare

di il
8 risposte

NullPointerException che non riesco ad eliminare

Salve a tutti,
sto scrivendo un programma in java che gestisce dei titoli azionari.
Ad un certo punto nell'esecuzione del programma trovo una null pointer exception di cui non riesco a liberarmi, mi sembra di aver inizializzato e riempito tutto ciò che serve ma evidentemente mi sono persa qualcosa. Posto la parte della classe principale che mi dà errori e le classi ad essa legate che servono nel metodo in questione.
La quinta riga nel metodo addAsk della classe StockExchange è quella che mi genera la nullPointerException, la riposto qui :
if(users.get(userId).getWallet().getTitoliAcquistati().get(t)<quantity) throw new WalletException();
Da quello che sono riuscita a capire titoliAcquistati non viene riempito ma non riesco proprio a capire il perchè.
Grazie mille a chiunque tenterà di darmi una mano.

Questa è la classe principale:
public class StockExchange {
	private int numTitoli;
	private int numUsers;
	Map<String,Titolo> titoli;
	Map<Integer,User> users;
	
	public StockExchange() {
		numTitoli=0;
		numUsers=0;
		titoli= new HashMap<>();
		users= new HashMap<>();
	}

	public int defineStocks(String... stocks) {		
		numTitoli=0;
		for(String s:stocks) {
			String[] st = s.split("[: ]+");
			if(!st[0].equals("")) {
			if(!titoli.containsKey(st[0])){
				Titolo t = new Titolo(st[0],st[1]);
				t.setCode(st[0]);
				t.setName(st[1]);
				titoli.put(st[0], t);
				numTitoli++;
			}			
		}}
	    return numTitoli;
	}

	public String getStock(String stockCode) throws StockException {
		if(!titoli.containsKey(stockCode)) throw new StockException();
        return titoli.get(stockCode).toString();
	}

	public int registerUser(String name) {
		numUsers++;
		User u = new User(numUsers, name);
		users.put(numUsers, u);
        return numUsers;
	}

	public String getUser(int userId) throws UserException {
		if(!users.containsKey(userId)) throw new UserException();
        return users.get(userId).toString();
	}

	public void addToBalance(int userId, double amount) throws UserException {
		if(!users.containsKey(userId)) throw new UserException();
		users.get(userId).setSaldo(users.get(userId).getSaldo()+amount);
	}

	public double getBalance(int userId) throws UserException {
		if(!users.containsKey(userId)) throw new UserException();
        return users.get(userId).getSaldo();
	}

	public void addToWallet(int userId, String stockCode, int quantity) throws UserException, StockException {
		if(!users.containsKey(userId)) throw new UserException();
		if(!titoli.containsKey(stockCode)) throw new StockException();
		Titolo t = titoli.get(stockCode);
		if(users.get(userId).getWallet().getTitoliAcquistati().containsKey(t)) {
			users.get(userId).getWallet().addQuantityToTitle(t, quantity);
		} else {
			users.get(userId).getWallet().addTitleToWallet(t, quantity);
		}		 
	}

	public Collection<String> getWallet(int userId) throws UserException {
		if(!users.containsKey(userId)) throw new UserException();
        return users.get(userId).getWallet().elencoTitoli(); 
	}
	
	public void addAsk(int userId, String stockCode, int quantity, double minPrice) throws UserException, StockException, WalletException {
		System.out.println(users.get(userId).getWallet().getTitoliAcquistati());
		if(!users.containsKey(userId)) throw new UserException();
		if(!titoli.containsKey(stockCode)) throw new StockException();
		Titolo t = titoli.get(stockCode);
			if(users.get(userId).getWallet().getTitoliAcquistati().get(t)<quantity) throw new WalletException();
			users.get(userId).getWallet().removeTitle(titoli.get(stockCode), quantity);
			Integer i = userId;
			Integer q = users.get(userId).getWallet().getTitoliAcquistati().get(t);
			Double d = minPrice;
			Proposta proposta =new Proposta(userId,quantity,minPrice);
			titoli.get(stockCode).addProposta(proposta);	
	}
}
Questa è la classe user:
public class User {
	private int id;
	private String name;
	private double saldo;
	private Wallet wallet;
	
	public User(int id, String name) {
		this.id=id;
		this.name=name;
		saldo=0;
		wallet = new Wallet();
	}
	
	public String toString() {
		return id+": "+name;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public double getSaldo() {
		return saldo;
	}

	public void setSaldo(double saldo) {
		this.saldo = saldo;
	}

	public Wallet getWallet() {
		return wallet;
	}

	public void setWallet(Wallet wallet) {
		this.wallet = wallet;
	}
	
	public long getNumTitoliInWallet() {
		return wallet.getTitoliAcquistati().size();
	}
}
E questa è la classe wallet:
public class Wallet {
	private Map<Titolo, Integer> titoliAcquistati; //l'integer contiene la quantità per ogni titolo
	
	public Wallet() {
		titoliAcquistati= new HashMap<Titolo, Integer>();
	}
	
	public void addQuantityToTitle(Titolo t, int quantity) {
		int newQuantity = titoliAcquistati.get(t)+quantity;
		titoliAcquistati.put(t, newQuantity);
	}
	
	public void addTitleToWallet(Titolo t, int qty) {
		titoliAcquistati.put(t, qty);
	}
	
	public Map<Titolo, Integer> getTitoliAcquistati() {
		return titoliAcquistati;
	}

	public void setTitoliAcquistati(Map<Titolo, Integer> titoliAcquistati) {
		this.titoliAcquistati = titoliAcquistati;
	}
	
	public Collection<String> elencoTitoli(){
		List<String> elencoTitoli = new LinkedList<>();
		for(Titolo t:titoliAcquistati.keySet()) {
			String s = t.getCode()+": "+titoliAcquistati.get(t);
			elencoTitoli.add(s);
		}
		return elencoTitoli;
	}
	
	public void removeTitle(Titolo t, int quantity) {
		if((titoliAcquistati.get(t)-quantity)!=0) {titoliAcquistati.put(t,(titoliAcquistati.get(t)-quantity));} titoliAcquistati.remove(t);
	}
	
	public int quantityPerTitle(Titolo t) {
		return titoliAcquistati.get(t).intValue();
	}
}

8 Risposte

  • Re: NullPointerException che non riesco ad eliminare

    Per primo direi che sarebbe più comodo in debug singole assegnazioni rispetto ad una chiamata di metodi successivi :
    if(users.get(userId).getWallet().getTitoliAcquistati().get(t)<quantity) throw new WalletException();
    in questo modo vedresti più facilmente ad esempio cosa torna getTitoliAcquistati() ,se torna un null la get successiva fallisce ,rileggendo tutto il programma dovresti controllare dove e quando viene settato titoliacquistati ,ciao
  • Re: NullPointerException che non riesco ad eliminare

    Se aggiungo una println di titoliAcquistati prima di quella riga me la dà vuota, quindi sicuramente è quello il problema. Purtroppo non riesco a capire perchè in quanto mi sembra di averla riempita correttamente, infatti il metodo addToWallet utilizza due metodi della classe wallet che inseriscono titoli in titoliAcquistati. Da lì in poi quella mappa non viene più toccata e quindi nemmeno svuotata
    Intanto grazie per la risposta, in base a quello che ho scritto riesci per caso a darmi qualche consiglio in più?
  • Re: NullPointerException che non riesco ad eliminare

    Non sò che ambiente ide usi ma se possibile metti dei breakpoint e non println ,
    >>>mi sembra di averla riempita correttamente
    metti dei breakpoint anche dei metodi che aggiungono valori a titoliacquistati per capire se ci passi oppure no
  • Re: NullPointerException che non riesco ad eliminare

    Conosco poco java, alcuni dei frequentatori del forum sono molto competenti in java e magari potrebbero dare un aiuto
  • Re: NullPointerException che non riesco ad eliminare

    Ma come vengono popolate le varie entita' ? C'e' una calla a DB ? Mostraci i test che hai fatto per generare NullPointerException perche da questo :

    users.get(userId).getWallet().getTitoliAcquistati().get(t)

    Sono ammessi i casi in cui la Map titoli acquistati non contenga nessuna entry ? Perche c'e' poi una call get(t) quindi mi sembra un po rischiosa.
  • Re: NullPointerException che non riesco ad eliminare

    Posto anche i test junit che riguardano questa parte:
     private StockExchange se;
    public void setUp() {
            se = new StockExchange();
        }
    
    public void testBidInvalidBalance() throws StockException, UserException, WalletException, BalanceException {
        	se.defineStocks(TestR1_Stocks.STOCKS);
    		int u1 = se.registerUser("Marco");
    		se.addToWallet(u1, "AAPL", 10);
        	se.addAsk(u1, "AAPL", 4, 194.5);
        	se.addAsk(u1, "AAPL", 6, 207.8);
    		int u2 = se.registerUser("Giovanni");
    		se.addToBalance(u2, 1500.0);
    		se.executeBid(u2, "AAPL", 6, 250.1);
        }
    La seconda addAsk di questo test mi genera l'errore insieme alla riga riportata prima

    Posto anche la classe Titolo e la classe Proposta così c'è praticamente tutto
    Titolo:
    public class Titolo {
    	private String code;
    	private String name;
    	private List<Proposta> proposteVendita;
    	
    	public Titolo(String code, String name) {
    		this.code=code;
    		this.name=name;
    		proposteVendita=new LinkedList<>();
    	}
    		
    	public List<String> getTitolParameters (String s) {
    		String[] st = s.split("[: ]+");
    		List<String> lista = new ArrayList<>();
    		lista.add(st[0]);
    		lista.add(st[1]);
    		return lista;
    	}
    	
    	public void addProposta(Proposta proposta) {
    		proposteVendita.add(proposta);
    	}
    	
    	public void removeProposta(Proposta proposta) {
    		proposteVendita.remove(proposta);
    	}
    	
    	public List<String> getProposteVendita() {
    		return proposteVendita.stream().sorted(comparing(Proposta::getMinPrice).thenComparing(x->x.quantity).reversed()).map(x->x.toString()).collect(toList());
    	}
    	
    	public List<Proposta> getPropVendita(){ return proposteVendita;}
    	public void setProposteVendita(List<Proposta> proposteVendita) {
    		this.proposteVendita = proposteVendita;
    	}
    
    	@Override
    	public String toString() {
    		return code+": "+name;
    	}
    	
    	public String getCode() {
    		return code;
    	}
    
    	public void setCode(String code) {
    		this.code = code;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    Proposta:
    package it.polito.oop.stocks;
    public class Proposta {
    	double minPrice; 
    	int userId, quantity; 
    	public Proposta(Integer i, Integer q, double p) {
    		userId=i; 
    		quantity=q; 
    		minPrice=p;
    		}
    	public String toString(){ 
    		return userId+": "+quantity+"@"+minPrice;
    		}
    	public double getMinPrice() {
    		return minPrice;
    		} 
    	public int getUserId() {
    		return userId;
    		} 
    	public int getQuantity(){
    		return quantity;
    	} 
    	public void setQuantity(int quantity) {
    		this.quantity=quantity;
    		}
    }
    In ogni caso grazie mille ad entrambi per l'aiuto!
  • Re: NullPointerException che non riesco ad eliminare

    Qual'e' il valore di TestR1_Stocks.STOCKS ?
  • Re: NullPointerException che non riesco ad eliminare

    Ok ragazzi, sono riuscita a risolvere cambiando il metodo remove e una riga del metodo addAsk.
    Penso che il problema fosse che tentava di rimuovere un elemento null e quel .size() su un null dava problemi.
    Ora funziona tutto. Grazie mille a tutti per l'aiuto!
Devi accedere o registrarti per scrivere nel forum
8 risposte