10

I know that private instance variables are accessed through their public getters and setters method.

But when I generate constructors with the help of IDE, it initializes instance variables directly instead of initializing them through their setter methods.

Q1. So should I change the IDE generated code for constructors to initialize those instance variables through their setter methods.

Q2. If yes, then why IDE don't generate constructors code in that way?

============================= EDITED =======================================

  • I use Eclipse and Netbeans IDE

  • It's a general question. But as asked by @Lords would the answer depends on whether our constructor is public or protected or package private or private?

Amit
  • 33,847
  • 91
  • 226
  • 299
  • Are your constructors public, private or something else? – Pops Apr 02 '10 at 18:43
  • And I have edited my answer. (Actually two edits in quick succession.) – Pops Apr 02 '10 at 19:23
  • I think IDEs can't generally rely on there being setters and can't _know_ if a method is a setter. That is, although they can interrogate the code, it's not guaranteed that setFoo is the setter for this.foo unless the code for setFoo is very simple. It can obviously know whether setFoo assigns to this.foo but not whether the developer intends for that to be the setter unless that assignment is _all_ that setFoo does. And then it becomes a subjective matter whether the developer wants to use that setter in the constructor. – nicerobot Apr 02 '10 at 19:29
  • 1
    @nicerobot, if the IDE generates the setter itself, then it does know what it does. Sure, you could alter the setter's behavior after the fact, but you could also change the variable name after the fact, or any of a dozen other things. – Pops Apr 02 '10 at 19:32
  • @lord-torgamus variable name changes also can be controlled by the IDE. What's your point? Regardless of which path the IDE took, it'd require changes by the developer. This _is_ development we're talking about after all. The direct assignment in the constructor is guaranteed to work regardless of what the developer does to setters. It isn't true that using setters in the constructor is guaranteed to work regardless of what the developer does to the setters. Let the developer decide. Code generation can only go so far. Don't expect it to go farther. – nicerobot Apr 02 '10 at 19:46
  • @nicerobot, I think you misinterpreted my comment. It wasn't about development in general. It was only about the autogenerated stuff that happens before development starts, because that's what the OP was asking about. Once a programmer starts modifying code, your comment is of course correct. – Pops Apr 02 '10 at 19:48

7 Answers7

12

You should never call a non-final method from a constructor. A class constructor is used to initialize an object, and the object is not in a consistent state until the constructor returns. If your constructor calls a non-final method which is later overridden by a subclass, you can get strange, unexpected results because the object is not fully initialized when the overridden method is called.

Consider this contrived example:

class A {
    private int x;

    public A() {
        setX(2);
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }
}

class B extends A {
    private int number = 10;

    @Override        
    public void setX(int x) {
        // set x to the value of number: 10
        super.setX(number);
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // b.getX() should be 10, right?
        System.out.println("B.getX() = " + b.getX());
    }
}

The output of this program is:

B.getX() = 0

The reason is that B's number member is not initialized at the time setX is called, so its default value of 0 is used.

This article has a more thorough explanation, as does Effective Java.

Jason Day
  • 8,809
  • 1
  • 41
  • 46
2

Constructors are for initialization. Initialize private instance variables directly in the constructor. Methods define an object's behavior. Behavior occurs after instantiation/initialization. Manipulate the state of your instance variables with your setter methods. That's classic OOP thinking and probably why your IDE is generating the code it does.

Chris
  • 1,826
  • 12
  • 15
1

That depends. If your setters/getters are simply accessing the members you should access them directly. If you also have some code along with it, use setters.

Searles
  • 1,447
  • 1
  • 11
  • 26
  • ok but wouldn't it be better to use setters even if the setters are just setting them directly so as to follow Encapsulation and make it easy to add some code in setters in future (if needed)? – Amit Apr 02 '10 at 19:11
  • Well, then it would not be a setter anymore. You also should consider, that from an object-oriented point of view setters are not object-oriented (which object in nature has a "setter"?) – Searles Apr 06 '10 at 12:07
0

You should decide which fields you will initialise with the constructor and which to initalise with a setter. (both is possible) I prefer to use the constructor only as much as possible and often have no setters.

This should be configurable/selectable in IDE. Without knowing your IDE there is no way to know why it works the way it does.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

Good answers. Only want to add that Eclipse (the one I use often) has templates, which you can modify in order to generate your code the way you want. It could help to adjust the code to your needs.

PS. I rather use setters and getters. Just as an habit, keeps the code coherent, I feel like it will be easier to read for someone else if I keep the habits all over the code.

Alfabravo
  • 7,493
  • 6
  • 46
  • 82
0

First of all initialization != setters (at least not always)

But IDEs are just playing nice with once revered JavaBean design pattern Assuming property changes should happen via setters.

So, it is a matter of design. If your classes represent pure value objects, no harm in initializing via = But if your classes have a potential of becoming a JavaBean whose property change is more than just init or assignment, go with set* calls.

ring bearer
  • 20,383
  • 7
  • 59
  • 72
0

Private instance variables of a class should be (I believe need to be) declared outside of any class constructor. If I could break part of your question down into two parts:

Q1) If instance variables are initialized when a class is instantiated, unlike local variables, why bother doing the extra work within a given class constructor (?).

A1) Although you do not need to initialize instance variables (private string someString; defaults to null and is legal), one reason for doing so is that the default assigned by the compiler may not be the value you want, or worse, incorrect (which the compiler should catch).

Q2) Assuming the part above, what is the significance of get; set; properties?

A2) Aside from the fact they are easy and more elegant that a method equivalent, properties can be used at anytime within your class (obviously), they can be used as simple assignments or contain additional code (someone already stated this for validating information), and finally the data is self contained within the class and therefore easier to debug.

All this being said, you may have a perfectly valid reason for doing things differently than what a book or someone else says. There are always acceptions to the "rule(s)", and you should code accordingly.

JohnV
  • 1