Prosty Stos

D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

Witam, napisałem prosty stos, i niestety otrzymuje NullPointerException...
Co przeoczyłem, czego nie zainicjowałem:

Kopiuj
public class MojStos {
	Object tab[];
	int counter;
	
	
	public MojStos(int wielkosc){
		Object tab[] = new Object[wielkosc];
		counter = 0;
	}
	
	public void push(Object o)throws StosPrzepelnionyException{
		if(tab.length>counter){
			tab[counter++]=o;
		} else {
			throw new StosPrzepelnionyException();
		}
	}
	public Object pop() throws StosPustyException{
		if(counter<=0){
			throw new StosPustyException();
		} else {
			return tab[--counter];
		}
	}
	
	public void show(){
		/*for(Object item : tab){
			System.out.println(tab[item]);
		}*/
		System.out.println("===============");
		for(int i=0;i<=tab.length;i++){
			System.out.println(tab[i]);
		}
		System.out.println("===============");
		
	}
	
}

Klasa Main

Kopiuj
public class Main {
	
	public static void main(String[] args) {
		MojStos ms = new MojStos(3);
		
	
		try {
			ms.push(new Integer(8));
		} catch (StosPrzepelnionyException e) {
			e.printStackTrace();
			}
		}
	}
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:prawie 2 lata
  • Lokalizacja:Wrocław
  • Postów:13042
0

W konstruktorze nie inicjujesz pola.


D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

I tab i counter sa są przeciez zainicjowane?
tab = new Object(wielkosc);
counter = 0;

edytowany 1x, ostatnio: dombek100
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:prawie 2 lata
  • Lokalizacja:Wrocław
  • Postów:13042
0

Jak już wycinasz fragment, wycinaj z kontekstem:

Kopiuj
Object tab[] = new Object[wielkosc];
// ^^^^^^^^

;-)


edytowany 2x, ostatnio: Patryk27
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:około 6 godzin
  • Postów:4937
0

Tu jest stos od autorow Algorytmow w Javie https://algs4.cs.princeton.edu/13stacks/Stack.java.html


A9
A9
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Zgorzelec/Görlitz
  • Postów:14
0

Cześć,
W konstruktorze tworzysz zupełnie nowy obiekt, który nic Ci nie daje później. Zamiast tego odwołaj się do zmiennych klasy:

Kopiuj
    public MojStos(int wielkosc){
        Spojler alert. Masz drugą zmienną i wymyśl co z pierwszą i zastanów się dlaczego tak jest:)
        this.counter = 0;
    }

i z tego co widzę jeszcze powinno Ci wywalić ArrayOutOfBoundException przy:

Kopiuj
        for(int i=0;i<=tab.length;i++){
            System.out.println(tab[i]);
        }

iterujesz o jeden obiekt za dużo. Sam zmień :)

Pozdrawiam,
adaszewski95

D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

W konstruktorze tworzysz zupełnie nowy obiekt, który nic Ci nie daje później. Zamiast tego odwołaj się do zmiennych klasy:

Kopiuj
    public MojStos(int wielkosc){
        Spojler alert. Masz drugą zmienną i wymyśl co z pierwszą i zastanów się dlaczego tak jest:)
        this.counter = 0;
    }

Hey, dzieki za odpowiedzi, dlaczego mówisz ze tworze obiekt który nic mi nie daje. Tworze Objekt Tab (tj. moj stos). To obiekt wiec muszę go zainicjować.

D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

i z tego co widzę jeszcze powinno Ci wywalić ArrayOutOfBoundException przy:

Kopiuj
        for(int i=0;i<=tab.length;i++){
            System.out.println(tab[i]);
        }

iterujesz o jeden obiekt za dużo. Sam zmień :)

jasna sprawa już poprawione:)

edytowany 2x, ostatnio: dombek100
A9
A9
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Zgorzelec/Görlitz
  • Postów:14
1

Dobre rano :)

Już Ci tłumaczę, bo to jest kluczowe. Zauważ, że w klasie masz dwie **zdefiniowane **zmienne:

Kopiuj
    Object tab[];
    int counter;

Następnie tworzysz konstruktor, co jest jak najbardziej logiczne. Tylko w tym konstruktorze kluczowe jest to, żeby przypisać wartość zmiennym, które wcześniej zdefiniowałeś. Czyli tym powyżej. A to co robisz Ty w tym konstruktorze:

Kopiuj
    public MojStos(int wielkosc){
        Object tab[] = new Object[wielkosc];
        counter = 0;
    }

jest zdefiniowanie nowych zmiennych, które nie mają nic wspólnego z Twoimi zmiennymi klasy.
Zmienne, które zdefiniowałeś i przypisałeś im wartość w konstruktorze widzi tylko ten obiekt. Co to powoduje? Że do Twoich zmiennych klasy nie została przypisana żadna wartość a Ty próbujesz z nich skorzystać w dalszych metodach (myśląc, że przypisałeś im wartość, a tak na prawdę stworzyłeś nowe zmienne, które nie są widoczne poza konstruktorem) co skutkuje NullPointerem, ponieważ po stworzeniu obiektu nie zostały przypisane wartości zmiennym klasy. Dlatego też musisz koniecznie przypisać tym zmiennym wartość w konstruktorze. Tzn teraz patrzę to counterowi przypisujesz ale tworzysz tylko new Object tab = ...
Po prostu napisz tab = ... i będzie gitarrra :D
Mam nadzieję, że wytlumaczyłem zrozumiale.

Pozdrawiam,
adaszewski95

katelx
  • Rejestracja:około 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Hong Kong
1

pare uwag odnosnie twojego stosu ktore mozna latwo poprawic:

  • moglby byc type safe zamiast uzywac object
  • moglby nie rzucac wyjatkami
  • mogby nie miec ograniczen jesli chodzi o rozmiar
  • moglby nie miec wyciekow pamieci (przy pop)

np:

Kopiuj
import java.util.Optional;

public class Stack<TElement> {

    private Node<TElement> top;

    public void push(TElement element) {
        top = new Node<>(element, top);
    }

    public Optional<TElement> pop() {
        if (top == null) {
            return Optional.empty();
        }
        TElement popped = top.value;
        top = top.below;
        return Optional.of(popped);
    }

    public void show() {
        System.out.println("===============");
        Node current = top;
        while (current != null) {
            System.out.println(current.value);
            current = current.below;
        }
        System.out.println("===============");

    }

    private class Node<TElement> {
        final TElement value;
        final Node<TElement> below;

        Node(TElement value, Node<TElement> below) {
            this.value = value;
            this.below = below;
        }
    }


    public static void main(String[] args) throws Exception {
        Stack<String> stack = new Stack<>();
        stack.push("lol");
        stack.push("rotfl");
        stack.push("lmao");
        stack.show();
        stack.pop();
        stack.pop();
        stack.show();
        stack.pop();
        stack.pop();
    }
}
edytowany 1x, ostatnio: katelx
A9
adaszewski95
Myślę, że jak zaczyna swoją przygodę z javą to jeszcze nie wie co to Optional czy generics.
katelx
to dobra okazja zeby sie dowiedziec ;)
D1
nie wiem :), ale sie dowiem. Nardzo Wam dziękuje za pomoc. Cieszę się że znalazłem to forum.
FI
filemonczyk
czy to jest po bozemu ze element top ma referencje do elementu ponizej?
D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0
adaszewski95 napisał(a):

Dzięki za wskazówki. Zrobiłem poniższe:

Kopiuj
	public MojStos(int wielkosc){
		this.tab = new Object[wielkosc];
		this.counter = 0;
	}

Odwołuje się do konkretnych pól klasy które inicjuje w konstruktorze (błąd NullpointException rozwiązany :)

A9
adaszewski95
No i elegancko :) kolejnym krokiem jest wprowadzenie getterów i setterów, żebyś później mógł korzystać z tych zmiennych danego obiektu gdzieś indziej, np w main. Pozdrawiam :)
D1
Jeszcze raz dzięki!
Patryk27
@adaszewski95: wprowadzenie tutaj akcesorów doprowadziłoby do powstania leaking abstraction. Przecież równie dobrze można stos reprezentować listą jednokierunkową czy czymkolwiek innym.
A9
adaszewski95
@Patryk27: to prawda, ten przypadek nie jest do tego najlepszy. Raczej chodziło mi o późniejsze implementacje jakichś klas modelu. I w ogóle wygooglowałem "leaky abstraction", bo nie wiedziałem do końca co pod tym rozumieć, i pamiętam jak kiedyś była o tym mowa na teoretycznej informatyce :) ale znam to pod inną nazwą, tylko teraz nie wiem dokładnie pod jaką. Bym musiał odkopać książkę profesora z TI. Fajnie tak się udzielać na forum, zawsze można się czegoś ciekawego dowiedzieć :)
D1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

Co znaczy?

  • moglby nie miec wyciekow pamieci (przy push)
katelx
  • Rejestracja:około 10 lat
  • Ostatnio:6 miesięcy
  • Lokalizacja:Hong Kong
2

mialam na mysli pop.
gdy bierzesz obiekty ze stosu to nie usuwasz ich z tablicy, tak wiec nawet jesli przestaniesz ich uzywac w innych miejscach, to referencja bedzie dalej trzymana i garbage collector ich nie usunie.
rozwiazaniem na ten problem (w twoim kodzie) byloby:

Kopiuj
counter--;
Object element = tab[counter];
tab[counter] = null;
return element;
edytowany 1x, ostatnio: katelx

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.