This is just a quick question to settle a dispute that I stumbled on a while back (sorry I don't have the link).
How I have been declaring object is as so:
class Foo {
private Bar aBar = new Bar();
...
}
Now the dispute that I found says that this is bad Java. I have no idea why he would say that, but he was quite adamant. What he proposed was that all objects should be declared in the class body, but not instantiated until the constructor. Can anyone shed light on this for me? Is it indeed better to instantiate objects in the constructor?
TFYT
~Aedon
Edit 1:
I know that I used the word dispute, but I do not intend for this to be argumentative.
In most cases it doesn't matter. My rule of thumb is:
If you're going to use the same expression to initialize the variable in all constructors, and it doesn't rely on any parameters, do it at the point of declaration.
Otherwise, you're pretty much forced to do it in the constructor anyway.
Reasoning: by initializing at the point of declaration, it's clear that the value is going to be assigned the same way regardless of the constructor and parameters. It also keeps your constructors simpler, and free of duplication.
Caveat: Don't also assign the value in a constructor, as otherwise that invalidates the previous clarity :)
I suggest you ask your colleague (or whatever) for concrete reasons for his claims that your current code is "bad". I'm sure there are valid alternative points of view, but if he can't provide any reasons, then there's no reason to pay attention IMO.
Another quick note - I'm assuming that none of the initializers need to do any significant work. If they do, that could be a point of confusion, especially if exceptions are thrown. In general, I don't like my constructors doing a lot of work.
By assigning properties in the constructor, it becomes immediately clear what code will run when you instantiate your class.
If you assign inside a field declaration, people reading the class constructor won't realize that the field is set elsewhere.
The contract of a constructor is to create an instance that is semantically valid. That is all fields are properly initialized to reasonable values and so on. For this reason, initializing everything in the constructor helps to clarify what makes a valid instance of your class. In addition, mechanisms like constructor chaining can be used to avoid repeating the same code when you have multiple constructors.
However, that is just a textbook-like theory and in real life you sometimes do the more expedient thing. Since it will make almost no difference if you instantiated objects at the point of declaration or not there need be no strong positions that leads to disputes.
Related
I went through a coding problem in a course I'm taking, and I didn't realize that I needed to include my own constructor until I saw the instructor's solution. This has happened a few times throughout the course: I don't expect that I need a constructor, but it turns out I do need one, according to the answer given (below is one of the answers given to me).
I'm wondering now: do I need to make my own constructors when I need to pass parameters and/or I need additional functionality inside the constructor? Are there other situations when relying on the default constructor would be problematic?
private MenuIterator() {
menuIterator = menu.iterator();
calculateNumMenuItems();
}
You need a constructor exactly when you need to perform some sort of setup for your class and field initialization isn't enough. Your described constructor makes no sense because there's no way for your constructor to get menu (and the private modifier prevents you from calling new MenuIterator() in the usual fashion).
The answer given by chrylis is correct. You may also find this discussion of default constructors useful: Java default constructor. Essentially, if you provide any constructor at all (even a no-arg constructor), you will no longer be provided with a default constructor.
If you need to do anything other than call the class' superclass constructor, you will need to supply your own constructor.
Maybe slightly advanced. In addition to what #chrylis said you also need an explicit constructor if you need the constructor to be anything else than public. This is the case if you want the clients of your class to obtain an instance through a static factory method and not use the constructor directly. The Singleton pattern is just one of many uses of a static method for obtaining an instance.
I wouldn’t worry too much. Even though your instructor has a fine solution with a constructor, it could well be that you have a fine solution without a constructor. Programming problems can always be solved in more than one way.
Links
Java Constructors vs Static Factory Methods
Singleton pattern
A ClassName.class returns the Class object for that particular class. That said and understood, I can't really grasp what the keyword does when used directly in a method.., then, if we write class and follow it immediately with a dot, the list that appears seems to include all that's in scope there, i.e. local variables of the method, other methods and variables(depending on whether the method is static or not), method itself, and class itself..
Coming from its first stated function above, I find myself at odds with this one: I can't tell what it's exactly doing.. way I see it, it's the same word, expect same function at heart, but that doesn't seem to be the case here
Blurry.. I know, but any insight into it is appreciated. Thx.
I get similar behaviour from Netbeans:
However, these are somewhat bogus suggestions.
class.emptyList(), despite being a suggestion, will not compile. This is probably a peculiarity of the way suggestions are computed. If there's a way to get legal code out of these suggestions, I can't think of it.
Note that you get the same suggestions if you just hit CTRL+enter (or whatever keys you have bound to suggestions) on an empty statement.
Usually there are only two circumstances to use the word class:
When defining a class, for example public class MyClass { ... }
With a dot, after a class name, to get the Class object for a type - Class<Person> clazz = Nurse.class
Sometimes you feel you'd like to have a variable called class, but it's a reserved word, so you can't. It's quite common to see variables called clazz for that reason.
For thread-safety reasons it is argumented:
Do not allow the this reference to escape during construction.
But is this always an issue and should be avoided by using newInstance() methods? Inside my model class I have a TableModel which should be instantiated, within the model class, but which also requires a reference to the model class:
public class MainModel {
TableModel tableMode;
public MainModel() {
tableModel = new MyTableModel(this);
}
}
If the constructor does not use this right away is it then safe or should it be avoided in any means?
If nothing in the MyTableModel is going to do anything in other threads etc - or copy the variable to some other shared data, such as a static variable - then it's safe.
Of course, if MyTableModel starts calling methods on the MainModel reference within its constructor, then it'll be calling them on a not-completely-initialized-yet object, which can cause issues - but that's not really threading related.
I blogged a bit more on this a while ago.
No, I don't think it's always a problem. In my opinion a good class is designed such that the constructor limits the activity it does on its dependents, limiting its behaviour only to initialization. If that's the case it would be very surprising for this to leak to another thread simply because you leaked it to another constructor.
The only time you are not permitted at all to leak a reference to this is before the super contructor has been called. In other words, you can't pass an argument to the super constructor that has a dependency on this, be it due to you calling an instance method or constructing something using this.
I think a better question might be why does MyTableModel need to see an instance of MainModel? Often bi-directional visibility is a sign of some harmful coupling.
Best pratice is not about correcting bugs, but patterns which are least likely to introduce bugs, be confusing or difficult to maintain. I have seen some increadibly difficult code which works just fine.
e.g. I remember one class called c which was written entirely on one line to save space (no line breaks) and only used single character variables/fields and had one to two character methods. This wasn't deliberately obfuscated, the developer thought this was the most efficient. The class worked fine as long as you didn't need to understand it of change it.
I have always felt that in general the main work of a class should be done in its instance methods, while the constructor should only get the instance into a usable inital state.
But I find that in practice there are situations where it seems to make more sense to put essentially all the actual work into the constructor.
One example: I need to retrieve some DBMS-specific information from the database. The most natural way to me seemed to have a class DBMSSpecInfo, with a constructor:
public DBMSSpecInfo(java.sql.Connection conn) throws SQLException{
// ... retrieve info from DBMS
}
/** #returns max size of table in kiB */
public int getMaxTableSize() {//...}
/** #returns max size of index in kiB */
public int getMaxIndexSize() {//...}
/** #returns name of default schema */
public String getDefaultSchema() {//...}
You would construct the class once, the constructor would fetch all data, then you could use various getters to retrieve the info you need.
Of course I could put the method somewhere else, and only use DBMSSpecInfo for the return value (essentially using DBMSSpecInfo only as a value holder), but it feels ugly to create a class just for returning values from a single function.
So what do you think? Are there problems with performing the main work in the constructor? Is it "un-idiomatic" in Java? Or is it an acceptable (though possibly uncommon) practice?
The main practical problem is unit-testing - you won't be able to instantiate the object without doing actual work. (Or you'd have to mock all the classes that participate in this work).
Related talk: OO Design for testability. It gives examples of why doing work in constructors is bad for unit-testing.
I would prefer separating the creation code from the class itself in such cases. It could be put into a static factory method, or a separate factory class (which can also be a public static inner class). The choice depends on the complexity of the code and the design context (which we don't know in this case).
This would also allow you to do optimizations, like caching and reusing the class instance(s).
I'm big on pragmatism. If it works, do it! But in the name of purity and goodness, I'd like to make a design suggestion:
This class muddles up the data content with the mechanism for retrieving it. The object you end up using elsewhere is interesting only for the data it contains. So the "clean" thing to do would be to have a different class for digging out the information and then creating instances of this properties object.
That other class could have a longer lifetime, as you'd typically be calling a method to do the work, not the constructor. The constructor of DBMSSpecInfo might end up assigning a bunch of properties but not doing a lot of error-capable DB access work.
In your example I would make a static method GetDBMSSpecInfo(java.sql.Connection conn) that will return an instance of DBMSSpecInfo object or null if something goes wrong (in case you don't want to throw exceptions).
The DBMSSpecInfo object for me should not contain nothing more than get properties: MaxIndexSize, MaxTableSize, DefaultSchema, etc.
And I would make the constructor of this object private so that instances can only be created from the static method.
I don't think it is a good idea to do the main work in a constructor, since it doesn't have a return value. So it makes error processing more complicated IMO, since it forces you to use exceptions.
A disadvantage of doing the work in the constructor is that constructors can not be overridden (nor should they delegate to overridable methods).
Another is that a constructor is all-or-nothing. If the object contains data whose initializations exhibit indepedent failures, you deprive yourself of the capability to use what data could be procured successfully. Similarly, that you have to initialize the entire object, even if you just need part of it, might adversely affect performance.
On the other hand, doing it in the constructor allows initialization state (here: the connection to the database) to be shared, and released earlier.
As always, different approaches are preferable in different circumstances.
Doing all the work in the constructor can lead to "overload hell". You keep wanting to add more features and instead of just adding a new method, like you would in normal Object-Oriented development, you find yourself adding more and more overloaded constructors. Eventually, the constructors can grow so many overloads and parameters that it becomes unwieldy.
Just be careful that the object is not cloned/deserialised. Instances created this way do not use the constructor.
In my opinion the constructor should be lightweighted and should not throw exceptions.
I'd implement some kind of Load() method to retreive data from the database, or implement lazy loading.
No problem. JDK has a lot of classes that does network IO in constructors.
This is a question about coding style and recommended practices:
As explained in the answers to the question unnecessary to put super() in constructor?, if you write a constructor for a class that is supposed to use the default (no-arg) constructor from the superclass, you may call super() at the beginning of your constructor:
public MyClass(int parm){
super(); // leaving this out makes no difference
// do stuff...
}
but you can also omit the call; the compiler will in both cases act as if the super() call were there.
So then, do you put the call into your constructors or not?
On the one hand, one might argue that including the super() makes things more explicit. OTOH, I always dislike writing redundant code, so personally I tend to leave it out; I do however regularly see it in code from others.
What are your experiences? Did you have problems with one or the other approach? Do you have coding guidelines which prescribe one approach?
BTW: A related question (just for reference):
Is there a reason to explicitly code a default constructor when there are no other constructors?
I don't write the super() call for the same reason I don't write unnecessary casts:
It adds noise to the code without providing any additional information (neither to the compiler nor to the developer reading my code).
The default settings of some versions of some IDEs generate it automatically, so that's one reason you might be seeing it.
Whether to write it or not depends on who will be reading it. I prefer not to add it, but if you are not certain that team members understand what the compiler does, and how object construction proceeds, you may add it "just in case".
I don't, but the argument given to me for doing this while at university was that it makes things more explicit, so you don't 'forget' that a superclass constructor is being called.
I just don't see the need tho.
I use the super() only when the constructor super() needs parameters.
What are your experiences? Did you
have problems with one or the other
approach?
I never called the default constructor (explicit) and never faced any problems
I never add it and I was deeply shocked when a colleague didn't understand that there was an implicit call made to the super class so perhaps I should start doing it.
Advantage: Anyone reading your code knows that you really want to call the default constructor, you did not leave the call out by mistake.
Disadvantage: You clutter your code with unimportant information.
Usually, if a language lets you omit some instruction, it is not bad style doing so. I think it is a question of weighing the pros and cons. For instance, explicitly writing super() when your constructor has parameters and the base class also has parametered constructors available may be a good idea.
I actually put the super() call in as I find it to be a helpful memory aide. When I have written a piece of code a few months ago and return to it, the super() reminds me when I am looking at the constructor that the class I wrote inherits from something.
I try to avoid writing code where calling super() is necessary, because I prefer composition over inheritance.
If I have to derive from another class, I try to put both behind an own interface and pass one of them to the other as a dependency.
If I have a lib class, however, which I cannot give an extra dependency, the first thing I try is to use a decorator.
If this doesn't work, and I have to derive from an implementation, I think it doesn't matter whether to write super() or not, since it happens so rarely ;)
So, all in all, I think this question is pointless.