As per Joshu Bloch's Effective Java,"The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed." Can someone please explain what does this mean? Especially the bolded words. If a static factory method is provided or not, class with private constructor can't be subclassed right?
Providing only static factory methods is that classes without public
or protected constructors cannot be subclassed.
Whenever a constructor of a subclass is called, the constructor of the parent class is also called. In the absence of protected or public constructors, sub classing or extending a class will make no sense. Hence the disadvantage.
Java requires from derived class to ensure that inherited fields will be properly initialized. It is done by making at start of constructor call to constructor of superclass.
Such code should look like
class Derived class Parent{
public Derived(){
super();//this will be added automatically by compiler
//or super(arguments) if you want to use constructor with arguments
}
}
But if superclass doesn't make its constructor accessible (it is privet) derived class can't add super call in any of its constructor. This means that we can't create valid code for constructor, and since all classes must have at least one constructors derived class can't compile.
Related
https://stackoverflow.com/a/7486111/17273668 ; from what I have seen here to make a class "static" , we have to make it final with private constructor and static fields and methods.
Is there any difference between making the constructor private and making the class abstract?
There is a huge difference between making a constructor private, or making a class abstract. Making a constructor private means that the constructor can only be invoked within the class itself or its nested classes, which means it cannot be called from outside. Making a class abstract means that it can only be instantiated by subclassing it. If a class is abstract, but has a non-private constructor (the default constructor is public), it means it can be subclassed by classes in other compilation units.
When it comes to utility classes, making the class final with a private constructor is - in my opinion - the better choice. The alternative is to make it abstract with a private constructor, but I think that is abusing the term abstract. Making something abstract raises an expectation of having concrete subclasses, which is not what you do with a utility class.
An abstract class can be extended by sub classes, a private constructor (if it is the only constructor) prevents sub-classing (exception: nested classes). The only way to instantiate a class with private constructor is by implementing a static factory method in the class itself (e.g. Optional.of).
I have three classes like this:
public abstract class ClassA extends ClassX {
protected ClassA() {
super();
}
// more code
}
public class ClassB extends ClassA {
public ClassB() {
super();
}
// more code
}
public abstract class ClassC extends ClassB {
public ClassC() {
super();
}
// more code
}
I would say that the standard constructor for ClassC is not necessary since Java will insert it during compilation, since there is no other constructor in this class, right?
If true, I could simplify the code for ClassC down to this:
public abstract class ClassC extends ClassB {
// more code
}
Now I'd say that I can't do the same for ClassB since the accessibility of the constructor is increased from protected to public.
I'm asking since I am not 100% sure about this and thought I might be missing something. Especially about the standard constructor that will be inserted into ClassC if I don't implement it myself. In this case it will have accessibility public since it inherits from ClassB. Is that correct?
So my question is: Can I delete the constructor in ClassC without having the code being changed (especially the accessibility of constructors) and is it correct that I can't delete the constructor of ClassB.
Now I'd say that I can't do the same for ClassB since the accessibility of the constructor is increased from protected to public.
That's irrelevant, given that it's an abstract class. The constructor can't be called directly - it's only used when chaining from a subclass constructor.
So while it would be technically different, your code would be effectively the same if you removed all the constructor declarations.
But in terms of the accessibility of default constructors, JLS 8.8.9 is the authority here:
If a class contains no constructor declarations, then a default constructor is implicitly declared. The form of the default constructor for a top level class, member class, or local class is as follows:
The default constructor has the same accessibility as the class (§6.6).
...
The rule that the default constructor of a class has the same access modifier as the class itself is simple and intuitive. Note, however, that this does not imply that the constructor is accessible whenever the class is accessible.
If you do not make a constructor, the default empty constructor is automatically created.
If any constructor does not explicitly call a super or this constructor as its first statement, a call to super() is automatically added.
That means if your constructors are defined with in the scope of the child class then there is no need to call super() explicitly. As in your case you can remove all the constructors. Your program will still compile and run.
Hope this helps. For more please have a look at the shared links, it has some more beautiful examples.
From the Java specification on default constructor.
If a class contains no constructor declarations, then a default constructor with no formal parameters and no throws clause is implicitly declared.
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
So you should be good with not including any of those constuctors.
Why can't constructors be final, static, or abstract in Java?
For instance, can you explain to me why this is not valid?
public class K {
abstract public K() {
// ...
}
}
When you set a method as final it means: "I don't want any class override it." But according to the Java Language Specification:
JLS 8.8 - "Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding."
When you set a method as abstract it means: "This method doesn't have a body and it should be implemented in a child class." But the constructor is called implicitly when the new keyword is used so it can't lack a body.
When you set a method as static it means: "This method belongs to the class, not a particular object." But the constructor is implicitly called to initialize an object, so there is no purpose in having a static constructor.
The question really is why you want constructor to be static or abstract or final.
Constructors aren't inherited so can't be overridden so whats the use
to have final constructor
Constructor is called automatically when an instance of the class is
created, it has access to instance fields of the class. What will be
the use of a static constructor.
Constructor can't be overridden so what will you do with an abstract
constructor.
A Java constructor is implicitly final, the static / non-static aspects of its semantics are implicit1, and it is meaningless for a Java constructor to be abstract.
This means that the final and static modifiers would be redundant, and the abstract keyword would have no meaning at all.
Naturally, the Java designers didn't see in any point in allowing redundant and/or meaningless access modifiers on constructors ... so these are not allowed by the Java grammar.
Aside: It is a shame that they didn't make the same design call for interface methods where the public and abstract modifiers are also redundant, but allowed anyway. Perhaps there is some (ancient) historical reason for this. But either way, it cannot be fixed without rendering (probably) millions of existing Java programs uncompilable.
1 - Actually, constructors have a mixture of static and non-static semantics. You can't "call" a constructor on an instance, and it they are not inherited, or overridable. This is similar to the way static methods work. On the other hand, the body of a constructor can refer to this, and call instance methods ... like an instance method. And then there is constructor chaining, which is unique to constructors. But the real point is that these semantics are fixed, and there is no point allowing a redundant and probably confusing static modifier.
public constructor: Objects can be created anywhere.
default constructor: Objects can be created only in the same package.
protected constructor: Objects can be created by classes outside the package only if it's a subclass.
private constructor: Object can only be created inside the class (e.g., when implementing a singleton).
The static, final and abstract keywords are not meaningful for a constructor because:
static members belong to a class, but the constructor is needed to create an object.
An abstract class is a partially implemented class, which contains abstract methods to be implemented in child class.
final restricts modification: variables become constant, methods can't be overridden, and classes can't be inherited.
Final: Because you can't overwrite/extend a constructor anyway. You can extend a class (to prevent that you make it final) or overwrite a method (to prevent that you make it final), but there is nothing like this for constructors.
Static: If you look at the execution a constructor is not static (it can access instance fields), if you look at the caller side it is (kind of) static (you call it without having an instance. Its hard to imagine a constructor being completely static or not static and without having a semantic separation between those two things it doesn't make sense to distinguish them with a modifier.
Abstract: Abstract makes only sense in the presence of overwriting/extension, so the same argument as for 'final' applies
No Constructors can NEVER be declared as final. Your compiler will always give an error of the type "modifier final not allowed"
Final, when applied to methods, means that the method cannot be overridden in a subclass.
Constructors are NOT ordinary methods. (different rules apply)
Additionally, Constructors are NEVER inherited. So there is NO SENSE in declaring it final.
Constructors are NOT ordinary methods. (different rules apply)
Additionally, Constructors are NEVER inherited. So there is NO SENSE in declaring it final.
No Constructors can NEVER be declared final. YOur compiler will always give an error of the type "modifer final not allowed"
Check the JLS Section 8.8.3 (The JLS & API docs should be some of your primary sources of information).
JLS section 8 mentions this.
Constructors (§8.8) are similar to methods, but cannot be invoked
directly by a method call; they are used to initialize new class
instances. Like methods, they may be overloaded (§8.8.8).
But constructors per say are not regular methods. They can't be compared as such.
why constructor can not be static and final are well defined in above answers.
Abstract: "Abstract" means no implementation . and it can only be implemented via inheritance. So when we extends some class, all of parent class members are inherited in sub-class(child class) except "Constructor". So, lets suppose, you some how manage to declare constructor "Abstract", than how can you give its implementation in sub class, when constructor does not get inherit in child-class?
that's why constructor can't be
abstract .
lets see first
final public K(){
*above the modifier final is restrict 'cause if it final then some situation where in some other class or same class only we will override it so thats not gonna happen here proximately not final
eg:
we want public void(int i,String name){
//this code not allowed
let static,, static itz all about class level but we create the object based constructor by using 'new' keyword so,,,,,, thatsall
abstract itz worst about here not at 'cause not have any abstract method or any declared method
Unfortunately in PHP the compiler does not raise any issue for both abstract and final constructor.
<?php
abstract class AbstractClass
{
public abstract function __construct();
}
class NormalClass
{
public final function __construct() {
echo "Final constructor in a normal class!";
}
}
In PHP static constructor is not allowed and will raise fatal exception.
Here in AbstractClass obviously a constructor either can be declared as abstract plus not implemented or it can be declared as something among (final, public, private, protected) plus a function body.
Some other related facts on PHP:
In PHP having multiple constructor __construct() is not possible.
In PHP a constructor __construct() can be declared as abstract, final, public, private and protected!
This code was tested and stood true for in PHP versions from 5.6 up to 7.4!
I am little confused about abstract class in java. I know that whenever there is an abstract method in the class compiler force developer to mark class abstract. But even we don't have any abstract method in the class we still mark the whole class as abstract. I am not getting the point why we can do this. what is the purpose to allow developer to mark class abstract when there is no abstract method. One can say that reason is that we don't want to create instance of that class. If that the reason then marking constructor of the class private is more suitable rather than marking class abstract.
There is a very useful reason for having an abstract class without abstract methods: Providing default implementations for overridable methods.
There are several perfect examples in the JDK itself. Look - for example - at a WindowAdapter. It implements the WindowListener interface (among others), but provides empty not-doing-anything method implementations. In most cases you want to register a window listener that only overrides one or two of the interface methods. Then your own class simply extends WindowAdapter instead of implementing WindowListener.
Note, that with Java 8 default methods in interfaces this reason does not hold anymore, and in fact abstract classes without abstract methods do not make sense anymore.
I think it's to allow subclasses to be created but not the main class.
I guess your class has method stubs in it, otherwise tyere would be no reason not to instantiate it. It is generally better to use abstract methods for this.
For restricting the class to be instantiated.. Example HttpServlet class.. it is defined abstract but has no abstract methods.. We can use these methods in the subclasses but creating the class httpservlet itself is useless.. thats the reason i think..
HTH!
As stated, this can be to prevent instantiation. I strongly prefer private or protected constructors over this as I feel they communicate the intent more clearly.
Also, in a class hierarchy, if class A is abstract and contains an abstract method, that method does not need to be defined in a class B which extends class A. In this case, class B is marked as abstract and has no abstract members.
To prevent instantiation of a class and use it as a base class. For example, HttpServlet class, an example of template method design pattern where each method already has a behaviour defined. The child class is free to override one or more of them instead of all of them.
One can say that reason is that we don't want to create instance of
that class. If that the reason then marking constructor of the class
private is more suitable rather than marking class abstract.
No it is not at all suitable
This below example will clear your doubts , If you use private constructor , Not only your Object creation is blocked but also you can not even create a subclass of the Parent class
class ParentClass{
private ParentClass(){
}
}
class Subclass extends ParentClass{
static{
System.out.println("Hello");
}
}
You will get compile time error saying
error: ParentClass() has private access in ParentClass
But Marking a class as abstract will block Object creation but will not block Inheritence in java
Update
As you asked in comments that you can make it protected but then your class can be easily instantiated , because protected member can be accessed from the same class as well as in SubClass in same package as well as in a sub class in another package .
A class automatically becomes abstract class when any of its method declared as abstract.
I take this point in some blog. Can someone explain me Why entire class becomes abstract when we use only one abstract method.?
Because it can't be instantiated directly anymore. Also, it's then a compiler error if you don't mark the class itself as abstract.
First of all, I'm going to guess that the blog you mentioned was actually discussing C++. In Java, it's a compiler error to declare an abstract method within a class that is declared with the abstract keyword. With that said, Consider this (erroneous) code:
class A
{
abstract void foo();
}
A a = new A();
a.foo(); //Whoa! what are we supposed to do??!
If A had been declared as abstract (as would be required in real code), it would have been impossible to instantiate it.
If any part of a class is missing (that is, it is declared abstract), the class must be abstract because parts of it cannot be used.
In C++, there is no abstract keyword-- a class is automatically abstract if it has any abstract methods (referred to as pure virtual functions in C++).
In Java on the other hand, a class is only abstract if it is declared with the abstract keyword. However, this keyword is required if there are any abstract methods, so the only difference between the two systems in practice is that Java allows abstract classes to not have any abstract methods. In both languages, a class must be abstract if it has any abstract methods: in C++, this is simply how abstract classes are defined, and in Java it is required via the mechanics of the abstract keyword.
Once a method is abstract, it is declared to have no implementation. How would you suggest the VM instantiate an instance of that class?
An abstract method is one that defines a contract for a method but does not implement the functionality.
To instantiate a class with methods that cannot meet the contract defined as there is no implementation wouldn't work. Thus an abstract method means that you should not be able to instantiate the class.
A class automatically becomes abstract class when any of its method declared as abstract.
Can someone explain me Why entire class becomes abstract when we use
only one abstract method.?
The class has to be declared Abstract because the compiler expects a body for a normal class's method otherwise it will throw error. So either you write the method's body or declare the class Abstract
Example:
class SomeClass{
// Method without body
public void SomeMethod();
public static void main(String[] args) {
}
}
When you try to compile it, you will get:
SomeClass.java:4: missing method body, or declare abstract
public void SomeMethod();