2015-04-09 17 views
16

Perchè non io uso costruttori protette al di fuori del pacchetto per questo pezzo di codice:Perché non posso usare costruttori protetti al di fuori del pacchetto?

package code; 
public class Example{ 
    protected Example(){} 
    ... 
} 

Check.java

package test; 
public class Check extends Example { 
    void m1() { 
    Example ex=new Example(); //compilation error 
    } 
} 
  1. Perché ottengo l'errore anche se ho esteso la classe? Si prega di spiegare

EDIT: errore

Compilation:

The constructor Example() is not visible 
+0

Conoscere l'errore di compilazione potrebbe essere molto utile per diagnosticare il problema ... –

+0

Guardate questo http://stackoverflow.com/questions/5150748/protected-constructor-and-accessibility potete usare un costruttore protetto di una superclasse nel costruttore di una sottoclasse ma non per istanziare un'istanza di superclasse altrove. – redge

+0

Più o meno lo stesso motivo per cui non è possibile eseguire l'esempio di classe pubblica {protected int i;}/* in un altro pacchetto: */public class Check extends Esempio {void m1 (Esempio ex) {ex.i = 2;} } ' – immibis

risposta

3

modificatore protetta viene utilizzata solo con nel pacchetto e in sotto-classi di fuori del pacchetto. Quando crei un oggetto usando Example ex=new Example();, chiamerà il costruttore della classe genitore per impostazione predefinita.

Dato che il costruttore della classe padre è protetto, si verifica un errore in fase di compilazione. È necessario chiamare il costruttore protetto in base alla JSL 6.6.2.2 come mostrato di seguito nell'esempio 2.

package Super; 

public class SuperConstructorCall { 

    protected SuperConstructorCall() { 
    } 

} 

package Child; 

import Super.SuperConstructorCall; 

public class ChildCall extends SuperConstructorCall 
{ 

    public static void main(String[] args) { 

     SuperConstructorCall s = new SuperConstructorCall(); // Compile time error saying SuperConstructorCall() has protected access in SuperConstructorCall 
    } 
} 

Esempio 2 secondo JLS 6.6.2.2:

package Super; 

    public class SuperConstructorCall { 

    protected SuperConstructorCall() { 
    } 

} 

package Child; 

import Super.SuperConstructorCall; 

public class ChildCall extends SuperConstructorCall 
{ 

    public static void main(String[] args) { 

     SuperConstructorCall s = new SuperConstructorCall(){}; // This will work as the access is by an anonymous class instance creation expression 
    } 
} 
+1

No.' protected' può essere usato tra i pacchetti. Devi solo estendere la classe. lo scope 'default' è * all'interno di un pacchetto *. ** Il modificatore protetto specifica che è possibile accedere al membro solo all'interno del proprio pacchetto (come con package-private) e, inoltre, da una sottoclasse della sua classe in un altro pacchetto.** – TheLostMind

+2

Ancora la risposta non è convincente, capisco che chiamerà il genitore della classe genitore cioè> Example() che è protetto ma come sappiamo possiamo usare i modifers protetti al di fuori del pacchetto se estendiamo quella classe, allora perché non lo fa lavoro qui in caso di costruttori? – Abhilash28

+1

Perché dovresti chiamare il costruttore di una superclasse in modo indipendente? Hai accesso ai metodi della superclasse direttamente se non sono accesso predefinito o privato. –

3

In realtà si sta già utilizzando il costruttore protetto dell'esempio perché controllare ha un costruttore implicita ed implicita chiamata Esempio costruttore:

public Check() { 
    super(); 
} 
9

solito protected significa solo t accessibili o sottoclassi o classi nello stesso pacchetto. Tuttavia qui sono le regole per i costruttori dalla JLS:

6.6.2.2. Qualified Access to a protected Constructor

Let C be the class in which a protected constructor is declared and let S be the innermost class in whose declaration the use of the protected constructor occurs. Then:

If the access is by a superclass constructor invocation super(...), or a qualified superclass constructor invocation E.super(...), where E is a Primary expression, then the access is permitted.

If the access is by an anonymous class instance creation expression new C(...){...}, or a qualified anonymous class instance creation expression E.new C(...){...}, where E is a Primary expression, then the access is permitted.

If the access is by a simple class instance creation expression new C(...), or a qualified class instance creation expression E.new C(...), where E is a Primary expression, or a method reference expression C :: new, where C is a ClassType, then the access is not permitted. A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) or a method reference expression only from within the package in which it is defined.

A titolo di esempio, questo non compila

public class Example extends Exception { 

    void method() { 
     Exception e = new Exception("Hello", null, false, false); 
    } 
} 

ma questo

public class Example extends Exception { 

    Example() { 
     super("Hello", null, false, false); 
    } 
} 

e così fa questo

public class Example { 

    void method() { 
     Exception e = new Exception("Hello", null, false, false) {}; 
    } 
} 

Quindi la regola sono chiari, ma non posso dire di aver capito le ragioni dietro a loro!

+0

appreso una nuova cosa;) – kittu

+0

@kittu Così ho fatto I. Non mi rendevo conto che c'erano strane restrizioni come quella. –