Frage

I came across something called "consistent constructors" when going through constructor overloading. I understand what constructor overloading is all about.

Class Person
{
  String Name;
  String City;

  Person(String N,String C)
  {
    Name=N;
    City=C;
  }

  Person(String N)
  {
    this(N,NULL);
  }
}

Class NewClass
{
  public static void main(String[] args)
  {
    Person obj1=new Person("carl","max");
    Person obj2=new Person("Tommy");
  }
}

What according to me is a consistent constructor :: Its using this as i have shown in one of the constructors for initializing the instance variables .... In my example always the constructor with two arguments is called !


  1. What are these Consistent Constructors in Java?

  2. What the practical applications of these?

  3. Why are they used in Java?

  4. Any more information on understanding this topic?

Can someone give more explanation on this topic for a noob like me in layman terms and more information to learn about this topic?

War es hilfreich?

Lösung

I've never heard about consistent constructors but I guess it's about parameters initialized by defferent constructors. Let's see how inconsistent constructors could look like:

class Person {
    String firstName;
    String lastName;
    Integer age;

    Person(String firstName, String lastName, Integer age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    Person(String firstName, String lastName) {
        this(firstName, lastName, 0);
    }

    Person(String firstName) {
        this(firstName, null, null);
    }
}

Person p1 = new Person("Joe", "Doe", 24);
Person p2 = new Person("Joe", "Doe");
Person p3 = new Person("Joe");

Where is the inconsistency? You'd expect that age of person number #2 and #3 (p2, p3) would be undefined, i.e. its value would be -1, 0 or null. It doesn't matter which one as long as using Person(String, String) and Person(String would give you the very same, consistent, value.

In this example second construcot initialize age to 0, but third constructor initialize this property to null - that seems to be quite inconsistent.

Andere Tipps

I've never heard it called "consistent constructors". I think I've heard it called "chained constructor invocation". It's when you use the this keyword from one constructor to invoke a different constructor.

What the practical applications of these?

They reduce code duplication and thus increase maintainability. Imagine that the "Name=N" code was duplicated in each constructor:

Person(String N,String C)
{
  Name=N;
  City=C;
}

Person(String N)
{
  Name=N;
  City=null;
}

Now imagine we want to validate the name:

Person(String N,String C)
{
  if (N == null || N.length() == 0) throw new IllegalArgumentException();
  Name=N;
  City=C;
}

Person(String N)
{
  Name=N;
  City=null;
}

We have changed one constructor but forgotten the other one, so the restriction on the name can be circumvented. This is a real risk if the class is quite complex.

By doing this(N,null); to call one constructor from another, the main logic of the constructor can be maintained in just one place, which is a good thing.

Why are they used in Java?

Java does not support optional arguments, unlike some other languages. In some languages, you might write the constructor like this:

Person(String N, String C=null) {
  Name=N;
  City=C;
}

In that case there is only one constructor, which may be invoked with either 1 or 2 arguments, with the city defaulting to null if not specified. That is not valid Java, but it is possible to fake it with overloading.

It's a nice technique I often use, but I don't know the name of it. It can also be applied to overloaded methods. The main benefit is that you have single logic for multiple input cases and you provide defaults to simplify it's usage. I.e. you have a method with a full signature like:

foo(a, b, c, d) {...}

And it's quite lengthy. This can be a code smell - i.e. it may be better to combine these parameters into one or two parameter objects or into an instance state. Anyway, there might be a reason for having this signature, so to simplify usage of this method, one could provide a signature which would call it with the defaults:

foo(a, b){
    return foo(a, b, defaultC, defaultD);
}

Reverse Case

You have a method foo(a) which you want to parameterize:

foo(name){
    System.out.println("Hello, " + name);
}

And you need to pass "Hello, " as a parameter only for a single case. When this is a real project and foo is used in 100 other place, you could do this:

foo(a){
    foo("Hello", a);
}

foo(greeting, name){
    System.out.println(greeting +", " + name);
}

Some IDEs support this as a refactoring, so it can be quite a handy technique.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top