Possible Duplicate
The top answer given there states that the protected constructor can be called using super() but cannot be instantiated using new? Why so? And if that is the reason then what is the difference between package-private(no modifier) and protected constructor?
The following code is not getting me any difference.
package pack1;
public class Rr {
protected Rr() {
System.out.println("Rello");
}
}
package pack2;
class Tt extends pack1.Rr {
Tt() {
super(); //works
pack1.Rr r = new pack1.Rr(); //error
}
}
class Uu {
public static void main(String args[]) {
Tt t = new Tt();
}
}
A protected method can be accessed via its sub-class objects.
Note, "sub-class" here is very important, which means "via a sub-class way", not "anywhere within a sub-class".
Let's look at an example.
Following are 2 classes:
package one;
public class A {
protected A() {} // protected constructor
public A(int i) {} // public constructor
protected void foo() {} // protected method
}
package two;
import one.A;
public class B extends A {
public void bar() {
this.foo(); // correct
A a = new A(0); // call A's public constructor to construct an A instance.
a.foo(); // compiler error: the method foo from the type A is not visible.
}
}
The first invocation is permitted, but the second not, why?
Like I said, the first one is accessing via "a sub-class way", in which this is A's sub-class instance; however the second just "within a sub-class" (here B is no meaning to A, it's just an ordinary class, so it can not access A's protected method).
Another example is Object.clone. This is a protected method of root class Object. You might likely say it can be accessed from any object created from any class, but the answer is capital "NO": only those codes which are using "sub-classes way" can access it.
The following illustrates this:
this.clone(); // ok
Object o = new Object();
o.clone(); // compiler error: the method clone from the type Object is not visible.
A "default constructor" is a constructor that Java generates if you don't provide one yourself; it's always has the same access as the class itself and has no arguments. Ie when you define
class YourClass {}
the system makes it
class YourClass {
YourClass() {} // default constructor
}
If you create a any other constructor - even a public one with no arguments - it is not a default constructor. The second code piece above would prevent the system from generating one, because you already declared it.
The same is true if you create a protected constructor. Compare:
public class Class1 {}
public class Class2 {
protected Class2() {}
}
you can instantiate Class1, but not Class2:
// invokes autogenerated default constructor
Class1 c1 = new Class1();
// compile error: default constructor is not generated because you declared a protected one
Class2 c2 = new Class2();
As #Turing85 states in a comment, the protected modifier only means that the declared constructor can only be invoked within the proper access scope - from subclasses or classes in the same package.
For completeness' sake: you can call both super() and the constructor explicitly from a subclass:
class Class3 extends Class2() {
public Class3() {
// call to protected constructor of Class2
super();
// explicit call to constructor by creating new instance
Class2 o = new Class2();
}
}
EDIT: I just tried it out, and the last sample is only valid if the two classes are in the same package. I don't know and would like to know.
protected gives access to subclasses, in addition to the classes in the same package.
When you call the constructor directly, e.g. new A() you can think of it as calling a static method. There is no instance of the class yet, thus inheritance rules cannot apply. Therefore, static access rules apply: if the constructor is protected, then it must be in the same package in order to be accessible.
Once you are inside a constructor code and you call super(), then you already have an instance, so if you are in a subclass and call the protected constructor it will work.
Related
In the book Java: The complete reference
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor
It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.
Why did the Java Language designers consider it necessary to do so?
As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.
As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.
Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.
To illustrate this, consider a very simple set of classes:
public class Super {
private final String name;
Super() {
name = "default";
}
public String name() {
return name.toUpperCase();
}
}
public class Sub extends Super {
public Sub() {
// don't do anything
}
}
When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.
You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.
Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
more here
Because it says so in the Java Language Specification.
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:
public abstract class TestA {
private int a;
public TestA()
{
a=10;
}
public int displayA()
{
return a;
}
abstract void display();
}
public class TestB extends TestA{
#Override
void display() {
System.out.println("this is class B");
}
}
package Abstract;
public class TestMain {
public static void main(String[] args) {
TestA obj= new TestB();
System.out.println(obj.displayA());
}
}
Output is : 10
Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.
Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties
class A {
protected int a;
A() {
a=12;
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
System.out.println(a);
}
}
public class ConstructorInheritance {
public static void main(String args[]) {
B b=new B();
}
}
output:
Inside A's constructor.
Inside B's constructor.
12
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".
Thus, constructor of super class have to be called. There is sequence how the constructor processed:
Call super class constructor
Initialize fields with initializers and initialization blocks
Execute body of the constructor
For more details, have a look of the book to section "3.2".
Consider class test
package access;
public class test {
public String s;
protected test(String s){
this.s = s;
System.out.println("access.test constructor");
}
protected void test1(String s){
this.s = s;
System.out.println("access.test test1 method");
}
}
Consider class Operations
package data;
public class Operations extends access.test{
Operations(String s){
super(s);
}
public static void main(String args []) {
// TODO Auto-generated method stub
//Operations O = new Operations("Operations!");
access.test t = new access.test("hello");//1
t.test1("hi!"); //2
}
}
Constructor test and method test1 is not visible at lines 1 and 2. Why??
In your data.Operations.main() you are attempting to instantiate access.test via new:
access.test t = new access.test("hello");//1
You can't do that. That's what it's telling you via the error.
Section 6.6.1 of the JLS tells us:
A member (class, interface, field, or method) of a reference (class,
interface, or array) type or a constructor of a class type is
accessible only if the type is accessible and the member or
constructor is declared to permit access:
If the member or constructor is declared public, then access is
permitted. All members of interfaces are implicitly public.
Otherwise, if the member or constructor is declared protected, then
access is permitted only when one of the following is true:
Access to the member or constructor occurs from within the package
containing the class in which the protected member or constructor is
declared.
Access is correct as described in §6.6.2.
We jump to 6.6.2.2 and find:
A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) only from within the package in which it is defined.
access.test is in a different package and you declared the constructor protected. Only classes within access can call the constructor directly (e.g. using new - this is what "class instance creation expression" means).
Your data.Operations class extends access.test, which is fine since access.test was declared public. Your constructor is package-private, therefore you are allowed to call:
Operations o = new Operations("Operations!");
in data.Operations.main(). Operation's constructor calls super(s) which it is allowed to do because it's a subclass (in fact, it has to since there's no nullary constructor in the superclass). Note that this is not the same thing as calling the constructor directly via new.
If you were to have this:
Operations(String s){
super(s);
access.test t = new access.test(s);
}
It would produce the same error when trying to use new; you can't do that.
A protected method has different access rules than a protected constructor.
You've declared test1() in access.test as protected.
Declaring a method protected means classes in the access package and subclasses (regardless of package) can call it. Therefore, the following is perfectly valid in data.Operations.main():
Operations o = new Operations("Operations!");
o.test1("hi!");
If your main() was in a different class in your data package (or in another package and Operations had a public constructor), you couldn't do that.
package data;
public class ThirdClass {
public static void main(String[] args) {
// This is perfectly fine since Operations has a package-private constructor
Operations o = new Operations("Some String");
// This won't compile
o.test1("hi!");
}
}
Constructors are not inherited.
use it
public test(String s){
this.s = s;
System.out.println("access.test constructor");
}
A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package.
Does JVM call default Constructor of Anonymous Class to create instance.
My understanding may be stupid for that. I think, even if Reflection API is used to create an instance, there will be at least Default Constructor. Anonymous Class have a Default Constructor? Otherwise, how JVM or whatever create instance?
Yes it does. You can even use other constructors through specifying parameters:
Given
public abstract class A {
String str;
public A(String str){
this.str=str;
}
public abstract void doSomething();
}
You can do
...
A a = new A("Hello World") {
public void doSomething() {
System.out.println(str);
}
};
a.doSomething();
When a class doesn't have an explicit constructor, it has an implicit default empty constructor. That is called, just as any other constructor would be called.
It appears to me that unlike normal classes, anonymous classes has different behaviour associated with implicit constructors.
When you define a normal class, compiler can implicitly insert only a no-arg constructor.
But with anonymous class you can get (implicitly by a compiler) all the constructors the superclass has.
Say we have a class:
class A {
A(int i) {}
A(String s) {}
}
If we subclass it as follows...
class B extends A {}
...we get a compilation error because compiler tries to do this:
class B extends A {
B() {
super(); // Error: there's no no-arg superclass constructor!
}
}
But when we create an anonymous class it implicitly creates constructors as defined for a superclass (A)
A a1 = new A(1) {}; // OK. Uses (int) constructor
A a2 = new A("") {}; // OK. Uses (String) constructor
A a3 = new A() {}; // Error. There's no no-arg constructor
As if our anonymous class has these constructors
X(int i) {
super(i);
}
X(String s) {
super(s);
}
Anonymous classes have a default no args constructor that is called once by the JVM. Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. If your class requires a constructor, you must use a local class instead.
In any case, a constructor is called to initialize newly created object. Anonymous class has default constructor, which initialize the fields of the class, if any, and calls constructor of the superclass.
I have an interface I that is implemented by a base class B. The base class is extended by a bunch of classes (A,C,D) that must init some of the protected vars declared in base class B. I'd like to make the declaration of a constructor mandatory in the subclasses (A,C,D), to discourage the user from relying on default constructor that's declared in B. Yet I do want the B's default constructor to execute automatically, since B can be used by itself as well. How can I accomplish this?
thanks
Use an abstract superclass of B with a private constructor:
public abstract class BSuper {
private BSuper() {
// initialize stuff
}
protected BSuper(some params) {
this():
// other init with parms
}
}
public class B extends BSuper {
public B(some other params) {
super(some params);
}
}
public class A extends B {
public A() {
super(some other params);
}
}
or similar
Make B's default constructor private and call this(); from within the parameterized constructor...
public class B {
private B() {
super();
}
public B( Foo foo ) {
this();
}
public static B createInstance() {
return new B();
}
}
Edit: Miss read the issue, removed abstract keyword from class declaration. Also added public static factory method for creating B class. It calls B's default constructor.
Just write a comment in the Javadoc that says "Use of default constructor is discouraged when subclassing." In my experience, trying to enforce that programmatically is not worth the effort and could cause problems latter on. Simple English will do.
If class B is going to have its own default constructor, what you want is impossible. When you derive from a class, you're telling the compiler that it should allocate memory for a base class object in every instance of the derived class. There's no way to tell a java compiler to suddenly take away some of the base class's functionality every time that something is inherited from it.
Also note that constructors and static factory methods can't be abstract, so even if B could be an abstract class you would have to do something like:
public class B {
B() {
initialize();
}
protected abstract void initialize();
}
...along with making sure that the derived classes implement default constructors that call super()
If I have a class:
class A {
public A() { }
}
and another
class B extends A {
public B() { }
}
is there any way to get B.B() not to call A.A()?
There is absolutely no way to do this in Java; it would break the language specification.
JLS 12 Execution / 12.5 Creation of New Class Instances
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor [...]
If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then [...]
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super).
Execute the instance initializers and instance variable initializers for this class [...]
Execute the rest of the body of this constructor [...]
The closest you can achieve to the desired behaviour is to delegate initialisation normally performed in the constructor to a template method, which you then override in your subclass implementation. For example:
public class A {
protected Writer writer;
public A() {
init();
}
protected void init() {
writer = new FileWriter(new File("foo.txt"));
}
}
public class B extends A {
protected void init() {
writer = new PaperbackWriter();
}
}
However, as other people have noted this can typically indicate a problem with your design and I typically prefer the composition approach in this scenario; for example in the above code you could define the constructor to accept a Writer implementation as a parameter.
Java deserialisation doesn't call the constructor, but it seems that it is based on some internal JVM tricks.
However, there is a framework that allows you to do that in a portable manner: Objenesis (http://www.theserverside.com/discussions/thread/44297.html)
I've seen this recently in Spring, when using CGLIB proxies, Spring creates two class instances, but the constructor is called only once: https://stackoverflow.com/a/11583641/2557118
This behavior is added in Spring 4:
CGLIB-based proxy classes no longer require a default constructor.
Support is provided via the objenesis library which is repackaged
inline and distributed as part of the Spring Framework. With this
strategy, no constructor at all is being invoked for proxy instances
anymore.
The possibility is that you can call the super class constructor of your choice. That is possible by calling the super class constructor explicitly as :
super(para_1, para_2,........);
class BaseA {
BaseA(){
System.out.println("This is BaseA");
}
BaseA(int a){
System.out.println("This is BaseA a");
}
}
class A extends BaseA {
A(){
super(5);
System.out.println("This is A");
}
public static void main(String[] args) {
A obj=new A();
}
}
Output will be:
This is BaseA a
This is A
No and if you could, your derived object wouldn't really be the object it's deriving from now would it? The is-a principle would be violated. So if you really need it, then polymorphism isn't what you're after.
Every superclass needs to be constructed and there is no other way then calling a constructor.
I think the only way to do it is messing up with the byte-code.
I'm not sure if the Classloader or the JVM checks if super() is being called, but, as Bozho wrote, you probably would end with inconsistent objects when doing so.
Nope - you cannot do it and why would you want to do it anyway? That would mess up your object model.
Anyways - i believe if you still want to do it and then you would have to manipulate the generated byte code.... there are a couple of libraries available that make it easy to instrument the byte code.
Strongly suggest against doing it...
Every object in java is a subclass of Object (object with a capital 'O'). when you create an object of a subclass the super class constructor is invoked. Even if your class is not inhereting anyother class, implicitly it is inheriting Object, so the Object constructor has to be called. So super() is invoked for this purpose.
Assuming you mean
class B extends A {
public B() { }
}
then sure you can
class B extends A {
public B() {
this(abort());
}
private B(Void dummy) {
/* super(); */
}
private static Void abort() {
throw null;
}
}
Not very useful. The interface [not Java keyword] to class A says that you need to run its constructor in order to construct it, not unreasonably. The exception is that serialisable classes are constructed without calling the constructors of the serialisable classes.
As pointed out by another poster, B doesn't extend A, so it won't call A's constructor anyways.
There is no way to do this in Java.
You can probably accomplish equivalently what you want to do as follows:
a) in each class of your hierarchy, include a constructor with a unique signature that calls the superclass's constructor with its arguments. For example, declare a class "Noop" and a constructor that takes that as an argument:
public class NoOp {
}
public class class1 {
class1() {
System.out.println("class1() called");
}
class1(String x, String y) {
System.out.println("class1(String, String) called");
}
class1(NoOp x) {
System.out.println("class1(NoOp) called");
}
}
public class class2 extends class1 {
class2() {
System.out.println("class2() called");
}
class2(String x, String y) {
System.out.println("class2(String, String) called");
}
class2(NoOp x) {
super(x);
System.out.println("class2(NoOp) called");
}
}
public class class3 extends class2 {
class3() {
System.out.println("class3() called");
}
class3(String x, String y) {
super(new NoOp());
System.out.println("class3(String, String) called");
}
class3(NoOp x) {
super(x);
System.out.println("class3(NoOp) called");
}
public static void main(String args[]) {
class3 x = new class3("hello", "world");
}
}
If you run this you will get the output
class1(NoOp) called
class2(NoOp) called
class3(String, String) called
So, effectively you have created a class3 constructor that only calls constructors that don't do anything.
I had a similar requirement where I needed my child class NOT to go through the super class' constructor, and I wanted the rest of the benefits of the super class. Since super class is also mine, here's what I did.
class SuperClass {
protected SuperClass() {
init();
}
// Added for classes (like ChildClassNew) who do not want the init to be invoked.
protected SuperClass(boolean doInit) {
if (doInit)
init();
}
//
}
class ChildClass1 extends SuperClass {
ChildClass1() {
// This calls default constructor of super class even without calling super() explicitly.
// ...
}
// ....
}
class ChildClass2 extends SuperClass {
ChildClass2() {
// This calls default constructor of super class even without calling super() explicitly.
// ...
}
// ....
}
class ChildClassNew extends SuperClass {
ChildClassNew() {
/*
* This is where I didn't want the super class' constructor to
* be invoked, because I didn't want the SuperClass' init() to be invoked.
* So I added overloaded the SuperClass' constructor where it diesn;t call init().
* And call the overloaded SuperClass' constructor from this new ChildClassNew.
*/
super(false);
//
// ...
}
// ....
}