I'm having confusion in calling a non-static method
class A {
void doThis() {}
public static void main(String... arg) {
A a1 = new A();
a1.doThis(); // method - 1
new A().doThis(); // method - 2
}
}
I know that both method-1 and method-2 will call doThis(), but is there any functional difference?
There won't be any difference in execution of those methods but in case of new A().doThis() your're going to lose the reference to the instance of an object you've invoked the method on and you won't be able to use it further in your code. All the changes this method could've done to internal state of the instance will be lost.
In case of A a1 = new A(); a1.doThis(); you're going to preserve the instance of an object (in variable a1) and potential changes made to its state made by method doThis(). Then you'll be able to continue working with this object.
Is there any functional difference?
Both will behave in the same way.
The second option doesn't allow you to reuse that instance again. It may be convenient and concise in one-line return statements (for instance, consider the builder pattern where each constructing method returns a half-initialised instance):
return new Builder().a().b().build();
or if an object was created only to perform a defined action once.
What will be the reference of a new object in method-2?
It is no longer exist (more precisely, we don't have access to it) unless the doThis returns this which you could be able to put in a variable after method execution.
Can I say that method-2 is an improper way of calling a non-static method?
No. Why should we create a variable if this variable will never be used afterwards?
Let's see what the code says in plain English:
A a1 = new A();
a1.doThis();
Create a new instance of A.
Store a reference to it in the variable a1.
Call doThis() on our instance.
Whereas new A().doThis(); reads as:
Create a new instance of A.
Call doThis() on our instance.
So the only difference is whether you store it in a local variable or not. If you don't use the value in the variable any more, then that difference doesn't matter. But if you want to call another method on the same object, let's say a1.doThat(), then you're in trouble with the second solution, as you haven't got a reference to the original instance any more.
Why would you want to use the same object? Because methods can change the internal state of the object, that's pretty much what being an object is about.
Lets take a look at both these methods one by one.
Method-1
A a1 = new A();
a1.doThis();
In method-1, you have a reference of newly created instance of A, i.e a1 and you can call as many methods on this instance of A using this reference a1. Basically you can reuse that particular instance of A by using its reference a1.
Method-2
new A().doThis();
However in method-2, you don't have any variable that stores the reference of your newly created instance of A. How will you refer to that particular instance of A if you have to call any other method on that particular instance of A ? You will not be able to re-use that instance of A if you create an instance using method-2 and you will lose that instance as soon as it is used.
case1:
A a1 = new A();
a1.doThis();
The above two line means object created and doThis(); executed but still object available in the heap memory.
case2:
new A().doThis();
A class object created and doThis(); executed after immediately GC(GarbageColletor) will activate to remove the A object from the heap memory bcz it's a non-referenced object and we can call this object as an anonymous object.
Related
I've one doubt about java reference type creation.
Suppose I've one class below
public class DefaultRepositorySelector
implements RepositorySelector
{
final LoggerRepository repository;
public DefaultRepositorySelector(LoggerRepository repository)
{
this.repository = repository;
}
public LoggerRepository getLoggerRepository()
{
return this.repository;
}
}
And am calling above class's constructor DefaultRepositorySelector somewhere in another class, like below.
repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
As you can see am Initializing a class new DefaultRepositorySelector(new NOPLoggerRepository()) and constructor accepts NOPLoggerRepository instance which is having an implementation of LoggerRepository Interface.
My doubt here is, we are directly passing a new NOPLoggerRepository() as a parameter in constructor which is an instance not a reference type, But constructor is holding a reference type LoggerRepository.
Am not able to understands the flow here, because according to flow when we are creating an instance we passing new object but not a reference to that object but in class's definition constructor accepts reference type of that object.
So at run time, How its taken care when we directly pass an instance but method or constructor accepts reference type of that instance ? Who gets created first reference type of OR Instance ? I think reference type but am not sure how its working behind the scenes..!
My question sounds very silly but please help to understand this ..!
Thanks
An object of class NOPLoggerRepository is created and passed to the method.
That's valid because NOPLoggerRepository implements LoggerRepository.
Rules about when an object is no longer reachable (and available for garbage collection) mean it won't be collected before being passed in (in case you were worrying about such weirdness).
When the constructor has completed the DefaultRespositorySelector holds a reference to the object passed in. However we know (in this case) it's underlying class is NOPLoggerRepository.
All good. The compiler knows when the underlying type may not be the explicit type of a reference and by various mechanisms ensures the correct behaviour. (Glossing over a whole load of stuff some implementation defined).
In java you never 'really' pass a object and class variables don't hold 'objects'.
They are always references to objects.
In casual conversation we all often say things like "I'm passing an NOPLoggerRespository to the constructor" but we really mean I'm passing a reference to a NOPLoggerRespository to the constructor. That's OK because it's always a reference so long as we all understand it's a fine shorthand.
I'm not quite sure I correctly understand your question.
You are going to create the object with the name repositorySelector of type DefaultRepositorySelector. While calling the constructor you need to have a reference of a LoggerRepository, which is a reference to a existing object (or null, if you pass null).
So, to get a reference, you pass new NOPLoggerRepository().
The expressions in parenthesis are evaluated first, so before the constructor of DefaultRepositorySelector can be called, the NOPLoggerRepository will be created as an anonymous object. That is, the object is created and is given no name. But we have the reference to it, which means we know where it is located on the heap.
As NOPLoggerRepository is of type LoggerRepository the constructor of DefaultRepositorySelector accepts the reference - the location of the anonymous object located on the heap and the object, which is named repositorySelector will be created.
Long story short, before calling a method (or constructor) the parameters are evaluated first (object creation, mathematical calculations, other method called and evaluated etc.), then the actual method can be called with the evaluated arguments.
The general idea of
Java is pass by Value
in objects does pretty much varie from premitive types .
in your code :
repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
the (new NOPLoggerRepository() is considered an Ignored Instance for the code scope in wich is invoked .
the thing in here is when you invoked the new DefaultRepositorySelector it did nothing at first as the parameters are invoked first , so in the ordered sequence
new NOPLoggerRepository() is invoked and created a new instance with no refrence on it on the heap .
new DefaultRepositorySelector is invoked and do ask for it's RepositorySelector instance wich is located with no any refrence in the example .
the JVM create the sole refrence for that object in your constructor and then another one (when your constructer pops off) in your class a .
so in short . it is still by refrence but just behind the scene .
What you're referring to is commonly known as dependency injection. First, the object that's being injected is instantiated, and then the dependent object. SO answer here.
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.
for example, lets say you have:
class X
{
public void foo()
{
}
}
and then in your main you have
X anX = new X();
anX.foo();
X bX = new X();
bX.foo();
is the "foo" method being duplicated for every instance of X? Or is it that each instance just re-uses the foo method code.
It will reuse the method code for each object. What changes is the implicit argument, which is the object you invoke the method on.
Instance methods are despatched (more or less) using a Class pointer and an internal virtual-method table. Similar, but slightly more indirect & slower, for methods accessed via an interface.
Class VMTs and method code are loaded once per ClassLoader & then shared between all objects using the method. Thus class type information & method code are not duplicated in memory.
Objects always keeps their Class pointer and the (internal) virtual-method table. This applies whether casting to a subtype or assigning to a supertype. Object Class and the internal pointer are assigned at construction and invariant for the lifetime of the object.
Static methods OTOH are not virtualized, do not use a VMT & despatch according to the static type of the reference. This is resolved at compile time.
When constructing a new object, I use the following code. In this code, is the object reference the variable 'a'?
BankAcc a = new BankAcc();
Also, out of interest, if the above constructs a new object to the variable a, what does the following do? Does it just create a new object without a variable/object reference?
new BankAcc();
Thanks!
Yes and yes.
The second one might be useful when you just want to use an anonymous object without caring about having a reference. Like:
new Thread(new Runnable() {
public void run () { }
}).start();
As explained in this Java tutorial, the creation of an object by using
BankAcc a = new BankAcc();
is a multi-step process. You have the declaration, instantiation and the initialization step
I will only highlight the most interesting parts from that tutorial which are relevant to your question:
To declare a variable, you use type name; (in this case BankAcc a;), which indicates a will/can be used to refer to data of type BankAcc. At this moment, a does not reference any object
To instantiate ayou use the new keyword. This will allocate memory for a new object and returning a reference to that memory. The new operator needs one single postfix argument: a call to a constructor. Whether or not you assign the reference returned by calling new to a variable or not is your choice. You can also use this reference directly in an expression (e.g. new Rectangle().height;)
The initialization is the actual call to the constructor, which initializes the new object. The constructor is invoked by the new operator
new BankAcc() creates the object and calls the constructor. Sometimes you need to do that, for example:
Rectangle rect = new Rectangle(new Point(100, 200), new Dimension(100, 300));
That is just an example of code so that you can see how it can be used.
Yes, it just creates object, but it won't be assigned to any reference, so you can't access that object and do any operations on that object. It will just stay there in memory until garbage collected.
Yes, and yes.
Note that just creating a new instance of a class without holding a reference to it is not unheard of (though not necessarily ideal), as the constructor of the class may do everything that is expected for a given operation.
The second line of code instantiate an anonymous instance of BankAcc class.
It is a quick way to instantiate a class,it is usually used when you need the reference only one time, for example to pass a class instance to a method argument :
myFunc(new BankAcc());
Yes the variable reference is "a" and yes new BankAcc(); creates a new object with no variable thus making it anonymous.
I think Sun some it up pretty nicely,
"The new operator instantiates a class by allocating memory for a new object and returning a reference to that memory. The new operator also invokes the object constructor."
So yes a is a reference to the object BankAcc you instantiated with the new operator i.e. you are assigning = the return of new to the variable a which is a reference to an instance of type BankAcc
Regarding your second point, this can be done (compiled and executed) but I can't see many reasons why you would unless the constructor did something 'important'.
Edit: please refer to Tudor's answer for examples where instantiating without a reference is applicable
Object is a real time entity or real world entity.
Examples of object is pen,car,board,table,pencil etc.,
Suppose see your class name is Book.here how to we declare object
Book obj=new Book();
I figured out how to have an object pass itself to another and have a field in it updated.
I did so by having ObjectA pass itself to ObjectB. Then ObjectB changes a field in ObjectA.
Starting in Main Method: (and leaving out method headers and such)
ObjA.changeField(Obj2)
In ObjectA
Obj2.callChangeMethod(this);
In ObjectB
Obj1.makeChange();
What I'm confused about is why did I have to pass "this" in line2 versus passing ObjA?
Thanks
The reason is quite simple actually: it all has to do with the scope of the variables.
Here is a slightly embellished version of the code you presented:
public static void main(String[] args) {
ObjectA Obj1 = new ObjectA();
ObjectB Obj2 = new ObjectB();
Obj1.changeField(Obj2);
}
The thing to notice about this code is that Obj1 and Obj2 are declared inside of the main method. This means that they belong to the main method, and cannot be used outside of main. This is what the "scope" means. If a variable is declared inside a class, only that class has access to it. If declared in a method, only that method can use it. The same holds for loop structures, and any other kind of block you can imagine. Essentially, if the variable was declared inside a pair of {}, then it belongs to that pair of {}.
So now if you look at your ObjectA class, you'll notice that it sits all by itself - it wasn't declared as part of the main method, so it can't use the variable Obj1 - the ObjectA code has no idea that Obj1 even exists.
That is why you must use the this keyword. You don't have access to Obj1, so you need to use a "variable" that you do have access to - in this case, you have this which always refers to the current instance of the class.
So although you are still using the same object (the one created by new ObjectA()), you simply have different variables which refer to that object, depending on which code you are currently looking at. The scoping rules do get a little more complex, but the more you play around with Java, and the more you understand classes vs instances vs references to instances, the easier it becomes to use them comfortably.
The only reference an object has to itself is the this keyword. Ultimately, there is no other way for an object to refer to itself.