Levenlol
Levenlol

Reputation: 415

Java: got an unexpected output

I'am learning Java and I got an unexpected output. That's the code:

public class Point {
    protected final int x,y;
    private final String name;

    public Point(int x,int y){
        this.x = x;
        this.y = y;
        name = makeName();
    }

    protected String makeName() {

        return "["+x+" ,"+y+"]";
    }
    public final String toString(){
        return name;
    }
}
public class ColorPoint extends Point{
    private final String color;

    public ColorPoint(int x,int y, String color){
        super(x,y);
        this.color = color;
    }

    protected String makeName(){
        return super.makeName() + ":" + color;
    }

    public static void main (String[] args){
        System.out.println(
                new ColorPoint(4,2,"viola"));
    }
}

The output is: [4,2]:null.
Why? Shouldn't it be just [4,2] because the variable String name is initialized first in makeName() method of the Point class and then should become unmutable? Am I wrong?

Upvotes: 1

Views: 115

Answers (6)

Pshemo
Pshemo

Reputation: 124225

final fields are initialized with default values (which for references is null). You can easily check it with this code:

class FinalTest{
    public final String value = test();

    private String test() {
        System.out.println("current state of value is '"+value+"'");
        return "foo";
    }

    public static void main(String[] args) {
        FinalTest ft = new FinalTest();
        System.out.println(ft.value);
    }
}

which produces output:

current state of value is 'null'
foo

So as you see final variable has its default value which can be later modified in constructor once.

But lets get back to your example. When you call

System.out.println(new ColorPoint(4, 2, "viola"));

you are creating invoking constructor of ColorPoint class, and then on this instance toString will be called. But lets take a closer look at ColorPoint constructor:

public ColorPoint(int x, int y, String color) {
    super(x, y);
    this.color = color;
}

As you see before this.color will be set you are invoking super(x,y) which code looks like this:

public Point(int x, int y) {
    this.x = x;
    this.y = y;
    name = makeName();
}

But here in makeName(); thanks to polymorphism (late binding) you are using code of makeName from ColorPoint class which looks like

protected String makeName() {
    return super.makeName() + ":" + color;
}

So at start you will get result of super.makeName() which is "[" + x + " ," + y + "]" but then you are trying to access color which as you remember is not initialized with because

super(x, y); //<-- we are still here
this.color = color;//this wasn't invoked (yet)

so color still has its default value (null).

This means that name will be set to [4 ,2]:null.

Since ColorPoint inherits toString from Point which looks like

public final String toString() {
    return name;
}

you see as output value stored in name which is [4 ,2]:null.

Upvotes: 0

Clyde D&#39;Cruz
Clyde D&#39;Cruz

Reputation: 2065

 new ColorPoint(4,2,"viola"));

calls the constructor on line 22 , which inturn calls the constructor on line 5 the constructor on line 5 calls the overridden function make name on line 27 which sets name as [4,2]:null because colour hasnt been initialized yet.

Upvotes: 0

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26926

makeName() is called in the constructor of the superclass. When it is called color is not yet set so the default value of color is null.

To solve the problem you have to explicitly call makeName() at the end of constructor. Here is the correct code:

public ColorPoint(int x,int y, String color){
    super(x,y);
    this.color = color;
    makeName();
}

Upvotes: 0

Nielarshi
Nielarshi

Reputation: 1136

Flow is like this,

Point constructor > makeName of ColorPoint > makeName of Point

since, makeName of ColorPoint is called first, till that time color property value was not assigned, so its giving null

Upvotes: 0

Brijesh Bhatt
Brijesh Bhatt

Reputation: 3830

super(x,y) is calling method makeName() of ColorPoint class and color is not assigned till then.

Upvotes: 0

Gabriele Mariotti
Gabriele Mariotti

Reputation: 363815

the makeName() method is called before you set this.color = color;

The makeName() method is called by your super.construtctor when the color variable is still null.

Upvotes: 2

Related Questions