What is the difference between using a method with void, and a constructor? For instance:
public class Time {
public void getMethod() {
}
public Time() {
}
}
Where do I use what?
Thank you
Constructor is called after creation of a new Object(). Typically to do some initialization, to prepare the object. Methods - you call them when you like.
Constructor can be called only once on a certain object. Methods can be called many times.
Constructor can't be static, because it would be not logical, static says "belongs to class, not an object". Methods can be static.
Constructors are methods that belong to a class that are associated with its creation. When you declare an object using Object a = new Object(); This is where constructors are invoked.
You should use constructors to organize any data that you'll need for the rest of the class. For example, if you are making a Time class, the Time constructor might get the current time and set it in a variable to use later.
Other methods are simply that. They are the methods that do some calculations or work for the class. For example, you might have a method that accepts a date and returns the days between the date entered, and the current date.
'void' is simply the return type of the method.
Constructors do not have return types.
A constructor is used to create a new object. Its use leads to the return of a reference to a new object (although technically the constructor does not return the reference itself). As such void would be a meaningless keyword for a contructor. It is used as Object o=new Object(parametersIfApplicable)
On the other hand a method with a void return parameter returns nothing (but would usually change the internal data within the object (or less frequently change one of the objects passed to it); otherwise calling it would be pointless).
Summary
Calling a contructor leads to a new object and returns a reference to it
A (non static) method is called on an existing object to do some work; it returns nothing
A void method specifically does not return any data or object. Pragmatically, a constructor does not return anything.
From a hardware perspective, it initializes the information given at construction allocated by the object declaration by the caller; Doughty provides a broad overview under "References to and Creating Objects".
In order to use the method, getMethod(), you must create an instance of the class Time which is done by constructing its object defined by its constructor.
Time currentTime; //Declaration of object only allocates space in memory for it
currentTime = new Time() //Constructs an instance of Time
//and assigns the object reference to variable currentTime
Then using the method with return of void:
currentTime.getMethod();
Simply calls the method so it performs its tasks. It returns no data or object, but control back to where it was called.
Most of an object's methods will be called the same way when invoked by an object under construction as when invoked from anywhere else. Constructors are different. A constructor is a special sort of void method which cannot be called directly from "normal" code. Instead, all constructor calls must take one of two forms:
A call made at the very beginning of one constructor to a another constructor in either the present class or superclass.
A call generated by the system as part of the following sequence (pseudocode given for x = new Foo(123);):
// "Magical" system routine to create an object without running constructors
Foo temp = InternalSystemMagic.CreateNewObject([foo's type]);
temp.Foo_constructor(p1); // Now invoke the constructor
x = temp; // Note that if the constructor throws, x will not get set.
Note that the compiler can produce code which will first create an object of type Foo without running the constructors, and then call a constructor on the newly-created type, even though neither operation would be legitimate without the other.
Related
If you're going to be passing an argument through several methods of an object, is it wise to save that argument to an instance variable?
For example:
public class Example {
private int[] array;
public void doThingsToArray(int[] array) {
this.array = array;
// `array` doesn't need to be passed as an argument.
doFirstThingToArray();
doSecondThingToArray();
...
}
...
}
In this case, the same instance of Example will be used to call doThingsToArray() on multiple arrays, so you can't just pass array as an argument to Example's constructor.
The pro I can see is that you don't have to pass array as an argument, and - according to Clean Code, at least - the fewer parameters a method has, the better.
I can't come up with a solid con, but I sense something wrong with this situation.
If you're going to be passing an argument through several methods of an object, is it wise to save that argument to an instance variable?
No, it is not wise to do that.
From a design perspective, the value you propose to stash in an instance variable is not a property of the object; rather, it is a property of a given computation. As such, method arguments and / or local variables are where it belongs, and it absolutely does not belong in an instance variable.
From a practical perspective, relying on the value being stashed in an instance variable breaks thread safety. You cannot have multiple computations running simultaneously on the same object, because each one expects to be able to use the same instance variable for its own purposes.
I know Java's constructors can't have any type and interestingly it cannot even be void. A logical explanation for that would be that a constructor returns the initialized object's reference.
MyClass myObject = new MyClass();
The constructor of myClass will now return the object reference after instantiating it and save it in the object variable MyObject and that's why the constructor can't have a return type.
Is that right? Could someone confirm this?
No, actually, the constructors are compiled into the class file like methods having the name <init> and a void return type. You can see these "<init>" invocations in stack traces. The expression new Type() is compiled as an instruction new which just creates the instance of Type and an additional method invokation (invokespecial) to one of the constructors declared in Type.
The verifier will ensure that such a special method is invoked at exactly once on a newly created instance and that it is called before any other use of the object.
It’s just a programming language design decision to let constructors have no return type from the Java language point of view. After all, new Type(…) is an expression that evaluates to the newly created instance of Type and you can’t get a return value from the constructor with that programming language construct. Further, if you add a return type, Java will unconditionally assume that it is a method, even if it has the same name as the class.
That’s simply how it was defined: (It makes parsing the class definition easier)
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration, or a compile-time error occurs.
In all other respects, a constructor declaration looks just like a method declaration that has no result (§8.4.5).
I suppose you could say that constructors have a "special syntax" used specifically for returning instances of the desired object. You do not specify the return type in these cases. The new keyword is used together with the constructor method to produce an instance of the class type.
If you'd like to control the return type of an instance generation method, then you should probably be looking at using a type of factory design pattern, wherein a static method creates an instance (using a constructor), and then returns a more explicit type (say for example, the super type, or an interface type).
This pattern is good when you'd like to decide which type to return based on some parameter, but leave the actual type hidden to the consumer of the instance generation method.
A constructor is not a methed. It does not return anything. It is used for initialization purposes, especially useful when those initializations depend on parameters or there is a chance that exceptions will be thrown (though both are optional).
So, unlike a method, it is not inherited and does not have a return type (not even void).
The idea is that you are "constructing" an instance of MyClass by calling the constructor itself. The idea of the constructor is to instantiate and not to return. Having created myObject you can then refer to public methods and variables part of its declaration which will provide you with the required data being returned as an answer to a call. It is important to understand that the constructor does not return anything it simply creates an instance which can then be used to refer to methods and variables (which return data) declared within the instantiated class.
When we create a Subclass object which extends an abstract class, the abstract class constructor also runs . But we know we cannot create objects of an abstract class. Hence does it mean that even if a constructor completes running without any exception, there is no guarantee whether an object is created?
Hence does it mean that even if a constructor completes running
without any exception, there is no guarantee whether an object is
created?
Simply speaking, a constructor does not create an object. It just initializes the state of the object. It's the new operator which creates the object. Now, let's understand this in little detail.
When you create an object using statement like this:
new MyClass();
The object is first created by the new operator. Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object.
Now consider the case of Abstract class and it's concrete SubClass, when you do like this:
AbstractClass obj = new ConcreteClass();
new operator creates an object of ConcreteClass, and invokes its constructor to initialize the state of the created object. In this process, the constructor of the abstract class is also called from the ConcreteClass constructor, to initialize the state of the object in the abstract class.
So, basically the object of AbstractClass is not created. It's just that it's constructor is invoked to initialize the state of the object.
Lessons Learnt:
The object is created by new operator, and not by the invocation of the constructor itself. So, the object is already created before any constructor is invoked.
Constructor is just used to initialize the state of the object created. It does not create an object itself.
An object state can also be contained in an abstract super class.
So, the purpose of invocation of Abstract class constructor, is only to initialize the object completely, and no object is created in process.
See:
Creation of new Class Instance - JLS-Section#12.5
But we know we cannot create objects of an Abstract class
Right but JVM can.
does it mean that even if a constructor completes running without any exception , there is no guarantee whether an object is created ?
The object is definitely created internally.
Does invoking a constructor mean creating object?
Not always. you can invoke constructor using super() and this() but it won't instantiate an object. (but will just invoke the constructor)
class AClass
{
AClass()
{
this(1); // will invoke constructor, but no object instatiated.
}
AClass(int a)
{
}
public static void main(String[] args)
{
AClass obj = new AClass(); // one object instantiated.
}
}
Barring any exceptions, the abstract class constructor is only run from within the subclass's constructor (as the first statement). Therefore you can be sure that every time a constructor is run, it is in the process of creating an object.
That said, you may call more than one constructor in the process of creating a single object, such as Subclass() calling Subclass(String) which calls AbstractClass via a super()call, and so forth.
Subclass == BaseClass + Extras you add in sub class
Thus when you create a subclass by calling its constructor, there is a call to base class constructor as well to make sure that all attributes (of the base class) are also properly initialized.
You can only call the abstract class constructor as a part of a concrete subclass constructor. This is OK, since the abstract class is extended into a concrete class and it is an object of that concrete class that is being created.
When you invoke a constructor using new, a new object is being created.
Now, as you probably already know, every constructor of any subclass, either implicitly or explicitly, directly or indirectly, invokes a constructor from the parent class (which, in turns, invokes one from its own parent class, all the way up to object). This is called constructor chaining.
The above, however doesn't mean that multiple objects are created. The object has been created at the new call and all constructors working on that object are already handed an allocated area. Therefore, constructor chaining does not create new objects. One call to new will return you one object.
This is how the flow works when you invoke the constructor of your subclass:
Constructor of Abstract class runs --> the object is half initialized here.
Constructor of subclass finishes execution --> The object is fully initialized and hence completely created here.
I am completely disagree that the object for an abstract class can not be created and only jvm can does it in case of Inheritance even a programmer can do it a t times whenever or wherever he/she intends to do so by using the concept of anonymous class:
Look at this code and try it by your Own
abstract class Amit{
void hai()
{System.out.print("Just Wanna say Hai");}
abstract void hello();
}
class Main{
stic public void main(String[]amit)
{
Amit aa=new Amit(){
void hello(){Sstem.out.print("I actually dont say hello to everyone");
}};
aa.hello(); }}
My Assumptions:
Static method cannot cannot call non-static methods.
Constructors are kind of a method with no return type.
Given this example...
public class Main {
public static void main(String[] args) {
Main p = new Main(); // constructor call
k(); // [implicit] `this` reference
}
protected Main() {
System.out.print("1234");
}
protected void k() {
}
}
this line prints 1234: Main p = new Main()
this line throws an Exception: k()
Why did the example code do those two things? Don't they conflict with my above Assumptions? Are my Assumptions correct?
1 - Static method cannot cannot call non-static methods.
Sure they can, but they need an object to call the method on.
In a static method, there's no this reference available, so foo() (which is equivalent to this.foo()) is illegal.
2 - Constructors are kind of a method with no return type.
If they should be compared to methods, I would say constructors are closer to non-static methods (since there is indeed a this reference inside a constructor).
Given this view, it should be clear to you why a static method can call a constructor without any problems.
So, to sum it up:
Main p = new Main();
is okay, since new Main() does not rely on any existing object.
k();
is not okay since it is equivalent to this.k() and this is not available in your (static) main method.
No. Constructors aren't ordinary methods in this respect. The whole point of the constructor is to, well, construct a new instance of the class.
So it can be invoked in static scope too. Just think about it: if you needed an existing instance of your class in order to create a new instance of it, you would simply never be able to instantiate it ever.
A few clarifications:
Static method cannot cannot call non-static methods.
Not quite. You can call a nonstatic method from inside a static method, just you need to scope it to a specific object of that class. I.e.
p.k();
would work perfectly in your code sample above.
The call
k();
would be fine inside an instance (nonstatic) method. And it would be equivalent to
this.k();
The implied this refers to the current instance of the class. Whenever the compiler sees an unqualified call like k() within an instance method, it will automatically scope it with this. . However, since static methods aren't tied to any instance of the class, you (and the compiler) can't refer to this inside a static method. Hence you need to explicitly name an instance of the class to call an instance method on.
Rules are simple:
1 - Static method cannot cannot call non-static methods.
That's simply not true. A static method can call a non-static method, just via a "target" reference. For example, this is fine in a static method:
Integer x = Integer.valueOf(10);
int y = x.intValue(); // Instance method!
The real point is "there's no this reference within a static method".
2 - Constructors are kind of a method with no return type.
That's not a really useful model, to be honest. It makes more sense (from the caller's point of view) to consider a constructor as a static method with a return type that's the same as the declaring class, but even that's not a perfect model by any means.
I suggest you think of a constructor as a different type of member. Embrace the differences between constructors and methods, instead of trying to hide them.
Please refer to the Java code below:
class Base{
Base(){
System.out.println("Base Constructor");
method();
}
void method(){}
}
class Derived extends Base{
int var = 2;
Derived(){
System.out.println("Derived Constructor");
}
#Override
void method(){
System.out.println("var = "+var);
}
}
class Test2{
public static void main(String[] args) {
Derived b = new Derived();
}
}
The output seen is:
Base Constructor
var = 0
Derived Constructor
I think var = 0 occurs because Derived object is half initialized; similar to what Jon Skeet says here
My questions are:
Why does the overridden method get called if the Derived class object isn't created yet?
At what point in time is var assigned value 0?
Are there any use cases where such behavior is desired?
The Derived object has been created - it's just that the constructor hasn't been run yet. The type of an object never changes in Java after the instant it is created, which happens before all constructors run.
var is assigned the default value of 0 as part of the process of creating an object, before constructors are run. Basically, the type reference gets set and the rest of the memory representing the object gets wiped to zero (conceptually, anyway - it may already have been wiped to zero before, as part of garbage collection)
This behaviour at least leads to consistency, but it can be a pain. In terms of consistency, suppose you had a read-only subclass of a mutable base class. The base class may have an isMutable() property which was effectively defaulted to true - but the subclass overrode it to always return false. It would be odd for the object to be mutable before the subclass constructor ran, but immutable afterwards. On the other hand, it's definitely strange in situations where you end up running code in a class before the constructor for that class has run :(
A few guidelines:
Try not to do much work in a constructor. One way of avoiding this is to do work in a static method, and then make the final part of the static method a constructor call which simply sets fields. Of course, this means you won't get the benefits of polymorphism while you're doing the work - but doing so in a constructor call would be dangerous anyway.
Try very hard to avoid calls to non-final methods during a constructor - it's very likely to cause confusion. Document any method calls you really have to make very clearly, so that anyone overriding them knows that they will be called before initialization has finished.
If you have to call a method during construction, it's usually not then appropriate to call it afterwards. If that's the case, document it and attempt to indicate it in the name.
Try not to overuse inheritance in the first place - this is only going to become an issue when you've got a subclass deriving from a superclass other than Object :) Designing for inheritance is tricky.
Why does the overridden method get
called if the Derived class object
isn't created yet?
Derived class constructor implicitly calls the Base class constructor as the first statement. Base class constructor calls method() which invokes the overridden implemention in the Derived class because that is the class whose object is being created. method() in Derived class sees var as 0 at that point.
At what point in time is var assigned
value 0?
var is assigned the default value for int type i.e. 0 before the contructor of Derived class is invoked. It gets assigned the value of 2 after the implicit superclass contructor call has finished and before the statements in Derived class's constructor start executing.
Are there any use cases where such
behavior is desired?
It is generally a bad idea to use non-final non-private methods in the constructors/initializers of a non-final class. The reasons are evident in your code. If the object that is being created is a subclass instance, the methods may give unexpected results.
Note that this is different from C++, where the type does change while the object is being constructed, so that calling a virtual method from the base class constructors doesn't call the derived class's override. The same thing happens in reverse during destruction. So this can be a small trap for C++ programmers coming to Java.
There are some properties of the Java language specification that should be noted in order to explain this behavior:
A superclass' constructor is always implicitely/explicitely called before a subclass' constructor.
A method call from a constructor is just like any other method call; if the method is a non-final, then the call is a virtual call, meaning that the method implementation to invoke is the one associated with the runtime type of the object.
Prior to a constructor execution, all data members are automatically initialized with default values (0 for numeric primitives, null for objects, false for boolean).
The sequence of events is as follows:
An instance of the subclass is created
All data members are initialized with default values
The constructor being invoked immediately delegates control to the relevant superclass' constructor.
The super constructor initializes some/all of its own data members, and then calls a virtual method.
The method is overriden by the subclass, so the subclass implementation is invoked.
The method tries to use the subclass' data members, assuming they are already initialized, but this is not the case - the call stack hasn't returned to the subclass' constructor yet.
In short, whenever a constructor of a superclass invokes a non-final method, we have the potential risk of entering into this trap, therefore doing it is not recommended.
Note that there is no elegant solution if you insist on this pattern. Here are 2 complex and creative ones, both requiring thread synchronization(!):
http://www.javaspecialists.eu/archive/Issue086.html
http://www.javaspecialists.eu/archive/Issue086b.html