public class ConstructorsDemo {
    public static void main(String[] args) {
        System.out.println("-- default constructor: the compiler writes it --");
        System.out.println("declared constructors of Plain: " + java.util.Arrays.toString(Plain.class.getDeclaredConstructors()));

        System.out.println("-- chaining: this(...) inside a class, super(...) up the hierarchy --");
        new Manager("Ravi");

        System.out.println("-- copy constructor makes an independent object --");
        Point p = new Point(1, 2);
        Point q = new Point(p);
        q.x = 99;
        System.out.println("p=" + p + " q=" + q);

        System.out.println("-- shallow copy trap --");
        Team t1 = new Team(new String[] { "asha", "ravi" });
        Team t2 = new Team(t1);
        t2.members[0] = "CHANGED";
        System.out.println("t1.members[0] = " + t1.members[0]);

        System.out.println("-- private constructor: the only way in is a factory --");
        System.out.println(Config.get() == Config.get());
        System.out.println("-- constructors are not inherited --");
        System.out.println("Child constructors: " + Child.class.getDeclaredConstructors().length
                + ", Parent constructors: " + Parent.class.getDeclaredConstructors().length);
    }
}
class Plain { }

class Person {
    Person(String name) { System.out.println("  Person(" + name + ")"); }
}
class Employee extends Person {
    Employee(String name, int level) {
        super(name);
        System.out.println("  Employee(" + name + ", " + level + ")");
    }
    Employee(String name) {
        this(name, 1);
        System.out.println("  Employee(" + name + ")");
    }
}
class Manager extends Employee {
    Manager(String name) {
        super(name);
        System.out.println("  Manager(" + name + ")");
    }
}

class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
    Point(Point other) { this(other.x, other.y); }
    public String toString() { return "(" + x + "," + y + ")"; }
}
class Team {
    String[] members;
    Team(String[] m) { members = m; }
    Team(Team other) { this.members = other.members; }
}
class Config {
    private static final Config INSTANCE = new Config();
    private Config() { }
    static Config get() { return INSTANCE; }
}
class Parent { Parent(int x) { } }
class Child extends Parent { Child() { super(1); } }
