why I can't assign variable i in subclass ?
class a {
int i;
}
class b extends a {
i=1;
}
You can assign variables in a subclass. What you can't do is put statements where only declarations are allowed. (Note that int i = 10; is a declaration - not a statement.)
In this case the constructor would likely be a suitable place to establish a default value (for the subtype):
class b extends a {
public b () {
i = 1;
}
}
As damo suggested, an initialization block would also work. This is discussed in Initializing Fields tutorial:
Normally, you would put code to initialize an instance variable in a constructor [but] there are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.
All answers are correct but no one says that you can do this..
class b extends a {
{
i=1;
}
}
And this will compile and be execute after a constructor and before b constructor
As you are using the default access modifier, this means that the property in class a is accessible to all classes within the same package, including the subclass b. However, you must access the property in a method.
class a {
int i; // this is an instance variable
}
Instance variables are a class level, they can be assigned to a literal or reference variable or you can leave it to have it's default value, the subclass can use the public instances inside it's method or constructor not in the class level as you did :
class b extends a {
i = 3; // assgining a literal to i is compilation error
}
Because it's the location that Class fields and Instance variables declared, not assigning a super class's instance variable to something.
If you want to use i inside class a, you have to use it inside some method or a constructor.
class b extends a {
a(){
i = 4;
}
void doSomething(){
i = 5;
}
}
Related
What is the Difference between super(variable-name); and super.variableName = something; in a constructor, when you want to initialize the parameters and you wanna assign one of them to a variable of a parent class?
for example i want to implement the constructor of the "Zahnradfraese" and it takes the parameter "int Kennung" and this parameter should be assigned to the attribute "kennung" of the parent class "Produktionmittel"
Should I always use super when I wanna call a variable from this parent class or I just use it if I have another variable with the same name in the child class?
What is the difference between super(variableName); and super.variableName = something;?
method() (here, super(variableName)) is a method invocation (here, a parent's constructor invocation).
super.variableName = something; is an assignment to a parent's field.
Should I always use super when I wanna call a variable from this parent class or I just use it if I have another variable with the same name in the child class?
super(variableName) can initialise the inner state of the parent, particularly super.variableName. It is reasonable to initialise a super.variableName before accessing it. Both ways you listed can be utilised for that. Just make sure there is no code duplication.
I want to implement the constructor of the Zahnradfraese and it takes the parameter int Kennung and this parameter should be assigned to the attribute kennung of the parent class Produktionmittel.
Add a constructor to Produktionmittel which takes an int
public Produktionmittel(int i) {
kennung = i;
}
and call it from the child:
public Zahnradfraese(int kennung) {
super(kennung);
}
super(variable_name) represents a constructor call and should be first line in the constructor. Whereas super.variableName = something; means you are assigning a value to the instance variable of the parent class from the child class using super which is used to refer parent class objects.
Now in your case: as per given class-diagram
the class Zahnradfraese has a constructor which takes int Kennung argument. Also, kennung is the parent-class and has no constructor and instead it has method setKennung(). So you can do super.setKennung(kennung) from inside the constructor of Zahnradfraese class. You can also declare a constructor inside kennung but that would mean deviating from the class-diagram which has setter and getter methods and no constructor.
public class Zahnradfraese extends Kennung{
public Zahnradfraese(int kennung){
super.setKennung(kennung);
}
}
So super(variableName) is invoking your parent class one arg constructor, and that logic gets executes
super.variableName = something; is assigning something value to parent class variable variableName
super() is a keyword which is used to call the constructor in the parent class and it must be called from inside the constructor of the child class. Also it must be the first statement.
Where as super.s is used to set the variable s (which is declared in the parent class) from the child class and it doesn't have restrictions as above.
See below example:
class Test {
int s;
Test(int d) {
}
}
class T extends Test {
T() {
super(8);
int d = 99;
super.s = 00;
}
void ss() {
super.s = 99;
}
}
super(arg) invokes the constructor of the super class, setting the variable just sets the variable. (The constructor might contain more logic than just assigning a variable, which you bypass with the second way)
Simple example:
public class P{
protected String variable1;
private boolean variableInitialized = false;
public P (String s){
this.variable1 = s;
this.variableInitialized=true;
}
}
public class C extends P{
}
calling super("x") within C will also set the boolean flag, as the parent class "might expect" it. Calling super.variable1="x" will not affect the boolean flag, and you can't change it, cause it's private.
As a rule of the thumb i'd say: If there is a dedicated constructor for a certain variable, it seems worth using it, unless you exactly want to override that implementation.
I have studied some of the related posts about this topic and I have learned that when we make a variable of the same name in a subclass, that's called hiding.
class A {
int i = 10;
public void printValue() {
System.out.print("Value-A");
System.out.println(i);
}
}
class B extends A {
int i = 12;
public void printValue() {
System.out.print("Value-B");
System.out.println(i);
}
}
public class Test {
public static void main(String args[]) {
A a = new B();
a.printValue();
System.out.print(a.i);
}
}
When I instantiate class B with type A and print member data
A a=new B();
System.out.println(a.i)//The output is `10`.(The value of parent class member data).
But when I instantiate class B as type B,
B a=new B();
System.out.println(a.i)//The output is 12. (The value of parent class member data)
I would like to know how they are different.
Variables bind to the reference, not to the object created. In your example, A a = new B(); Here a is a reference to which variable binds of type A. And, created object is of type B, to which methods are bind. That's why it is picking values for variables of references. This is called data hiding. Because when we create same variable in sub-class, value of variable of sub-class is hidden under super class variable. Hope it helps.
Polymorphism applies only on methods. Variables still binds to the type. You can't ovveride variables. That is the reason you are seeing different output when you changing the type.
In simple words, when you write
A a=new B();
Just to remember, variables bind to left side and methods gets execute from right side.
I would like to understand a strange behavior I faced dealing with anonymous classes.
I have a class that calls a protected method inside its constructor (I know, poor design but that's another story...)
public class A {
public A() {
init();
}
protected void init() {}
}
then I have another class that extends A and overrides init().
public class B extends A {
int value;
public B(int i) {
value = i;
}
protected void init() {
System.out.println("value="+value);
}
}
If I code
B b = new B(10);
I get
> value=0
and that's expected because the constructor of the super class is invoked before the B ctor and then value is still.
But when using an anonymous class like this
class C {
public static void main (String[] args) {
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
}
}
I would expect to get value=0 because this should be more or less equal to class B: the compiler automatically creates a new class C$1 that extends A and creates instance variables to store local variables referenced in the methods of the anonymous class, simulating a closure etc...
But when you run this, I got
> java -cp . C 42
> value=42
Initially I was thinking that this was due to the fact that I was using java 8, and maybe, when introducing lamdbas, they changed the way anonymous classes are implemented under the hood (you no longer need for final), but I tried with java 7 also and got the same result...
Actually, looking at the byte code with javap, I can see that B is
> javap -c B
Compiled from "B.java"
public class B extends A {
int value;
public B(int);
Code:
0: aload_0
1: invokespecial #1 // Method A."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field value:I
9: return
...
while for C$1:
> javap -c C\$1
Compiled from "C.java"
final class C$1 extends A {
final int val$v;
C$1(int);
Code:
0: aload_0
1: iload_1
2: putfield #1 // Field val$v:I
5: aload_0
6: invokespecial #2 // Method A."<init>":()V
9: return
....
Could someone tell me why this difference?
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
EDIT:
to clarify the question: why does the initialization of the anonymous classes break the rules for initializing of any other class (where super constructor is invoked before setting any other variable)?
Or, is there a way to set instance variable in B class before inovking super constructor?
This question applies to all inner classes, not just anon classes. (Anon classes are inner classes)
JLS does not dictates how an inner class body accesses outer local variable; it only specifies that the local variables are effectively final, and definitely assigned before the inner class body. Therefore, it stands to reason that the inner class must see the definitely assigned value of the local variable.
JLS does not specify exactly how the inner class sees that value; it is up to the compiler to use whatever trick (that is possible on the bytecode level) to achieve that effect. In particular, this issue is completely unrelated to constructors (as far as the language is concerned).
A similar issue is how an inner class accesses the outer instance. This is a bit more complicated, and it does have something to do with constructors. Nevertheless, JLS still does not dictate how it is achieved by the compiler; the section contains a comment that "... compiler can represent the immediately enclosing instance how ever it wishes. There is no need for the Java programming language to ... "
From JMM point of view, this under-specification might be a problem; it is unclear how writes were done in relation to reads in inner class. It is reasonable to assume that, a write is done on a synthetic variable, which is before (in programming order) the new InnerClass() action; the inner class reads the synthetic variable to see the outer local variable or the enclosing instance.
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
You may arrange the "normal" class as outer-inner class
public class B0
{
int value;
public B0(int i){ value=i; }
public class B extends A
{
protected void init()
{
System.out.println("value="+value);
}
}
}
It will be used like this, which prints 10
new B0(10).new B();
A convenience factory method can be added to hide the syntax ugliness
newB(10);
public static B0.B newB(int arg){ return new B0(arg).new B(); }
So we split our class into 2 parts; the outer part is executed even before the super constructor. This is useful in some cases. (another example)
( inner anonymous access local variable enclosing instance effective final super constructor)
Your anonymous class instance behaves differently than your first code snippet since you are using a local variable whose value is initialized before the anonymous class instance is created.
You can get a similar behavior to the first snippet with an anonymous class instance if you use an instance variable in the anonymous class :
class C {
public static void main (String[] args) {
A a = new A() {
int avalue = 10;
void init() { System.out.println("value="+avalue); }
}
}
}
This will print
value=0
since init() is executed by A's constructor before avalue is initialized.
The variable capture in anonymous classes is allowed to break the rules of normal constructors (super constructor call must be the first statement) because this law is only enforced by the compiler. The JVM allows any bytecode to be ran before invoking the super constructor, which is utilized by the compiler itself (it breaks it's own rules!) for anonymous classes.
You can mimic the behavior either with inner classes as shown in bayou.io's answer, or you can use an anonymous in a static B factory method:
public class B extends A
{
public static B create(int value)
{
return new B() {
void init() { System.out.println("value="+value);
};
}
}
The limitation is actually rather pointless and can be annoying in some situations:
class A
{
private int len;
public A(String s)
{
this.len = s.length();
}
}
class B extends A
{
private String complexString;
public B(int i, double d)
{
super(computeComplexString(i, d));
this.complexString = computeComplexString(i, d);
}
private static String computeComplexString(int i, double d)
{
// some code that takes a long time
}
}
In this example, you have to do the computeComplexString computation twice, because there is no way to both pass it to the super constructor and store it in an instance variable.
The two examples are not related.
In the B example:
protected void init() {
System.out.println("value="+value);
}
the value being printed is the value field of the instance of B.
In the anonymous example:
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
the value being printed is the local variable avalue of the main() method.
In the following example:
class A {
private int a;
private int b;
private int c;
public A(int a, int b , int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
class B extends A {
public B() {
super(1,2,3);
}
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
You cannot call super() like this:
class B extends A {
super(1,2,3);
}
super() OR this() should be the first statement in a constructor. First correct this basic mistake of yours before going further. super() is used by default even if you don't explicitly use it.
class B extends A {
B (){
super(1,2,3);
}
}
This is the right way. Please Read about Constructors and Java language basics first before posting questions.
EDIT
I didn't notice that someone edited you question to add super(1,2,3) in a constructor, now answering your questions as follows:
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
No, by calling super(1,2,3) all you're doing is passing 3 integer values to the base class constructor public A(int a, int b , int c) After that you're assigning these values to the private instance variables of base class, you're not making a separate fields for class B, if thats what you asked, and No B class still can't access base class instance variables directly (by stating directly I mean by inheritance or making an instance, there are other ways like setters/getters etc)
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
No, if you don't use a constructor in B class which uses super(int, int, int) to match the arguments of base class constructor (int a, int b , int c) then your code won't even compile. The default constructor will call the no-args constructor of Base class, but since Base class has no default constructor you'll get compilation error!
First of all, the code you posted is not valid Java. It is important that you post working code, otherwise we can't be sure about what you are asking.
Does the statement super(1,2,3) in the class B create a private fields same as the private fields in the class A? Or is it illegal to use this statement because B cant inherit the private fields of A?
Assuming you put the statement in a constructor instead of at class level, which is illegal, then no, that will not automatically create fields in class B. It just calls the constructor in the superclass A that takes three int arguments and initializes the fields in the superclass part of the object.
And we suppose that we didn't use the super constructor in the class B then normally the computer will call the default constructor of the class A. We know that private fields are not inherited in Java so what will the default constructor initialize in this state ?
Since there is no default (i.e. no-arguments) constructor in class A, you would get a compiler error - the compiler would complain that there is no appropriate constructor in class A.
Java only automatically adds a no-arguments constructor to a class if you do not specify a constructor at all in the class. Since class A already has a constructor, Java is not automatically going to add a no-arguments constructor.
First of all you need to understand one thing: private fields of a parent class ARE BEING INHERITED. The only thing is that if they are private in parent, then they cannot be accessed directly from the child class (the B class in your example). So in other words: not a single B class method can access those fields, but every A class method can access them. So for example its possible that there is a public/protected method inside A class that changes some of those fields and this method can be called from a child class (B).
Once you correct your class to the proper:
class B extends A {
public B() {
super(1,2,3);
}
}
...we can proceed to answer your actual questions.
The constructor of A does not create fields. The fields are created as part of creating of any A object, and are initialized by the constructor.
Those fields are created in B as well, but not because you called super(1,2,3) but because you extend A. As soon as an instance of B, which is an extended instance of A is created, those fields are there - but they are accessible only to methods that are declared in A itself and not in its descendents.
By calling super(1,2,3), you are initializing those private fields. They are still not accessible to B. The constructor of A is mediating between B and these private variables. If you had a method that prints those fields in A, and that method was not private, you could call it and it would print them with these values.
As for your second question, if you didn't call the super(1,2,3), Java would try to call the default constructor. However, for a class that has a constructor, there is no default constructor. The empty/nullary constructor only exists if you either declared it yourself, or if you didn't declare any constructor at all.
// The following two classes have a default constructor which will be called
// if any descendent doesn't call super(...)
class HasADefaultConstructor {
}
class AlsoHasADefaultConstructor {
AlsoHasADefaultConstructor() {
}
}
// But this one doesn't.
class DoesntHaveADefaultConstructor {
DoesntHaveADefaultConstructor( String a ) {
}
}
So you can't inherit private varibles, but you can access them if the parent class has the appropriate getters:
Run the example and you see the output is 'a is: 1'
Regarding the default constructor: In your example you have explicitly implemented
a constructor. So the implicit default constructor is not there any more
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}
class B extends A {
public B() {
super(1, 2, 3);
}
public void foo() {
//access a
System.out.println("a is: " + super.getA());
}
public static void main(String[] args) {
B bb = new B();
bb.foo();
}
}
Java code like this:
public class A {
private static int a;
public static class B {
static void funcc() {
a = 3;
}
}
}
public class C extends A.B {
public void func() {
a = 1;
}
}
When I try to compile it, an error occurs:
C.java:3: error: cannot find symbol
a = 1;
^
symbol: variable a
location: class C
1 error
Why this happens?
B is static. This makes it equivalent to declaring it at top level. It is not a nested class and does not have access to anything private in its lexically containing class.
Nested class B has access to all of the fields and methods of it's enclosing because it is a member of A. Subclasses of B (that are not members of A) do not have that access.
Internal classes don't extend their containing class; they are a class in their own right.
In your example, B is a class which has no methods and no fields. It doesn't have a variable a.
However you could access the variable a inside of the B class, but this is only because a is in its closure; it can peak at A's variables, which is the power of an internal class.