What are the advantages/disadvantages of init method over a constructor in java? They both have the same purpose. How to choose between them?
public class A {
private int x;
public A(int x){
this.x = x;
}
public void init(int x){
this.x = x;
}
}
Here we can use either constructor or init method.
You are wrong. They do not have the same purpose.
A constructor is always required when you want to create a new object using the new() operator.
A init method is something that might make sense in certain contexts, for example servlet stuff (see here for further reading regarding this aspect).
And please note: in your example, one could your init method more as a setter - as it is simply setting the corresponding field.
Coming from there:
first of all, you think about the constructors that you want to put into you class (by asking: which information is required to create a new instance of the class)
if there is special need, then consider adding setters for specific fields - or as layed out above, it might be required to provide an init() method (in case where object creation and initializiation can not happen at the same point of time)
Constructor is not a regular method. It's special in a sense that it gets always called when you invoke new A(). If you don't provide a constructor, Java creates one automatically. As a consequence, constructors do not have a return (i.e. they return this) and always have the same name as the class.
On the other hand, init is a regular method, which you can call - or not. There is no universally accepted consensus for any kind of "init" methods. So it depends on what you want to do. If you want to ensure that the new calls your logic, use constructor. If you want to have your own stuff, use plain methods. You can mix and match, just be sure to write a good documentation about how your class is supposed to be used.
Related
I need to modify an argument to a function in Java. How do I add the argument to the callers using automation?
For example, In class A a method hello(int a ) exists. Now I am adding String to the same function argument so it becomes hello(String b , int a). If class B calls this method,how do I update the calling line in class B.
A a = new A();
int a; String b;
a.hello(a) % change to a.hello(b,a); //Assuming b is accessible.%
Eclipse provides this functionality via refactoring. Do they expose this API to external world or any other API is there?
You can right-click onto the method, select Refactor and select Change Method Signature. This opens a dialog that allows you to add new parameters, change parameter order, etc. When adding a new parameter you can provide a "Default Value" that will be used as argument in all classes that are currently calling the changed method.
Only classes with source that are currently in open Projects of the current Workspace are changed. The "outside world" will not get any notification of that. If you want to keep things runnable you should follow the advice to create a second method with the additional parameter and keep the old one (calling the new one with fitting default value). This can also automatically be done by mentioned refactor-dialog by checking the checkbox "keep original method as delegate to changed method".
Instead of trying to find all calling instances of a method, I would overload the method to include a way to handle passing in a string.
Class A(int a){}
Class A(String a){}
when you call these methods with the appropriate argument, you call that specific method. If you already have method calls using String a as an argument, a)you should get compiler errors, but more importantly b)this would fix all of them.
You can overload the method to add more parameters. All you have to do is define another method with the same name that takes different arguments.
public class A{
public void hello(int a){
//do things
}
public void hello(String b, int a){
//do things
}
}
The JVM will determine which method to use based on the given arguments during run time. If this isn't the functionality you need just give me a heads up.
I was looking at other questions on SO, but I didn't really see an explanation for my question. I read that calling a constructor from another constructor (using the this keyword) was valid, but I didn't understand why it was valid.
Previously, I thought that only one constructor could act per object. Constructor chaining seems to break this logic, in that while calling one constructor, it runs another in conjunction to the original, targeted constructor. Why does constructor chaining work?
We chain (call) one constructor from other within the same class so that we can avoid code duplication. Without chaining every constructor, we end up repeating business details and that leads to code duplication and hard to maintain the code as well.
Imagine you are creating a Bus.
public class Bus {
int noOfSeats;
String busColor;
public Bus() {
this(40); //// Using another constructor and proceeding with default values..
}
public Bus(int seats) {
this(seats,"red"); // Using another constructor and proceeding..
}
public Bus(int seats, String color) {
this.noOfSeats = seats;
this.busColor = color;
}
}
And the person using this class can use only constructor at a time, where as you are using chaining internally. Imagine that you have a method which initializes things with default values and calling it in the constructor. There's nothing wrong in that, right?
Just to clarify, the person who is creating the object is calling only one constructor. The invoked constructor calls others which is internal to that class.
Delegated constructors reduce the amount of duplicate code, since you can exploit the functionality set up in one constructor by calling it from another one.
Until this feature was designed into languages, we had to rely on "initialisation"-type functions that were called from constructors. That was a pain for two reasons (i) you could never guarantee that the functions were only called from constructors, and (ii) calling class methods from constructors is always a design "smell".
It allows to clarify the logic and reduce the code.
Is nesting constructors (or factory methods) good, or should each do all init work
It's reasonable to chain constructors together, the version with fewer parameters calls the version with more parameters. It makes very clear what's happening, and all the real "logic" (beyond the default values) is in a single place. For example:
public class Foo {
private static final int DEFAULT_X =10;
private static final int DEFAULT_Y =20;
private int x;
private int y;
private int precomputedValue;
public Foo(int x, int y) {
this.x = x;
this.y = y;
precomputedValue = x * y;
}
public Foo(int x) {
this(x, DEFAULT_Y);
}
public Foo() {
this(DEFAULT_X, DEFAULT_Y)
}
}
Not a Java dev here, but in Python this is also allowed and pretty much normal.
Whenever you inherit a class, you might want to call the parent class's constructor prior adding your own stuff-and-recipes.
This allows you to benefit the parent class's construction features. Whenever you do not know exactly what the parent class does you most of the time always call it first in order to avoid the parent's class features and methods being broken.
The fact that the confusion originates from every instance should call one ctor is absolutely right. The constructor chained another is used to avoid code duplication and simplicity because copying same code is really overhead. Sometimes maybe we need two constructors, first one just takes two parameters the other one takes three parameters. But, three parameters-ctor uses same variables of two parameters-ctor. Do you prefer copy-paste same assignmets or merely call the other ctor by this?
As a supplement to the other answers, I would like to share another use for calling a constructor from a constructor that I use often.
Another strategy of constructor chaining that I find useful is providing default implementations / auto-injection for Interfaces.
public class Foo {
private readonly ILogger _logger;
//Default implementation for most cases
public Foo() : this(new DefaultLoggerImplementation()) {}
//DI Constructor that allows for different implementations of ILogger
//(Or Mocks in testing)
public Foo(ILogger logger)
{
_logger = logger;
}
public void Log(string message)
{
_logger.log(message);
}
}
This way if you have a default implementation for an interface it is auto injected via new Foo()
If you have a case with different ILogger behavior it is easily injectable, this also promotes the ability to Mock the interface in your unit testing framework.
I have recently found out that no argument constructor and multiple argument constructor cannnot call each other in turns. What is the underlying reason of this limitation? Some might say that constructors are where resources are initialised. So they must not be called recursively. I want to know if this is the only reason or not. Functions/methods/procedures can be called recursively. Why not constructors?
The answer lies in the fact that the call to another constructor is the first line of any constructor and hence your if condition to break out of recursion will never be executed and hence stack overflow.
The main purpose of the constructor is to initialize all the global variables described in a particular class.
For Example:
public class Addition(){
int value1;
int value2;
public Addition(){ // default constructor
a=10;
b=10;
}
public Addition(int a, int b){
this(); // constructors having parameters , overloaded constructor
value1=a;
value2=b;
}
}
public class Main(){
public static void main(){
Addition addition = new Addition(); //or
Addition addition = new Addition(15,15);
}
}
Here, if you want to make instance of the class you can either make instance by calling default constructor or by calling constructor having parameters. So the constructors are overloaded and not overridden. If you want to call another constructor, that can only be done be putting either this() or super() in the first line of the constructor. But this is not prefferable.
Constructors are not intended to be called explicitly outside object initialization, because it's restricted in most (I guess all) languages. Instead, you can create an additional protected Init(...) member function and call it inside the constructor.
Your statement that constructor cannot call other constructors are not true for every programming languages. At least I know Java can do this, while C++ cannot. But you could easily overcome this limitation by writing a private __init function and let all your constructors call it.
In all languages you've listed objects contain finite (and normally short) set of properties. Each property could contain recursive structure (i.e. list), but it still represented by a single property in the object.
I don't see need to recursively call constructors. It feels like a strange use recursion to initialize several well know properties.
As you've said you can call constructors in non-recursive way to share code in some languages you've mentioned.
C#: Using Constructors
public Employee(int weeklySalary, int numberOfWeeks)
: this(weeklySalary * numberOfWeeks)
{
}
My concern in the code below is that the param to constructor is not actually directly mapped to the class's instance fields. The instance fields derive value from the parameter and for which I'm using the initalize method. Further, I do some stuff so that the object created can be used directly in the code that follows e.g. calling drawBoundaries(). I feel it's doing what is meant by creating(initializing) a Canvas in an abstract sense.
Is my constructor doing too much? If I add methods to call the stuff in constructor explicitly from outside, that'll be wrong. Please let me know your views.
public class Canvas {
private int numberOfRows;
private int numberOfColumns;
private final List<Cell> listOfCells = new LinkedList<Cell>();
public Canvas(ParsedCells seedPatternCells) {
initalizeCanvas(seedPatternCells);
}
private void initalizeCanvas(ParsedCells seedPatternCells) {
setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells);
drawBoundaries();
placeSeedPatternCellsOnCanvas(seedPatternCells);
}
...
P.S.: Sorry if this looks like a silly question; my code is going to be reviewed by an OOP guru and I'm just worried :-0
EDIT:
I read some concerns about the methods in initalizeCanvas() being over-ridden - luckily these methods are private and do no call any other methods.
Anyways, after further research on net I've started liking this more... I hope you guys agree !!??
public class Canvas {
private int numberOfRows;
private int numberOfColumns;
private final List<Cell> listOfCells = new LinkedList<Cell>();
private Canvas() {
}
public static Canvas newInstance(ParsedCells seedPatternCells) {
Canvas canvas = new Canvas();
canvas.setNumberOfRowsAndColumnsBasedOnSeedPatten(seedPatternCells);
canvas.drawBoundaries();
canvas.placeSeedPatternCellsOnCanvas(seedPatternCells);
return canvas;
}
It is generally a bad idea for a constructor to contain non-trivial code. As a rule, constructors should at most assign supplied values to fields. If an object requires complex initialization, that initialization should be the responsibility of another class (typically a factory). See Miško Hevery's great write-up on this topic: Flaw: Constructor does Real Work.
You should never call non-final methods in a constructor. Effective Java does a good job explaining why, but basically your object is not in a stable state before the constructor returns. If your constructor calls methods which are overridden by a subclass, you can get strange, undefined behavior.
Also see this answer.
Although its not the most elegant way to do it, I don't see it as flawed from OO perspective. However, if you are not calling the private method initalizeCanvas from anywhere else within the class, then you can consider moving those three lines to the constructor itself.
I see two potential issues:
Are the methods you call in initializeCanvas private or final? If they are not, it's possible for a subclass to override them and unwittingly break your constructor.
Are you doing graphics operations in the drawBoundaries method? It's good practice for a constructor to do only the minimum necessary to create a valid object. Are those operations necessary for the canvas to have a valid initial state?
It depends.
It is not bad for a constructor to call a private method, provided that the private method doesn't call other methods that could be overridden. However if the method or one of the methods that it calls could be overridden, you can run into trouble. Specifically the override method will be called before the overriding classes constructor runs and will see instance fields before they have been initialized.
A second problem if that the some of the methods in your initalizeCanvas method look like they my "publish" the current object before it has been fully initialized. This is potentially problematic if the application is multi-threaded, and could result in other threads seeing stale field values.
A private init function might be useful if you have multiple constructors where some parameters are defaulted or inferred. After everything is determined, one private init function fills in the object.
In a one-constructor class, probably not.
I've been programming in C# and Java recently and I am curious where the best place is to initialize my class fields.
Should I do it at declaration?:
public class Dice
{
private int topFace = 1;
private Random myRand = new Random();
public void Roll()
{
// ......
}
}
or in a constructor?:
public class Dice
{
private int topFace;
private Random myRand;
public Dice()
{
topFace = 1;
myRand = new Random();
}
public void Roll()
{
// .....
}
}
I'm really curious what some of you veterans think is the best practice. I want to be consistent and stick to one approach.
My rules:
Don't initialize with the default values in declaration (null, false, 0, 0.0…).
Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
If the value of the field changes because of a constructor parameter put the initialization in the constructors.
Be consistent in your practice (the most important rule).
In C# it doesn't matter. The two code samples you give are utterly equivalent. In the first example the C# compiler (or is it the CLR?) will construct an empty constructor and initialise the variables as if they were in the constructor (there's a slight nuance to this that Jon Skeet explains in the comments below).
If there is already a constructor then any initialisation "above" will be moved into the top of it.
In terms of best practice the former is less error prone than the latter as someone could easily add another constructor and forget to chain it.
I think there is one caveat. I once committed such an error: Inside of a derived class, I tried to "initialize at declaration" the fields inherited from an abstract base class. The result was that there existed two sets of fields, one is "base" and another is the newly declared ones, and it cost me quite some time to debug.
The lesson: to initialize inherited fields, you'd do it inside of the constructor.
The semantics of C# differs slightly from Java here. In C# assignment in declaration is performed before calling the superclass constructor. In Java it is done immediately after which allows 'this' to be used (particularly useful for anonymous inner classes), and means that the semantics of the two forms really do match.
If you can, make the fields final.
Assuming the type in your example, definitely prefer to initialize fields in the constructor. The exceptional cases are:
Fields in static classes/methods
Fields typed as static/final/et al
I always think of the field listing at the top of a class as the table of contents (what is contained herein, not how it is used), and the constructor as the introduction. Methods of course are chapters.
In Java, an initializer with the declaration means the field is always initialized the same way, regardless of which constructor is used (if you have more than one) or the parameters of your constructors (if they have arguments), although a constructor might subsequently change the value (if it is not final). So using an initializer with a declaration suggests to a reader that the initialized value is the value that the field has in all cases, regardless of which constructor is used and regardless of the parameters passed to any constructor. Therefore use an initializer with the declaration only if, and always if, the value for all constructed objects is the same.
There are many and various situations.
I just need an empty list
The situation is clear. I just need to prepare my list and prevent an exception from being thrown when someone adds an item to the list.
public class CsvFile
{
private List<CsvRow> lines = new List<CsvRow>();
public CsvFile()
{
}
}
I know the values
I exactly know what values I want to have by default or I need to use some other logic.
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = new List<string>() {"usernameA", "usernameB"};
}
}
or
public class AdminTeam
{
private List<string> usernames;
public AdminTeam()
{
usernames = GetDefaultUsers(2);
}
}
Empty list with possible values
Sometimes I expect an empty list by default with a possibility of adding values through another constructor.
public class AdminTeam
{
private List<string> usernames = new List<string>();
public AdminTeam()
{
}
public AdminTeam(List<string> admins)
{
admins.ForEach(x => usernames.Add(x));
}
}
What if I told you, it depends?
I in general initialize everything and do it in a consistent way. Yes it's overly explicit but it's also a little easier to maintain.
If we are worried about performance, well then I initialize only what has to be done and place it in the areas it gives the most bang for the buck.
In a real time system, I question if I even need the variable or constant at all.
And in C++ I often do next to no initialization in either place and move it into an Init() function. Why? Well, in C++ if you're initializing something that can throw an exception during object construction you open yourself to memory leaks.
The design of C# suggests that inline initialization is preferred, or it wouldn't be in the language. Any time you can avoid a cross-reference between different places in the code, you're generally better off.
There is also the matter of consistency with static field initialization, which needs to be inline for best performance. The Framework Design Guidelines for Constructor Design say this:
✓ CONSIDER initializing static fields inline rather than explicitly using static constructors, because the runtime is able to optimize the performance of types that don’t have an explicitly defined static constructor.
"Consider" in this context means to do so unless there's a good reason not to. In the case of static initializer fields, a good reason would be if initialization is too complex to be coded inline.
Being consistent is important, but this is the question to ask yourself:
"Do I have a constructor for anything else?"
Typically, I am creating models for data transfers that the class itself does nothing except work as housing for variables.
In these scenarios, I usually don't have any methods or constructors. It would feel silly to me to create a constructor for the exclusive purpose of initializing my lists, especially since I can initialize them in-line with the declaration.
So as many others have said, it depends on your usage. Keep it simple, and don't make anything extra that you don't have to.
Consider the situation where you have more than one constructor. Will the initialization be different for the different constructors? If they will be the same, then why repeat for each constructor? This is in line with kokos statement, but may not be related to parameters. Let's say, for example, you want to keep a flag which shows how the object was created. Then that flag would be initialized differently for different constructors regardless of the constructor parameters. On the other hand, if you repeat the same initialization for each constructor you leave the possibility that you (unintentionally) change the initialization parameter in some of the constructors but not in others. So, the basic concept here is that common code should have a common location and not be potentially repeated in different locations. So I would say always put it in the declaration until you have a specific situation where that no longer works for you.
There is a slight performance benefit to setting the value in the declaration. If you set it in the constructor it is actually being set twice (first to the default value, then reset in the ctor).
When you don't need some logic or error handling:
Initialize class fields at declaration
When you need some logic or error handling:
Initialize class fields in constructor
This works well when the initialization value is available and the
initialization can be put on one line. However, this form of
initialization has limitations because of its simplicity. If
initialization requires some logic (for example, error handling or a
for loop to fill a complex array), simple assignment is inadequate.
Instance variables can be initialized in constructors, where error
handling or other logic can be used.
From https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html .
I normally try the constructor to do nothing but getting the dependencies and initializing the related instance members with them. This will make you life easier if you want to unit test your classes.
If the value you are going to assign to an instance variable does not get influenced by any of the parameters you are going to pass to you constructor then assign it at declaration time.
Not a direct answer to your question about the best practice but an important and related refresher point is that in the case of a generic class definition, either leave it on compiler to initialize with default values or we have to use a special method to initialize fields to their default values (if that is absolute necessary for code readability).
class MyGeneric<T>
{
T data;
//T data = ""; // <-- ERROR
//T data = 0; // <-- ERROR
//T data = null; // <-- ERROR
public MyGeneric()
{
// All of the above errors would be errors here in constructor as well
}
}
And the special method to initialize a generic field to its default value is the following:
class MyGeneric<T>
{
T data = default(T);
public MyGeneric()
{
// The same method can be used here in constructor
}
}
"Prefer initialization in declaration", seems like a good general practice.
Here is an example which cannot be initialized in the declaration so it has to be done in the constructor.
"Error CS0236 A field initializer cannot reference the non-static field, method, or property"
class UserViewModel
{
// Cannot be set here
public ICommand UpdateCommad { get; private set; }
public UserViewModel()
{
UpdateCommad = new GenericCommand(Update_Method); // <== THIS WORKS
}
void Update_Method(object? parameter)
{
}
}