I have an abstract class which looks like:
abstract class AbstractFoo implements Bar {
//Code goes here
}
However when I try to make AbstractFoo protected I get an error compile time error complaining that it is an illegal modifier.
protected abstract class AbstractFoo implements Bar {
//Code goes here
}
Why can't you have a protected abstract class within Java?
EDIT: I should probably mention that this is not vanilla Java and is actually Blackberry / J2ME.
As many others have noted, the restriction here has nothing to do with the fact that your class is abstract, but rather in the visibility modifier you have chosen to use. Keep in mind what each of these visibility modifiers means:
For the class in which you are using the keyword...
private: Only visible to this class
(default/package private): Only visible to this class and classes in its package
protected: Visible to this class, classes in its package, and subclasses of this class
public: Visible to any class
Top level classes cannot be declared private, because then nothing would ever be able to access them.
But your question stems around why they may not be declared protected. It is clear that a protected top-level class (were it able to exist) would be visible to itself (every class is visible to itself). It is also clear that a protected top-level class would be visible to classes in its package. However, making it visible to its subclasses is tricky. Which classes should be allowed to inherit our protected class?
If it is all of them, then our class might as well be public, because then we're saying that any class has the right to access our protected class. If it's none of them, then our class might as well be package-private, since only the other two conditions (being visible to itself and things in its package) are met. And it can't be "some of them," since we would need a way of defining which classes can access it, which is what the visibility modifier was for in the first place.
So for these reasons, top-level classes cannot be private or protected; they must be package-private or public.
Top level classes can only be public or package-private (default).
public class PublicClass {
protected class InnerClass { } //protected makes sense here
}
class PackagePrivateClass { }
Since: PublicClass and PackagePrivateClass are both top-level classes here they cannot have other access-modifiers, private and protected.
Only the public and the default access-modifiers are allowed for the top-level classes.
But for the inner member classes other modifiers are also allowed.
That abstract has nothing do here most probably.
You can; the following code compiles fine:
public class Main {
interface Bar {}
protected abstract class AbstractFoo implements Bar {}
public static void main(String[] args) {}
}
I do not believe the premise of the question. I successfully compiled the below code:
class prot
{
public abstract class pubab
{
}
protected abstract class protab
{
}
abstract class packprivab
{
}
private abstract class privab
{
}
}
which suggests to me you can have a protected abstract class in java. For that matter you can have a private abstract class.
Did you try to have a protected top-level class (not allowed)?
IMO, it does seem like an illegal modifier because protected means it should be visible in the package + in the derived classes. But in order to declare that some class extends this protected class you first need to be able to see it from there, which can't happen because it's visible only from the derived classes(given that super class and subclasses aren't in the same package).
If you only want to be able to see the class from other classes in the same package the default(package-private) modifier will work, no reason for the protected modifier to work - it only adds a completely unlogical and useless ability to see the class from its derived classes, which
a) can't happen if this class and its derived classes aren't in the same package.
b) can happen, given that this class and its derived classes are in the same package - this will work with the default (package-private) modifier anyway.
Top level classes cannot have protected scope, only public or package. Here's a nice reference explaining the allowable uses of scoping modifiers on classes.
Related
import java.util.*;
public class NewTreeSet2{
void count(){
for (int x=0; x<7; x++,x++){
System.out.print(" " + x);
}
}
}
protected class NewTreeSet extends NewTreeSet2{
public static void main(String [] args){
NewTreeSet2 t = new NewTreeSet2();
t.count();
}
}
Here, I cannot make the NewTreeSet sub class as protected. Why is this? I am not trying to accomplish anything, this is only for my understanding of the access specifiers.
public is the only access-modifier that can explicitly be applied to a top level class in Java. The protected modifier in case of a class can only be applied to inner classes.
Section 8.1.1 of the Java language specification says this :
The access modifiers protected and private pertain only to member classes within a directly enclosing class declaration
So why can't top level classes be marked as protected? The purpose of protected access modifier in Java is to add restrictions on the access to a member of a class. Since a top level class is not a member of any class, the protected access modifier does not make sense for top level classes. Inner classes can be marked as protected because they are indeed members of a class. The same rules apply for private as well.
A class definition itself can only be public or package-private. Public classes must be defined in their own file and the filename must be the class name.
The documentation doesn't say anything about why there are only two access modifiers for the top level, but one might say that it is logical:
The protected access modifier makes sure only instances of the same or a child class can access the subject. Polymorphism is not applicable to classes, only to instances of classes. Thus the protected keyword there doesn't make sense.
If you want to protect the construction of objects, you should specify an access modifier to your constructor.
"Why can't we have the 'protected' modifier for a top-level class".
Assume it's allowed to use protected modifier for a class. Then what will happen, it will be visible to all the classes in the same package which is the same behavior what a default (package-level) access class will possess. Additionally this 'protected' class should be visible to all the subclasses outside package also. But unfortunately you would not be able to create any subclass of this class outside the package because this class itself will not be visible outside the package. Hence without the subclass specific behavior, this 'protected' class will be exactly same as a package-level or default access class. So, there is absolutely no need of 'protected' modifier for classes and hence, not permissible as well.
---This was posted in a different forum, by B Verma, found this answer according to which all of you said. It was really helpful, thank you.
http://www.coderanch.com/t/585021/java/java/Protected-access-modifier-class-level
This question already has answers here:
Should we declare a public constructor when the class is declared as package private?
(2 answers)
Closed 8 years ago.
I am new to Java. I want to know what it is the use of public constructor in a private class. Private class inside the class can be initialized from the same class then what it is the use to make the constructor of private class to public?
public class MainActivity extends Activity {
private class AcceptThread extends Thread {
public AcceptThread() {
}
}
}
There doesn't seems to be any real use case for public or protected modifiers with private classes. If you have multiple classes in a single file though (but not nested or local), you need non-private constructors to instantiate the private classes.
// X.java
public class X {
private Y y = new Y();
}
class Y {
Y () {
// if this were private, X wouldn't be able to create an instance of Y
}
}
Actually default or protected visibility would be enough to create an instance in this case. All non-private modifiers allow you to create instances from other classes within the same package but practically have the same visibility.
The private class isn't visible to classes outside of the package, so public methods have no use here.
The private class can't be extended by classes outside of the package, so protected has no use either.
Even when using reflections, a public constructor is not accessible by default from other packages and will throw a IllegalAccessException. It checks the class visibility first, then the member visibility.
The default modifier is the most restrictive modifier that allows you to directly call the constructor from other classes, so package-private seems to be the most appropriate visibility for the constructor and also any other non-private methods. This also has the advantage that if you change the class visibility in the future, you don't accidentally expose the constructor or any methods to the public.
You know, I ask myself this question almost each time I make a private inner class, but I always assumed that there could be some (possibly contrived) reason for a public constructor. So #kapep 's answer got me tingling and encouraged to find ways to require a public constructor on a private inner class, but the more I think and experiment with it, the more I think the holes are plugged.
Possible angles, all of which failed me:
Serialisation: When unmarshalling an object whose superclass is not serializable, the superclass needs a no-arg constructor accessible from the subclass. So, protected should always suffice here.
Reflective tools: Code that uses reflection to get the inner class constructor through a returned instance. Fails because the type visibility is checked first, as #kapep pointed out, though it leaves a rather interesting error message:
Exception in thread "main" java.lang.IllegalAccessException: Class A can not access a member of class contrived.B$C with modifiers "public"
Inner class extension shenanigans: Don't try this at home:
package a;
class Outer {
private class Inner {
}
}
package b;
// compile error: Outer.Inner has private access in Outer
class Extender extends a.Outer.Inner {
Extender(a.Outer outer) {
outer.super();
}
}
Seemed promising at first, but I didn't get too far with that one.
In the end, I could not find a way to make a public constructor on a private inner class useful.
Then why is this technically legal despite having no use? Probably because the compiler automagically inserts a no-arg public constructor when no other constructor is provided. Hence the language should not disallow this constructs. More of an artefact than a reason, though.
I have code very much like the following.
package my.pkg;
public abstract class X {
private CapableField field;
public abstract void doSomething();
public X(CapableField fieldValue) {
this.field = fieldValue;
}
}
And:
package my.pkg.sub;
public class Y extends my.pkg.X {
public void doSomething() {
this.field.doSomething();
}
}
Why is this even legal code in Java? I thought "private" meant that the field will not be directly accessible in subclasses, and that this was a fairly basic tenet of class inheritance. Making X concrete instead of abstract changes nothing.
What do I do if I specifically want a field, or member function, to be accessible only inside the class where it is defined, and not in some random subclass of the defining class?
This is not true. Most likely you've actually definied Y as an inner class. This way the private fields of the outer class are indeed visible like that.
Doesn't compile for me too! I suspect your Java implementation.
This is impossible. May be you missed something when you explain your question.
private members are not visible in inheritance except in inner class scope. If you want them to be accessed by the subclass then declare them as protected. or use setters and getters.
and in your code you used package keyword in your package declaration which is not allowed and gives compilation error.
Make sure that your classes in two different files. for example X.java and Y.java and y not an inner class
Is it possible to define a private abstract class in Java? How would a Java developer write a construct like below?
public abstract class MyCommand {
public void execute()
{
if (areRequirementsFulfilled())
{
executeInternal();
}
}
private abstract void executeInternal();
private abstract boolean areRequirementsFulfilled();
}
You can't have private abstract methods in Java.
When a method is private, the sub classes can't access it, hence they can't override it.
If you want a similar behavior you'll need protected abstract method.
It is a compile-time error if a method declaration that contains the keyword abstract also contains any one of the keywords private, static, final, native, strictfp, or synchronized.
And
It would be impossible for a subclass to implement a private abstract method, because private methods are not inherited by subclasses; therefore such a method could never be used.
Resources :
JLS - 8.4.3. Method Modifiers
JLS - 8.4.3.1. abstract Methods
That would be protected instead of private. It means that only classes that extend MyCommand have access to the two methods. (So do all classes from the same package, but that's a minor point.)
I am not able to understand why this code doesn't compile:
class A {
public static void main(String[] args) {
System.out.println("hi");
}
}
private class B {
int a;
}
I am saving the contents in a file named A.java - and I get an error:
modifier private not allowed here // where I have defined class B
This happens both when I try B as private and protected. Can someone please explain me the reason behind this?
Thanks !
From the Java Language specification:
The access modifiers protected and private pertain only to member classes within a directly enclosing class declaration
So yes, the private and the protected modifiers are not allowed for top level class declarations.
Top-level classes may be public or not, while private and protected are not allowed. If the class is declared public, then it can be referred to from any package. Otherwise it can only be referred to from the same package (namespace).
A private top level class wouldn't make much sense because it couldn't be referred to from any class. It would be unusable by definition. private is OK for member classes to make a class referable to only it's enclosing class.
A protected member class can be referred to from (1) any class of the same package and from (2) any subclass of the enclosing class. Mapping this concept to top level classes is difficult. The first case is covered by top level class with no access modifiers. The second case is not applicable for top level classes, because there is no enclosing class or something else from a different package with a special relation to this class (like a subclass). Because of this I think, protected is not allowed because it's underlying concept is not applicable for top level classes.
Make the B nested of A, like this:
class A {
public static void main(String[] args) {
System.out.println("hi");
}
private class B {
int a;
}
}
Or move B to a separate file. Also you can stick with default access level,
this way the class can be accessed only from within the package:
class A {
public static void main(String[] args) {
System.out.println("hi");
}
}
class B {
int a;
}
private and protected are meaningless to be allowed to a top level(not member) class/interface.
They are applicable only to the class members which can be variables, constants, constructors, methods, classes, and interfaces.
Why:
(1) private: What may be the meaning/purpose if we define a class as private. Its scope should be private to some area. default access is already package private. And nobody wants a class to be source file private, (Guessing the reason) it may not be a good programming practice to allow because java applications are finally organized in the form of packages, but not in terms of source files. Any source file should be part of some package, so in broad/final view each class/interface is part of some package, not just of some .java file. So not applicable.
(2) protected: If something is protected it should be available only within package and only to the sub classes in other packages. To extend a class in a different package, it should be available to all the classes in other packages, but protected says class should be available only to the classes extended it. It's a kind of deadlock situation. So not applicable.
Source: My readings and understanding
Just have no private/protected modifier at all.
B needs to be private to something. Place it within the definition of class A or create another file, B.java, and define it there, but then it cannot be private.
If you don't use the public keyword for the class it will be private by default (visible only within the file).
There can be only one public class per .java file, all the others need to be private. So class A can be public and class B doesn't need any modifiers in your example. The public class name must match the .java file name (eg. A.java can only contain one public class called "A").
A.java cannot contain two classes.