Subtleties of Inheritance - java

Let's say SList is a super class of TailList.
If I execute the following codes,
SList s;
TailList t = new TailList();
s = t;
is this same as doing SList s = new TailList();?
Now, is static type of t still TailList?

When you execute SList s = new TailList();, what happens is the following:
new TailList() is invoked, creating a new object which the constructor of TailList is run for. When the constructor finishes, an anonymous TailList reference is returned.
The anonymous TailList reference is assigned to s.
Since a TailList is inheriting from SList, you can also refer to it by that. The reference to the object doesn't change the object itself.
Imagine I put a trash bin somewhere, and then tell someone who doesn't know of that object being a trash bin that I put a "container" at that location. The trash bin is indeed a container, but that person only knows that it's a container. This doesn't change the fact that it's a trash bin, but the other person can't safely assume that he can put trash in there, or that it is scheduled to be emptied at any time, therefore he wouldn't know to invoke this functionality on the "container" that he is refering to.
So for instance, let's say we have the following code:
String s = "Hello there";
Object o = s;
o is now refering to a String object, but is treating it as an "object", it doesn't know that it has a length, or that it contains characters, even though it does.
s on the other hand, while still refering to the same object that o is refering to, knows that this object is a String, and can use String functionality on that object.
If we wanted to, we could assume that o is a String by a mechanism called "casting":
String s2 = (String)o;
We now refer to the object referenced by o as a String. All of this changes nothing for the object itself, it's all a mere change in reference. As if, for the previous analogy, the person who was told about the mysterious "container", will assume that the container is more specifically a "trash bin". We could also make a wrong assumption, that the container is a packaging container
Integer i = (Integer)o; // throws ClassCastException
Fortunately, when we assume wrongly in Java, we get a ClassCastException, unlike in real life where if you put your items into a trash bin while refering to it as a packaging container your belongings will be thrown to garbage.
Or perhaps, what is confusing you is that first assignment. Well, new TailList() part of SList s = new TailList(); by itself is a static invocation of the constructor of TailList, and it will always return a TailList reference. The assignment that comes afterwards will still refer to the TailList object that was constructed by the invocation.
TL;DR
Yes, it's the same thing.

The object will be instantiated as TailList, and the assignment won't change that. (It would be a neat trick if the language could change the implementation class on assignment ;) )
For example, you can always go
TailList t = new TailList();
Object o = t;
Does that make it more clear? The object is still the same implementation class. It' not going to change to an Object, even though we're referencing it that way.
You could always do a System.err.println(s.getClass().getName()) and see.
BTW this is actually polymorphism rather than inheritance, because you're referencing the object as a class higher in the hierarchy. Inheritance would be if you called t.slistMethod() without overriding it.

In statically typed object-oriented languages, both objects and variables have an associated type.
The type of a variable (the 'static type') is specified by the programmer when declaring the variable. It never changes.
The type of the object referenced by the variable (the 'runtime type') must be either the same or a subtype of the variable's declared type. An object never changes type, but the variable may be assigned a different object of a different type.
The first snippet declares two variables, s of type SList and t of type TailList. It creates an object of type TailList and stores a reference to it in both variables.
The second snippet declares a variable s of type SList, creates an object of type TailList, and stores a reference to it in s.
The end result in both cases is that s contains a reference to an object of type TailList. The difference is that in the first snippet there is an additional reference to the object stored in variable t (which still has a static type of TailList).

Is
TailList t = new TailList();
SList s = t;
The same as
SList s = new TailList();
Yes, except there's no separate reference of type TailList held to the new object, so you'll only be able to access methods from SList (unless you cast).

Related

Is it possible to have values for class object in java, if yes how can we acquire it?

Let's say, I am initializing a class obj as follows:
<class> obj = <some value>;
Is it possible to initialize as such I mean we initialize String and primitive values like that, But I mean for any class. And how can we get them so they can be used in some method of the same class?
Yes if it is for built in types like string, int, float etc. These built in types are pass by value. Which means if you say int a = 5, 5 is copied over to memory location.
If you are asking about your class, I do not think so. Unlike C++ you cannot overload operator. Another reason why you cannot do this is objects are pass by reference, meaning
MyClass myObject = <someValue>;
<someValue> is not copied to memory where myObject lives, instead reference (address of) it is. Thus, you need to have new myObject().
One disclaimer you can do this:
MyClass objA = new MyClass();
MyClass objB = objA;
but it is still copying reference not the actual values from myObj.
OP please read this.
While I think from some aspect this question is duplicate of this, I think the levels of knowledge between OPs of these questions is so far apart that I am not going to flag it.

Java object creation difference

I'm new to OOP concepts in Java. What is the difference between these two incidents?
1.
ClassName obj_name = new ClassName();
obj_name.method();
2.
new ClassName().method();
A good explanation is much appreciated. Thanks
In Option(1), you are still having/holding the reference to the object, so you can reuse that reference to access/call the other members(method/variables) of the object (class).
In Option (2), you don't have the reference (i.e., reference has been lost), so you will NOT be able to use it again.
One point to remember is that if you want to access the same object members multiple times, you need to hold the reference (use option 1 above), rather than creating the object (option 2) again and again (which is costly operation i.e., occupies memory).
Please refer the below link for more details:
https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html
The reference variable obj_name hold the object of ClassName.through which you can call the instance method of ClassName through reference variable obj_name.
Whene ever we create an object and dont assign its reference to any reference variable its Known as Anonymous object instantiation.The Advantage of this type of instantiation is that you can only do the limited operation on that.Like you can call a single method.
If you want to perform mopre operation then reference varaibale which hold the object is better approach.If you have multiple method in your class and you want to use them then option 1 is right choice.
for details please go through this Link
While they might accomplish the same objective for the first call, the two approaches do fundamentally different things in terms of class definition and instantiation.
ClassName object = new ClassName();`
object.method();`
This is a case of instantiation. You create a new ClassName object which possesses certain instance fields and methods. It can call these methods, and the result may cause its instance fields to change.
ClassName.method();
On the other hand, this approach does not create an instance of the class. Instead, it calls method as a class attribute. Thus, the result can change fields in ClassName, but it won't necessarily existing fields in already-instantiated objects.
public class ClassName(){
public int attr = 0;
public ClassName(){}
public void setAttr(int value){
this.attr = value;
}
public void method(int value){
this.attr += value;
}
}
Now, using the first approach, we can create a newObj and call newObj.method(100). This will increase newObj's instance variable attr by 100.
To see the difference between the two approaches, let's use setAttr(200) to change the object's attr to 200.
Next, if we just use ClassName.method(100), the class's attr value will become 100 for all future instances of ClassName. So if we create ClassName nextObj = new ClassName(), this new instance of ClassName will have attr of 100, while newObj will still have attr of 200.
Hopefully this explains the core difference between the two approaches.
in option 1 you are creating an object with new keyword
followed by constructor and that object is referenced by class_name
obj_name variable so obj_name is pointing to that object.
In option 2 you not referencing to that object. just you make an
object and call the method with no references so that object is
eligible for garbage collection.

New instance of class created or just space in memory allocated?

UPDATE
public Fish mate(Fish other){
if (this.health > 0 && other.health > 0 && this.closeEnough(other)){
int babySize = (((this.size + other.size) /2));
int babyHealth = (((this.health + other.health) /2));
double babyX = (((this.x + other.x) /2.0));
double babyY = (((this.y + other.y) /2.0));
new Fish (babySize, babyHealth, babyX, babyY);
}
return null;
}
When new Fish is called, is there a new instance of Fish floating around somewhere without a reference or have I just allocated memory for a new Fish without actually instantiating it?
Can I get the new Fish call to create an actual instance of the Fish with a unique reference name other than iterating through a loop?
When new Fish is called, is there a new instance of Fish floating around somewhere without a variable name or have I just allocated memory for a new Fish without actually instantiating it?
A new Fish object will be created, and will be garbage-collected since there is no reference to it.
The garbage collection will take place (sometime) after the constructor of Fish is done.
In your case that doesn't make much sense, but sometimes it does, if instantiating an object will start a new Thread or run some other routines that you want to be run only once.
If I have only allocated memory or there is a Fish without a name, how can I get the new Fish call to create an actual instance of the Fish with a unique variable name?
This is not very clear. But I sense that you just want to return new Fish(...); and assign it to a variable yourself where you call it, something like:
Fish babyFish = femaleFish.mate(maleFish);
"have I just allocated memory for a new Fish without actually instantiating it?"
No. The instance is initialized (the constructor is executed), but if no reference is kept for this instance it will eventually be garbage collected. Keep in mind that a reference can be kept even if your code doesn't do so, for example if the constructor puts this in some static variable.
The following figure's explanation really helped me when I had confusion in the beginning and I hope will help you as well.You can think of Employee as Fish here.
In your case you created a new Fish() object locally inside a method, so the lifetime of that should be assigned locally as well.The garbage collector always looks for unused objects and will identify this suitable for collection as soon as your method exits,along with other locals defined inside the method.
You are returning null, so this method can not be treated as factory method structure since it does not return an instance.I am not sure what you mean by :
Can I get the new Fish call to create an actual instance of the Fish with a unique reference name other than iterating through a loop?
But I think you asked if you can use the exact new Fish() that is inside the method.The short answer is: no. Although you can definitely create another new Fish() but you need a reference variable to retrieve that address or you can return the instance for the method instead of null,which will be a static factory method and is known as a good practice when you want to separately name your constructors.
In a more specific manner to answer both of your updated questions:
1)You did created a new object when you wrote new Fish() but you did not create a reference variable to really retrieve that object information.It's like you have built a house but you don't know the address of the house.Then you can never get to the house. What will happen is because of the lack of retrieval process, this object will be identified as unused by the garbage collector and hence it will be collected.
2)Since there is no reference/pointer or anything to get the information stored in the new object, you cannot retrieve the exact new Fish() inside the method but you can certainly create another object with a reference variable if you really wish to retrieve the information stored in the object.
Lastly, although it is mainly written for C language usage, the following document by Nick Parlante of Stanford University does an exceptional job in explaining references, stack,and heap memories.Click here.
First, let me clear up some confusion in your terminology: An object doesn't have a name. A variable has a name, but you can have many variables of different names all referring to the same object. Having a named variable reference the object does not mean the object has a name.
If you do new Fish() but don't assign the new reference to anything, the new object will be unreachable as soon as the constructor returns.
There is no way to recover that reference, and the object will be unallocated by the next Garbage Collection run.

Java - How to assign/copy a String content inside a function

Ok, I know that String objects are immutable, so if I need to "copy" the string content from a given string A to another one B I can assign the reference to A like (method 1):
String B = A;
instead of (method 2)
String B = new String(A);
because since there's no way to modify A I'm sure that by referring to B I obtain the same character sequence. Right?
But what happens in this situation described below?
I have a class C that has a String field "subject" and a constructor that take as argument a String "arg" and it must initialize subject to a character sequence equal to the one of "arg".
I have the following code:
public C getSomeC(...){
// some code to set the String A that is defined inside this function
return new C(A);
}
This way I simply call getSomeC(.) from some other point in my program so as to get my C instance.
But what changes whether I use method 1 or 2 in the constructor of C to define C.subject?
If I use the method 1 I pass to C constructor by value the reference of A and I assign to subject the reference to A right? But A has a visibility limited to method getSomeC(..) While I want my C instance to be used outside that method. What happens inside java in this case? Does the reference A be destroyed at the end of getSomeC(.) while the object remains alive because referred by instanceofC.subject?
What if I use method 2 instead?
In short, both methods are fine, your String will be kept, but you should prefer method 1 as it does not create unnecessary objects, as #Paul pointed out.
But A has a visibility limited to method getSomeC(..)
The variable A has this visibility, not the object pointed by A.
What happens inside java in this case? Does the reference A be
destroyed at the end of getSomeC(.) while the object remains alive
because referred by instanceofC.subject?
The String object will exist outside of the method's scope, as long as some reference to it is kept somewhere. And this is the case.
Indeed, a reference is kept in your C object, that's why you're fine.
You are confusing variable scope with object lifetime. Your variable A is only visible inside getSomeC(). But the strin object that variable points to is not applicable from garbage collection until it is not referenced anymore. So, if you pass it to teh constructor and assign it to a field, that field still point to the string object and it persists.
Besides that I'd prefer the first method. String B = new String(A); explicitly creates a new string object that represents the same value. With String B = A; you'll only have one object and save memory. It might not seem much but in big systems or if you do this in many iterations, this can make a difference.
I'm not sure I understand your last paragraph. However, there is basically no reason to ever use: String newString = new String(oldString);. You can always just use: String newString = olString;. (The inclusion of a constructor taking a String and returning a new String that is a copy of the original has been considered a mistake by many since, being immutable, is it better to just reuse the original String.)
The only exception would be if forced to deal with dodgy code relying on the identity (rather than the value) of a String.
You are right - strings are immutable in Java. Which means, that everytime you do something with string a new string with new contents is created.
The only difference is that when you explicitly call new operator it creates a brand new String, which is not taken from so-called "string pool".
E.g.:
"A" == "A"
can be true (not guaranteed, though), but
"A" == new String("A")
is always false.

Recursive pass in object by reference? JAVA

So I have an algorithm that forces me to pass in an object as a parameter recursively and on different depths of the recursion it sets the values of the object. The problem is Java isn't allowing me to do this because they pass in by value or something else that is just messing me up. How can you make sure that the object passed in retains the value set?
You never pass an object as an argument in Java. You either pass a reference or a primitive value. The argument is always passed by value. Java doesn't have pass-by-reference at all.
If you're passing in a reference to an object, and you want to make sure the code you call doesn't change the data within that object, your options are:
Create a copy and pass in a reference to that instead
Make your type immutable in the first place.
EDIT: Just to make it clear, if you have:
Foo f = new Foo();
then the value of f is not a Foo object. It's a reference to a Foo object. If you now call:
doSomething(f);
then the value of f is copied as the original value of the parameter within doSomething. That behaviour is basically the definition of pass-by-value. There's nothing doSomething can to do change the value of f - it will still refer to the same object afterwards. The data within that object may have changed, but it won't be a different object.
In a real-world analogy: if I give you a copy of my address, you can go and paint the front door, but you can't change where I live.
As Jon states, all non-primitives are passed by passing a copy of the reference. You don't have a choice. So your recursive method should be able to update the object if it is mutable. HOWEVER, you can't reassign a reference and expect it to propagate back up the call stack. And remember that Strings are not mutable.
In other words, if you do the following, you have not changed the object that was passed:
void myMethod(Object o){
o = new Object();
}
The above changes the local reference to o but does not change the caller's reference to o. If you need to do something like this you would need to return o.

Categories

Resources