2015-11-08 13 views
9

Questo è un esempio su cui stavo lavorando dal mio tutorial di java. Ho una classe Time1 che non ha un costruttore e quindi mi aspettavo che fosse inizializzata con i valori predefiniti su int, che è zero.Valore predefinito Java delle variabili di istanza di una classe non inizializzata a zero per int

public class Time1 { 
    private int hour; // expected to be initialised with zero 
    private int minute; // expected to be initialised with zero 
    private int second; // expected to be initialised with zero 

    public void setTime(int hour, int minute, int second) { 
     if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60) { 
      throw new IllegalArgumentException("value out of range"); 
     } 
     this.hour = hour; 
     this.minute = minute; 
     this.second = second; 
    } 

    public String toUniversalString() { 
     return String.format("%02d:%02d:%02d", hour, minute, second); 
    } 

    public String toString() { 
     return String.format("%d:%02d:%02d %s", ((hour == 0 || hour == 12) ? 12 : hour % 12), minute, second, (hour < 12 ? "AM" : "PM")); 
    } 
} 

e ora ho la classe principale

public class Time1test { 
    public static void main(String[] args) { 
     Time1 thistime = new Time1(); 
     System.out.println(thistime); 
     thistime.setTime(13, 22, 33); 
     System.out.println(thistime); 
    } 
} 

mi aspettavo System.out.println(thistime); prima di utilizzare il metodo setTime() di tornare 00:00:00 perché non ho usato tutti i metodi per riformattare esso, tuttavia Sto ottenendo l'uscita come 12:00 AM, che equivale a chiamare il metodo toString(). Perché questo metodo è stato chiamato di default quando un nuovo oggetto è inizializzato, anche senza essere chiamato?

+3

Perché ti aspettavi '00: 00: 00'? Ti aspettavi che Java chiamasse automaticamente 'toUniversalString'? – user2357112

+2

Fondamentalmente, quando si passa un 'Object' per stampare, come questo:' System.out.println (Object) ', fa davvero' System.out.println (Object.toString()) ' – Zizouz212

+1

@ user2357112, I non era a conoscenza di quale metodo viene chiamato e perché/come, e quindi questa domanda. E grazie Zizouz212 – scott

risposta

8

Se si utilizza un ide come eclissi, è possibile che si sia notato un segno vicino al metodo toString() che dice overrides java.lang.Object.toString. Questo è il metodo che viene chiamato per impostazione predefinita quando si tenta di stampare un oggetto. Questo assomiglia a

* @return a string representation of the object. 
*/ 
public String toString() { 
    return getClass().getName() + "@" + Integer.toHexString(hashCode()); 
} 

Poiché le definizioni sono all'interno del metodo con lo stesso nome, vengono sovrascritte. Si può notare la differenza se si rinomina un proprio metodo toString a qualcos'altro, e l'uscita sarebbe qualcosa di simile [email protected]

+0

Beh, non me ne sono accorto. Cliccando su di esso si apre quell'altra classe, e ha senso sul perché la mia classe personalizzata sta dando 'AM/PM' mentre quella predefinita sta dando una sorta di posizione di memoria. – scott

6

Quando si chiama System.out.println(thistime); per l'oggetto, viene eseguito il metodo toString e viene stampata la stringa che restituisce.

Il tuo metodo toString ritorna esplicitamente 12 quando hours == 0:

return String.format("%d:%02d:%02d %s", ((hour==0 || hour==12)?12:hour%12),minute, second, (hour<12?"AM":"PM")); 

              ------- 
+0

Grazie Eran, ma non ho chiamato questo metodo, quindi perché è stato applicato questo metodo? – scott

+2

@ scott Quando si tenta di stampare un oggetto, si chiama 'toString'. – Eran

+0

Grazie. Risponde alla mia domanda :) – scott

4

System.out.println si aspetta una stringa come parametro, quindi chiama il tuo metodo toString per convertire il vostro oggetto Time1 in una stringa. A causa della logica che hai lì, stai vedendo l'uscita "12:00:00 AM".

Si può fare

System.out.println(time1.toUniversalString()); 

per ottenere il risultato che ci si aspetta;

4

Mi aspettavo System.out.println (thistime); prima di utilizzare il metodo setTime() per restituire 00:00:00 perché non ho usato alcun metodo per riformattarlo, tuttavia sto ottenendo l'output come 12:00:00 AM, che equivale a chiamare a Stringa () metodo. Perché questo metodo è stato chiamato per impostazione predefinita quando viene inizializzato un nuovo oggetto, anche senza essere richiesto ?

Quando si stampa oggetto (che hai fatto con System.out.println(thistime)), il suo metodo toString si chiama (anche in assenza di chiamata esplicita) per impostazione predefinita. E 'così semplice.

+0

Questo è sbagliato. 'PrintStream.println()' è sovraccarico per 'Object', dove viene chiamato esplicitamente' String.valueOf() '. – xehpuk

8

Il problema è nel metodo toString. Che il seguente fa

((hour==0 || hour==12)?12:hour%12) 

è, ogni volta che il valore di ora è o 0 o 12, stampa 12, in caso contrario la stampa hour % 12.

quando si chiama:

System.out.println(thistime); 

il risultato di stampa sarà lo stesso di:

System.out.println(thistime.toString()); 

quindi questo è il motivo per cui il metodo toString viene richiamato. Puoi scrivere qualcosa come ((hour == 12) ? 12 : hour % 12) per risolverlo.

+0

Non è convertito. 'PrintStream.println()' è sovraccarico per 'Object', dove viene chiamato' String.valueOf() '. – xehpuk

0

Il metodo print è sovraccarico e invita .toString() per tutto ciò che non è primitivo. Il metodo di stampa può formattare valori primitivi ma chiama toString() per qualsiasi sottoclasse Object.