2015-08-20 19 views
35

La mia comprensione era che le variabili statiche e i metodi statici sono di una classe, non degli oggetti di classe. Quindi un Override di un metodo statico non funzionerà in Java, poiché per sovrascrivere abbiamo bisogno di creare un'istanza di una classe. Ma stavo provando qualcosa oggi che contraddiceva la mia conoscenza di Java.Se i metodi statici non possono essere sovrascritti, come funziona qui (per Java)?

Si prega di seguire questo codice:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{  
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Child "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

L'uscita di quanto sopra implementazione è:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise 
In static method 'doit' of class Parent 
In static method 'doit' of class Child 

Da questa uscita posso capire che anche se la classe Child estende la classe Parent, i doit metodi sono individuali per ogni classe in quanto sono static. Quindi non è consentito ignorarli.

Ora si prega di seguire il codice qui sotto, in cui viene aggiunto il metodo del bambino doIt@Override:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{  
    @Override // Adding this annotation here 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Child "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

L'uscita del codice di cui sopra dà un errore di compilazione come segue:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java 
StaticPractise.java:31: error: method does not override or implement a method from a supertype 
    @Override 
    ^
1 error 

Eccolo dice chiaramente che l'annotazione Override non può essere applicata nei metodi static in quanto non vengono sovrascritti.

Ora si prega di seguire il codice qui sotto, dove Child non ha doIt metodo:

class Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{ /* no doIt method */ } 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

L'output è:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise 
In static method 'doit' of class Parent 
In static method 'doit' of class Parent 

Perché il codice di compilazione e soprattutto correre? Mi aspettavo un errore di compilazione per il metodo doit per la classe Child, e mi aspettavo "Metodo non trovato". Non capisco.

Inoltre si prega di seguire il codice qui sotto. Qui, il metodo doIt in Parent è ora final.

class Parent{ 
    public static final void doIt(){ // now final 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

class Child extends Parent{ 
    public static void doIt(){ 
     System.out.println("In static method 'doit' of class Parent "); 
    } 
} 

public class StaticPractise{ 
    public static void main(String[] args){ 
     Parent.doIt(); 
     Child.doIt(); 
    }  
} 

L'uscita dopo l'esecuzione del codice di cui sopra è il seguente:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java 
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent 
    public static void doIt(){ 
        ^
    overridden method is static,final 
1 error 

D:\Rahul Shivsharan\MyPractise\JAVA> 

quello che mi aspettavo era che il codice di cui sopra dovrebbe funzionare bene come i metodi doit sono statici in ogni classe, quindi, anche un La parola chiave final non dovrebbe generare errori di compilazione in quanto il metodo è static.

Per favore spiegami come funziona il metodo di sovrascrittura nelle classi statiche in Java.

  1. È possibile sovrascrivere i metodi statici? Se sì, come mai l'annotazione di @Override fallisce?
  2. Se i metodi statici non possono essere sovrascritti, come mai il mio terzo blocco di codice funziona correttamente?
  3. Se i metodi statici non possono essere ignorati, come mai la parola chiave final fa la differenza?
+2

Ben scritta domanda del giorno finora :) –

risposta

40

Prima di tutto ci sono diversi meccanismi coinvolti qui: Overriding and Shadowing (also called hiding).

1) I metodi statici non possono essere sovrascritte in quanto sono attaccati alla classe che sono definiti in. Tuttavia, è possibile ombra/nascondere un metodo statico, come si sta facendo con la vostra classe Parent/Child. Ciò significa che il metodo viene sostituito nella classe Child ma è ancora disponibile dalla classe Parent.

diventa più evidente che siete non imperativa quando si sta chiamando i metodi statici da istanze di quelle classi (e non utilizzando il Class.staticMethod() invocazione).

Parent parent = new Parent(); 
Child child1 = new Child(); 
Parent child2 = new Child(); 

parent.StaticMethod(); 
child1.StaticMethod(); 
child2.StaticMethod(); 

l'uscita è

Static method from Parent 
Static method from Child 
Static method from Parent 

La risposta è l'invio dei metodi. È possibile afferrare il source code here

2) L'invio trova il metodo nella classe Parent. Non esiste una spedizione dinamica in quanto viene utilizzato il tipo di runtime per trovare l'handle del metodo. Usa il tipo di tempo di compilazione. Ricorda: la chiamata di metodi statici da istanze è considerata una cattiva pratica in quanto cose come sopra possono accadere e sono facili da trascurare.

3) Con final si dichiara che il metodo non può essere ignorato né nascosto/nascosto.

+3

Va inoltre notato che il compilatore si sta aggiungendo alla confusione con il suo messaggio di 'metodo sovrascritto è statico, finale'. Questo dovrebbe aver letto in ombra/nascosto. – Oliphaunt

6

Sei confuso overriding con hiding

+9

Mi insinua che "confuso" è anche evidenziato. :/ – EralpB

+0

@EralpB, Devo accettare ... a grande richiesta il collegamento alla sezione principale in JLS contenuto in [confusione] (https://docs.oracle.com/javase/specs/jls/se8/html/jls- 8.html # jls-8.4.8) è stato cancellato: D –

3

Anche se è sconsigliato porre 3 domande in un solo post, sono comunque disposto a risponderle.

  1. I metodi statici non possono essere sovrascritti perché non c'è motivo di farlo. Nel tuo caso, se vuoi sovrascrivere il metodo statico, puoi semplicemente chiamare il metodo e aggiungere la tua implementazione, oppure creare un altro metodo.

  2. Così ora che sai che i metodi statici non possono essere ignorati. Ma stai chiedendo perché funziona il terzo codice? Il terzo codice è il codice con

    public class Bambino estende Parent {}

giusto? Sebbene i metodi statici non possano essere ignorati, possono essere ereditati. Quello che stai facendo è ereditare Parent quindi è tutto a posto!

  1. Ora lasciate che vi dica, nel primo esempio di codice si è nasconde il metodo nella classe Parent, non ignorando. Ecco perché ottieni l'output.Una parola chiave final significa che il metodo può mai essere modificato, nemmeno nascosto. Ecco perché