Почему конструктор Java должен быть открытым или защищенным для того, чтобы класс был расширен за пределы своего пакета? - PullRequest
6 голосов
/ 13 декабря 2011

Ниже приведен мой ProtectedConstructor.java исходный код:

package protectCon;

public class ProtectedConstructor{
    public int nothing;
    ProtectedConstructor(){
        nothing = 0;
    }
}

И следующий источник UsingProtectedCon.java:

package other;

import protectcon.ProtectedConstructor;

public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**
    public static void main(String... a) {  
    }
}

Когда я компилирую UsingProtectedCon.java, я получаю ошибку в строке 4, показанной выше. Это говорит о том, что ProtectedConstructor () не является публичным; поэтому недоступен вне пакета.

Однако, поскольку мой класс общедоступен, я не смогу расширить его за пределы пакета. В любом случае, я не создаю ни одного его экземпляра.

Теперь, если я сделаю конструктор класса ProtectedConstructor как public или protected, тогда код скомпилируется без ошибок.

Так почему же даже конструктору необходимо быть public или protected, а не просто иметь доступ по умолчанию?

Ответы [ 8 ]

13 голосов
/ 13 декабря 2011

Если вы хотите расширить класс за пределы своего пакета, у него должен быть конструктор public или protected, потому что в Java каждый конструктор должен вызывать конструктор из своего суперкласса.

Из-за этого в каждом конструкторе подразумевается вызов super(), для которого нет this() или явный вызов super() в качестве первого оператора.И если вы вообще не указываете конструктор, Java добавит конструктор по умолчанию без параметров, поэтому ваш код выглядит так:

public class UsingProtectedCon extends ProtectedConstructor {
    public UsingProtectedCon() {
        super();
    }

    public static void main(String... a) {   
    }
}

Другими словами, ваш код не компилируется, потому что вызовsuper() в конструкторе по умолчанию не может быть разрешен.

3 голосов
/ 13 декабря 2011

constructor является членом класса, подобным field и method, поэтому модификатор доступа применяется к нему таким же образом, как и все члены класса

когда вы расширяете класс A в B, его конструктор по умолчанию A будет вызываться неявно из конструктора B (если вы не вызываете ни один из перегруженных конструкторов)

1 голос
/ 13 декабря 2011

в вашем классе ProtectedConstructor определяется с доступом Package-Private Это означает, что вне пакета он не виден даже классами, которые выходят из вашего класса ProtectedConstructor

Определите ваш конструктор с помощью «защищенного» модификатора доступа, и все будет готово:

 package protectCon;

public class ProtectedConstructor{
    public int nothing;
    protected ProtectedConstructor(){
        nothing = 0;
    }
}
0 голосов
/ 13 декабря 2011

Если у child будет конструктор, являющийся приватным для parent, мы можем создать экземпляр child с этим конструктором и привести его к типу parent.Таким образом, чтобы предотвратить это, компилятор Java не позволяет конструктору иметь конструктор, который является закрытым для родителя.

0 голосов
/ 13 декабря 2011

Вы можете иметь конструкторы, которые являются открытыми, защищенными (для внутреннего использования) и даже закрытыми.

Простым примером является String, в котором есть public конструкторы для общего использования и локальные для пакетов конструкторы для внутреннего использования.

Класс ObjectOutputStream имеет открытый конструктор, который принимает OutputStream и protected конструктор, который может использоваться только подклассом.

Кстати: если у вас есть класс abstract, имеет ли смысл сделать конструктор public, как это часто бывает. ;) подсказка: это то же самое, что и protected.

0 голосов
/ 13 декабря 2011

, чтобы избежать путаницы, сделайте это так. пакет protectCon;

public class ProtectedConstructor{
    public int nothing;
    public ProtectedConstructor(){
        nothing = 0;
    }
}


package other;

import protectCon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**

    public UsingProtectedCon(){
      super();
      }


  public static void main(String... a){   
    }
}
0 голосов
/ 13 декабря 2011

JLS 6.6.7 отвечает на ваш вопрос. Подкласс обращается только к защищенным членам своего родительского класса, если он включает реализацию своего родителя. Следовательно, вы не можете создать экземпляр родительского объекта в дочернем классе, если родительский конструктор защищен и находится в другом пакете. Поскольку конструктор по умолчанию подкласса будет пытаться вызвать родительский конструктор класса, вы получили эту ошибку.

См. ТАК сообщение F или подробности

0 голосов
/ 13 декабря 2011

Ваш конструктор не публичный. Область действия по умолчанию - пакет-приват.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...