blok inicjalizacyjny

0

hej,
mam pytanie, takie troche teoretyczne. czy jest jakis zakres operacji ktore moge i ktorych nie moge wykonac w bloku inicjalizacyjnym? Pytam, bo nacielam sie pare razy w moim programie ze niektorych rzeczy nie moge zrobic. tzn nie wiem czy nie moge, czy po prostu cos zle implementuje, ale podam pare przykladow co mi nie wyszlo:

  1. zapis do pliku
  2. chce ustawic adres serwera przy pomocy metody setMojaZmienna(String url). jednak jak sie pozniej odwoluje w innym miejscu programu do getMojaZmienna() to dostaje null. Jesli wywolam setMojaZmienna w innym miejscu, tzn juz "po" bloku inicjalizacyjnym (statycznym) to sie ustawi.
  3. "wypchniecie" dialogu z jakims info

wiec sie zastanawiam czy moze w bloku inicjalizacyjnym nie wszystko mi wolno? czy jednak stawialibyscie na to, ze mam problem w kodzie?

hmm, wlasciwie jak przeczytalam to co napisalam, to zrozumialam jak glupi blad popelnilam w przypadku 2gim.

metody get i set nie byly statyczne. wiec musialam sobie stworzyc obiekt MojObiekt i ustawic ten adres serwera przy pomocy set. jak go potem odczytac chcialam to przeciez nowy obiekt MojObiekt.. wiec nic dziwnego ze null dostawalam..

0

W pierwszym przypadku trzeba łapać wszystkie deklarowane wyjątki i rzucać RuntimeException (lub lepiej ExceptionInInitializerError)

static {
	try {
		Writer writer = new FileWriter("/dev/foobar");
		try {
			writer.write("abc");
		} finally {
			writer.close();
		}
	} catch (IOException e) {
		throw new ExceptionInInitializerError(e);
	}
}
0

RuntimeException? z tego co wiem, nie powinno sie rzucac RuntimeException ani Error. bo co to da? co ja z tym zrobic moge?

0

możesz pokazać kod jak to wykonujesz?

0
misty napisał(a)

RuntimeException? z tego co wiem, nie powinno sie rzucac RuntimeException ani Error. bo co to da? co ja z tym zrobic moge?

Rzucenie dowolnego RuntimeException/Error w bloku inicjalizacji statycznej spowoduje rzucenie tego wyjątku opakowanego w ExceptionInInitializerError przez class loader.
To z kolei spowoduje zamknięcie całej aplikacji z tym błędem.

Jeżeli tego nie chcesz, to możesz np. w bloku catch poinformować użytkownika o błędzie, ale kontynuować działanie programu (czyli nie rzucać wyjątku). Oczywiście w tym przypadku dane do pliku nie zostaną zapisane.

Zamiast statycznego boku inicjalizującego możesz pomyśleć o singletonie i zapisu pliku dokonać przy jego tworzeniu (albo możesz mieć zmienną boolowską, która mówi czy plik został już zapisany i jeżeli przy tworzeniu egzemplarza tej klasy zmienna ta ma wartość "false" to należy zapisać plik i zmienić zmienną na "true").

0
misty napisał(a)

hej,
mam pytanie, takie troche teoretyczne. czy jest jakis zakres operacji ktore moge i ktorych nie moge wykonac w bloku inicjalizacyjnym?
...
3) "wypchniecie" dialogu z jakims info

Zanim napiszesz taki kod, przemysl to dwa razy. Jesli nadal uznasz, ze to wlasciwe rozwiazanie, przemysl jeszcze raz.

Instrukcje z bloku inicjalizacyjnego wykonywane sa za kazdym razem, w momencie tworzenia instancji nowego obiektu (lub w przypadku bloku statycznego tylko raz, w momencie ladowania klasy do pamieci przez ClassLoader JVM). Blok statyczny ma dostep tylko do statycznych atrybutow/metod klasy. Blok "instancji" ma dostep do wszystkich atrybutow/metod, ale (UWAGA!) wykonywany jest zanim konstruktor zakonczy dzialanie, wiec w momencie, gdy nie ma jeszcze pelnego obrazu obiektu w pamieci. Tak wiec trzeba uwazac, aby atrybuty z ktorych korzystamy, byly poprawnie zainicjowane.

0

hej, dzieki za odpowiedzi.

wiec tak-tak, ten blok musi byc inicjalizowany przy kazdym nowym uruchomieniu programu(przez nowe rozumiem-ze np app zostala zamknieta a pozniej ponownie odpalona). i tak, musi sie to wykonac nim dojdziemy do konstruktora.

generalnie chodzi o to, ze ten blok ma zainicjowac jakies tam zmienne ( i wrzuca je to metod setCos, ktore sa statyczne). Probowac powinien 3 razy.
a jak program przechodzi do konstruktora to sprawdza czy taka zmienna jest ustawiona i w zaleznosci od tego robi cos albo cos innego.
generalnie problem jest teraz taki, ze musze to zaczac z pewnym opoznieniem, tzn np po ok 30 sek. to mniej wiecej powinno wygladac tak:

 static{
         Timer t = new Timer();
           t.scheduleAtFixedRate(new TimerTask(
  
             int licznik = 0;
     public void run(){
               licznik++;


         if(doMyMethod()){
this.cancel();}

if(licznik == 3){
	this.cancel();
}

}

), 30000, 5000);

}


//zas myMethod:

private static booleam myMethod(){

	try{
	//Configuration - klasa ktora ma same metody statyczne typu get/set
	  Configuration.setMyZmienna(true);
	
	//tu musze lapac ten exc, teraz przedstawiam tylko prosty przyklad
	}catch(NullPointerException e){
	 	  Configuration.setMyZmienna(false);
	}
  return Configuration.getMyZmienna();
}


//a konsturktor:

public MojTest(){

   if(Configuration.getMyZmienna){
	  System.out.println("jest ok");
	  //rob cos tam
   }else{
	System.out.println("nie jest ok");
	//rob cos tam
   }
}

no i praktycznie od razu po uruchomieniu programu dostaje "nie jest ok". a przeciez w bloku statycznym jest timer, ktory nie dosc ze ma sie uruchomic po 30sek to jeszcze ma 3 razy sprobowac wywolac metody doMyMethod. a to wyglada jakby od razu przechodzilo do konsturktora (w ktorym oczywiscie, jesli blok inicjalizacyjny nie wykona sie, to zmienna Configuration.getMyZmienna() bedzie na false). nie kumam co robie zle.

0

Gdzie jest "new MojTest()"?
Jak myślisz, co tak naprawdę anulujesz za pomocą wywołania this.cancel()? Co jest referencją do obiektu Timer, na rzecz którego wywołujesz zadania?
Czy jeżeli tworzysz jakiś obiekt w bloku static, to jesteś pewna, że obiekt jest statyczny oraz zmienna referencyjna, która na niego wskazuje również są statyczne?

Metoda run klasy TimerTask NIE działa w tym samym wątku, co t.scheduleAtFixedRate(). A w związku z tym blok static kończy się momentalnie po wywołaniu tej metody. A to oznacza, że metoda main() klasy, której na tym listingu nie ma wywołuje się zanim zaskoczy którykolwiek z timerów. Jeżeli chcesz naprawdę opóźniać wykonanie jakiegoś kodu, to musisz go zamknąć w zadaniu wywoływanym asynchronicznie podobnie jak to co jest w metodzie Run TimerTaska lub pobawić się metodami Thread.sleep() lub czymś takim "Timeunit.SECONDS.sleep(30);" w wywołaniu rozpoczynającym się w main. Pamiętaj, że main też jest metodą statyczną.

Poza tym łapanie wyjątku NullPointerException, to wyjątkowo zły pomysł. Jego wystąpienie oznacza praktycznie zawsze błąd w kodzie. Nie należy tego dynamicznie wyłapywać tylko znaleźć błąd i go wyeliminować.
Przy okazji postaraj się panować nad formatowaniem tekstu każdego programu jaki tworzysz (szczególnie konsekwentnym umiejscowieniem klamr bloków). Unikniesz dzięki temu ślęczenia godzinami nad banalnymi pomyłkami.

1 użytkowników online, w tym zalogowanych: 0, gości: 1