what is the need of multiple class modifiers in java? - java

While reading oracles Java documentation(chapter 8) I came across this interesting piece of line:
"If two or more (distinct) class modifiers appear in a class declaration, then it is customary, though not required, that they appear in the order consistent with that shown above in the production for ClassModifier."
and here is the Class Modifiers
ClassModifiers:
ClassModifier
ClassModifiers ClassModifier
ClassModifier: one of
Annotation public protected private
abstract static final strictfp
My question is what is the need for multiple class modifiers? when we can make use of multiple class modifiers?

Well, you can have a public abstract static strictfp inner class; each one of those is orthogonal to the rest. In general, you can group them in the following way:
public/protected/private: access modifiers - determining who has access to the class literal.
abstract/final: inheritance modifiers
static: only for inner classes
strictfp: it's orthogonal to everything else.

Two examples:
public final class MyClass { }
protected abstract class MyClass {}

Simply, to create a class that has the features dictated by several modifiers. Not all the modifiers are mutually exclusive. For example, abstract disallows making instances of the class, and public makes the class accessible even outside its package. Hence, to make an abstract class that's accessible outside its own package, you'd need to make it public abstract class.

Related

Why interface and abstract class could have default access modfier and not protected [duplicate]

Why can we not define a class as protected?
I know that we can't, but why? There should be some specific reason.
Because it makes no sense.
Protected class member (method or variable) is just like package-private (default visibility), except that it also can be accessed from subclasses.
Since there's no such concept as 'subpackage' or 'package-inheritance' in Java, declaring class protected or package-private would be the same thing.
You can declare nested and inner classes as protected or private, though.
As you know default is for package level access and protected is for package level plus non-package classes but which extends this class (Point to be noted here is you can extend the class only if it is visible!).
Let's put it in this way:
protected top-level class would be visible to classes in its package.
now making it visible outside the package (subclasses) is bit confusing and tricky. Which classes should be allowed to inherit our protected class?
If all the classes are allowed to subclass then it will be similar to public access specifier.
If none then it is similar to default.
Since there is no way to restrict this class being subclassed by only few classes (we cannot restrict class being inherited by only few classes out of all the available classes in a package/outside of a package), there is no use of protected access specifiers for top level classes. Hence it is not allowed.
public class A
{
protected class B
{
}
}
Defining a field protected makes that field accessible inside the package as well as outside the package through inheritance only (Only inside the child class).
So If we are allowed to make a class protected then we can access it inside the package very easily but for accessing that class outside of the package we first need to extend that entity in which this class is defined which is its package.
And since a package can not be extended (can be imported), defining a class protected will again make it package-private which is similar to defining it as default which we can already do.
Therefore there is no benefit of defining a class private it will only make things ambiguous.
For more information read Why an outer Java class can’t be private or protected
#Nikita Rybak answer has good points but lack of details, i can't simply get the idea without think deeply myself, the following is what i thought and now i should completely understood the reason.
Four access modifiers, assume the 1st level is public and 4th level is private (based on this table in sequence). The first thing we should know is why class cannot defined as private in top-level.
So if "private class foo"(A private member defined, i.e. class itself is a member) allow, what is the outer (which contains the member) ? File scope ? No, file outer is pointless because even multiple classes in single file will be compile into separate class files. So the outer is package. But the 3rd level default access modifier already means "package-private". So the 4th level private access modifier will not be used/allowed.
But nested private class is allow because the direct outer is class, not package, e.g.:
class PrivateNestedMain {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Now what if "protected class foo" allow ? protected main characteristic is subclass, so the outer(package) SHOULD(due to up-to scope, but still it's optional) provide style of subclass, i.e. sub-package, or package A extends package B, but we know no such thing. So protected can't use full potential(main scope is subclass-wide) in top-level which the outer is package(i.e. no such sub-package thing), but protected can use full potential in nested class which the outer is class(i.e. can be subclass):
class ProtectedNestedMain {
protected static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Note that the above said "can't use full potential" due to it can't reach subclass-wide merely because no outer subclass, that's means actually protected can be allow, it's just a matter of choice to avoid duplicate the job of package-private if outer not subclass-able, see below.
My confusing is mainly caused by the famous table at https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html:
If 1st level(public) and 3rd level (package-private) allowed, how on earth the in-between 2nd level (protected) not allowed ?
public support subclass so easy to misleading. The correct way to read this table is
public support subclass if the outer has subclass feature.
The same misleading apply to package-private, package-private doesn't support subclass (N in cell) doesn't means subclass concept apply in outer.
That's means we should ignore the Subclass column if subclass feature is not available in outer:
As we can see now, both protected and package-private are the same level now (Y-Y-N), no more confusion about why in-between level is not allowed. Overall, Java pick only package-private over protected to avoid confusing(it's just a matter of choice, but protected main characteristic is subclass, so package-private is superior), and the result, only 2 access modifiers allowed in top-level:
At the top level—public, or package-private (no explicit modifier).
Protected is not similar to public. Protected has both package level access plus can be accessed outside of packages only by inheritance..If a class say A outside a package INHERITS a class from other package(with protected method by using INHERITANCE) it can access the methods of this class B which has protected methods but the sub-classes derived from this class i.e., A can't access the protected methods..the opposite happens with public..
Example:
package 2;
class B
{
protected void method1()
{
}
}
package 1;
import 2.B;
class A extends B
{
//can access protected method
}
class C extends A
{
//can't access the protected method
}
if a outer class is declared by protected, I think you want the class can be only accessed from same package and its subclass but different packages. However, there is no possible to create subclasses for a protected class, because when you write "class Dog extends Animal", because of protected "Animal" only can be accessed by its subclass, obviously, "Dog" is not "Animal" subclass.
So protected outer class is same with (default) outer class!
behavior of “protected” = behavior of “default”+ “use it in any subclass in any package”.
Anyway we have default access modifier for class, only advantage we can get from protected access modifier is:- by using it in any package through subclassing. But for subclass, visibility of parent “protected”class would be private. So it can’t be accessed. Basically if you have a protected top-level class, no outer class can gain access by subclassing it. So protected for a top-level class is meaningless.
Protected : VISIBLE only to package level*.
class is defined protected ---> it cannot be extended from outside package(not visible).
And if it cannot be extended then it is meaningless to keep it as protected, because then it will become default access which is allowed.
Same applies to private defined classes.
Note : Nested or inner classes can be defined protected or private.
* : Explore protected keyword, for this answer I made it succinct.
The answer from #Akash5288 made no sense to me:
If all the classes are allowed to subclass then it will be similar to public access specifier.
Since there is no way to restrict this class being subclassed by only few classes (we cannot restrict class being inherited by only few classes out of all the available classes in a package/outside of a package), there is no use of protected access specifiers for top level classes. Hence it is not allowed.
You can then apply the same logic to protected methods and variables, they are also then "similar to public". All classes outside of a package can extend our public class and use its protected methods. Why is restricting methods and variables to extended classes ok, but restricting the whole class not ok? "Similar to public" is not "same as public". My interpretation is that it is perfectly fine to allow a protected class, as it is fine to allow protected methods.
The answer "you can not extend a class you can not access/see" is more logical.
What makes sense to this question is that, JVM is written in C (Sun JVM) and C++(oracle JVM) so during compilation, we are going to create .class files out of our java file and if we declare a class with Protected keyword then it will not be accessed by JVM.
The answer why protected class will not be accessed by JVM is that, since protected fields are accessible within same package or to diffrent package through inheritance only and JVM is not written in a way so that it will inherit will class.
Hope this satisfies this question :)
Similarly, A top level class can't be private. Explanation as below:
So what will happen if we will define a class private, that class will only be accessible within the entity in which it is defined which in our case is its package?
So defining private access to the class will make it accessible inside the same package which default keyword already do for us, Therefore there is no benefit of defining a class private it will only make things ambiguous.
protected means that the member can be accessed by any class in the same package
and by sub classes even if they are in another packages.
Example:
package a;
class parent{
protected void p();
}
package b;
import a.p;
class child extends parent{
//you can access method which is protected in the parent in the child
}
class another extends child {
//here you can not access the protected method
}
The protected modifier is allowed on an inner class. But still an instance of this inner class cannot be constructed from within a class extending the outer class. Only when the constructing code is within the same package it is allowed by the compiler. But what difference does the protected modifier then make with respect to the default accessibility?
So, from my point of view, the protected modifier is not at all allowed on top-level classes, and it does not make sense on embedded classes.

Java 8: Better to extend class of static methods or better to call static methods directly?

I'm updating some old Java 4 code to Java 8 (way too much to paste here) and the original programmer chose to have nearly every class of theirs extend this single HUGE class full of only static methods and constants, but I do not know their reasoning.
ex:
public class BaseClass{
/* this class has a huge amount of ONLY static methods/constants */
public static final int STUFF_DONE = 1;
public static String getStuff(){
String stuff = "this is my stuff.";
return stuff;
}
...
}
public class SuperClass extends BaseClass{
/* this class has only a few methods */
public String labelStuff(){
return getStuff();
}
}
public class MyClass extends SuperClass{
/* there are many classes that extend SuperClass like this one */
public int handleStuff(){
String myString = labelStuff();
return STUFF_DONE;
}
public static void main(){
if(handleStuff()) System.out.println("Done.");
}
}
My question is this... is it better to keep this design or is it better to remove the inheritance of the static methods/constants and simply call those methods/constants statically?
"Better" to me is defined as lower memory consumption (again, this base class is quite huge) as CPU is likely not affected by this. What are the benefits/pitfalls of this approach?
My concern is that because BaseClass is so huge that I'm wasting a LOT of memory for usage of only one or two methods/constants in the inheriting classes that I could just be calling statically.
Static members aren't "inherited" per se. They live on the base class regardless of which subclass they're called from, so I doubt there's any memory impact.
The reason for creating all classes as a subclass of this common class is just for easy access to static members without the qualifying class name. A common variation is to inherit from an interface that declares a bunch of static fields. The upside is that implementing an interface doesn't interfere with inheritance the way a superclass would (you can only extend a single superclass). The downside is that until Java 8 it wasn't possible to declare static methods on an interface.
In any case, this trick is generally considered an anti-pattern and has been superseded by static imports.
Inheritance is to customize the behavior of the parent class for the child classes.
Static methods cannot be inherited and their behavior does not change due to the state of the object.
So you cannot make something static and inheritable. There is no sense to extend a class of full static methods. Also, this does not change the size of the memory usage. Your classes are already loaded.
There are beautiful insights written above by members. I would like to put it in different words if it helps understanding.
Inheritance :
All the member variables and functions of parent classes are included in the child class based on visibility operator (public, private , protected )
Static members:
The static members of class are stored in memory accessible to all instance variables of the class. It's like a shared spaced for all the instance variables belonging to that class
Now coming to inheritance of static variables and functions , it's always advisable to have static imports.

Why `private static` field is not allowed in Java 8 interface?

When I'm trying to compile the following code
public interface SomeInterface{
private static Logger logger = Logger.getLogger();
public default void someMethod(){
logger.info("someMethod: default implementation");
}
}
I get an error
Illegal modifier for the interface field SomeInterface.logger; only public, static & final are permitted
When I delete private modifier, code compiles, but I don't want other classes from the package to see this field.
Why Java doesn't allow me to do such thing when it actually does make sense?
In the pre-Java-8 view of the world, interfaces were purely for interface contracts, and private members exist purely for implementation, so this restriction was completely sensible.
In the post-Java-8 world, where interfaces can carry behavior (but not state), it starts to be reasonable to ask whether other features of classes should be applied to interfaces as well. (However, just because something might be "reasonable" doesn't mean it must be supported; there is often more than one reasonable way to construct the world.)
In Java 9, private methods in interfaces will be supported.
Interfaces are not classes. They have no private state. Even a public logger in the interface is a design smell and an abuse of interfaces.
The use case for static fields in interfaces is mainly for compile-time constants, not for stateful objects.
The goal of interface is to define something implemented by other classes. A private field does not define anything as it is not visible outside the interface. Hence it does not make any sense in this construct. It may be some hacks how to use it (maybe from interface inner classes) but would not look like a good design anyway.
If you actually implement part of the functionality, use abstract class instead.
Interface is like a blueprint of any class, where you declare your members. Any class that implement that interface is responsible for its definition.
Private members can only be accessed by same class member, which does not make sense in terms of interface.
Protected members can be accessed by same class member and inherited class members, but in case of interface we never extend an interface, we implement it. So any interface can only contain public methods generally,
public interface SomeInterface {
public default void someMethod() {
SomeInterfaceInternal.logger.info("someMethod: default implementation");
}
}
final class SomeInterfaceInternal {
protected static final Logger logger = LoggerFactory.getLogger(SomeInterface.class);
}

Access not allowed to a static inner interface

I have the following situation.
package A;
class SampleClass
{
static interface sampleInterface
{
....
}
}
Now when I try to import the sampleInterface from another package , jDev says 'access not allowed'. What could be the problem?
Currently, the interface is seen as package-private (there's no visibility modifier, so that's the default). Place public on the outer class and the interface, and it will become visible to other classes.
Just be careful - if you get caught in a situation where you have to do this:
public class Alpha extends Alpha.IAlpha {
public void doNothing();
public static interface IAlpha {
public void doNothing();
}
}
...you'll have an issue with cyclic inheritance, and your class won't compile. In fact, you won't be able to use the interface at all.
Keep these rules in mind for exposing interfaces, classes, or enums:
If you only need an inner class, interface, or enum for that particular object, then it's fine to declare it as static.
If you need a class, interface, or enum accessible from anywhere but that object, then it's best to move it out of the inner class, and into its own file.
In general, interfaces are seen as APIs to conform by - there's really no benefit in having them as nested unless the scope of them is extremely narrow.
Change visibility of the class and the interface to public. It will work for sure.
When you declare a class without a access specifier it is by package-default. This means you can access that class in that package only.
If you want to access class from another package, make class public, i.e.
public class SampleClass
Similarly, in your case, as you want to access the Interface as well, you have to make that interface public as well.
This will solve your problem.

Why interface can only be declared in top-level class?

Alright, I know it's the rule:
According to JLS: 8.1.3 Inner Classes and Enclosing Instances, inner
classes may not declare static initializers or member interfaces.
Inner classes may not declare static members, unless they are
compile-time constant fields.
According to 8.5.2 Static Member Type Declarations, "Member interfaces
are always implicitly static. It is permitted but not required for the
declaration of a member interface to explicitly list the static
modifier". They are always top-level, not inner.
I just wonder why. What may happen if we are allowed to declare interface within an inner class? Won't inner class become top-level class if I put it into another Class file?
Won't inner class become top-level class if I put it into another Class file?
No, it still is an inner class, which the filename indicates (IIRC it's OuterClass$InnerClass.class).
Inner classes have access to the outer class' attributes, i.e. they depend on their outer class' instance. With interfaces you couldn't do this. Think of a completely unrelated class that would have to be created by the corresponding outer class' instance. How would that be done if the outer class doesn't know who implements that interface?
What you can do is declare static interfaces in your outer class, thus merely using the outer as a namespace:
public class OuterClass {
public static interface InnerInterface { //protected and private would be fine too, depending on what makes sense
}
}
Edit: actually, I misread the question and since interfaces are static anyways, here's an updated code snippet:
public class OuterClass {
public static InnerClass { //static inner class making OuterClass just be a namespace
public interface InnerInnerInterface { //protected and private would be fine too, depending on what makes sense
}
}
}
As a workaround you could define an abstract inner inner class, with the drawback that you have to stick to the single inheritance constraint.
Think of it in terms of static vs. non-static context. A "top-level" class establishes a static context because it can be accessed without any enclosing instance. I.e. you can access top-level classes from a main method. The same applies to any static members of a top-level class. An inner class, however, neither exists in* nor establishes any static context. Therefore it can't have any static members, and it can only be accessed via an instance of its containing class, like constructors and other instance members. From a main method, you wouldn't be able to say Outer.Inner.SOME_FIELD because members of an inner class only have meaning with respect to the containing class.
*sort of
By definition a top level class and its inner class(es) are tightly coupled. Interfaces are a means of reducing coupling.
Inner classes are supposed to be implementation details of the top-level class and should therefore be invisible to the client. Any functionality you wish to access of an inner class should be done so through the top-level class, because conceptually speaking, that functionality should be visible only as functionality of the top-level class, so that the class designer can swap out or otherwise drastically change inner classes without breaking clients' builds.

Categories