2015-06-19 15 views
13
public class Sample { 

    public void method() 
    { 
     System.out.println("normal hai"); 
    } 
    public static void method1() 
    { 
     System.out.println("static hai"); 
    } 
    public static void main(String[] args) { 
     Sample s = null; 
     s.method1(); 
     s.method(); 
    } 
} 

a wyjście jest:kolejność wykonywania metody statycznej

Exception in thread "main" java.lang.NullPointerException 
     at com.csvfile.sample.main(Sample.java:22) 

static hai 

Dlaczego kolejność zmieniło? To powinien wypisać:

static hai 
Exception in thread "main" java.lang.NullPointerException 
    at com.csvfile.sample1.main(Sample.java:22) 
+0

@kocko Ponieważ jest to kolejność, którą nazwał metodami w ... – immibis

+0

Wywołanie metody statycznej dla zmiennej instancji jest na początku złym stylem kodowania. Zawsze wywoływaj statyczne metody na samej klasie: 'sample1.method1()' –

+0

http://stackoverflow.com/questions/1883321/java-system-out-println-and-system-err-println-out-of-order – Marvin

Odpowiedz

5

To dlatego, że exception zostanie wydrukowany na stderr i System.out.println() jest drukowana na standardowe wyjście i oba strumienie nie są zsynchronizowane.

Jeśli zadzwonisz po raz drugi, zamówienie może się zmienić.

+0

nie zmienia się –

+10

@ Ramaiah.S napisałem to 'can' nie' musi' – Jens

16

Problem polega na tym, że Exception jest drukowany na System.err, a kod jest drukowany na System.out.

Tak, bez źle nazwie klasy (PascalCase proszę) możemy zrobić:

public static void main(String[] args) throws Exception { 
    final System system = null; 
    system.out.println("Odd"); 
    System.out.println(system.toString()); 
} 

a wyjście pojawia się:

Exception in thread "main" java.lang.NullPointerException 
Odd 
    at com.boris.testbench.App.main(App.java:14) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 

Więc oni faktycznie przeplatanego. tj. kolejność wyjścia to niezdefiniowana, ponieważ do konsoli są drukowane dwa strumienie wyjściowe.

zmiana kodu do:

public static void main(String[] args) throws Exception { 
    final System system = null; 
    system.err.println("Odd"); 
    System.err.println(system.toString()); 
} 

daje pożądany efekt.

Można też złapać wyjątek i wydrukować go do System.out aby osiągnąć ten sam efekt:

public static void main(String[] args) throws Exception { 
    final System system = null; 
    system.out.println("Odd"); 
    try { 
     System.out.println(system.toString()); 
    } catch (RuntimeException ex) { 
     ex.printStackTrace(System.out); 
    } 
} 

PS: Jestem pewien, że o tym wiesz, ale nie powinieneś nigdy wywoływać metody static na instancji urządzenia class. Powinieneś zawsze wywoływać metodę static na samym class. Tak więc w twoim przykładzie zawsze powinieneś:

public static void main(String[] args) { 
    sample1 s = new sample1(); 
    s=null; 
    sample1.method1(); 
    s.method(); 
} 
+0

Prawdopodobnie można również osiągnąć ten efekt, wywołując 'System.out.flush()' przed wyrzuceniem wyjątku. – Justin

+0

@Quincunx zakładając, że twój emulator terminalu nie robi innych buforów i różnego rodzaju niewiadomych - tak, powinien zadziałać. –

1

Jest tak dlatego, że out i err to dwa różne strumienie wyjściowe. Jednak obie z nich są drukowane na konsoli. Więc nie widzisz ich jako różnych strumieni. Wypróbuj poniższy kod i sprawdź wynik.

for (int i = 0; i < 10; i++) { 
     System.out.println(i); 
     System.err.println(i); 
} 
0

Wystarczy dobrze wiedzieć coś w Javie:

W Javie istnieje kilka rodzajów startowych fileds: Zobaczmy przykład:

public class HunarianEngineer{ 

static{ 
     System.out.println("1.This is a static block, called when the JVM pull in the class first time ever"); 
} 

{ 
System.out.println("2.This is an instance block, runs before constructor"); 
} 

public HungarianEngineer(){ 
    System.out.println("3.I`m a constructor"); 
} 

}//EndOfClass 

Czytaj więcej o nich: https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html lub tutaj:

http://www.thejavageek.com/2013/07/21/initialization-blocks-constructors-and-their-order-of-execution/

+2

Jak to w jakikolwiek sposób wiąże się z zadawanym pytaniem? –

Powiązane problemy