Don't understand references - java

I just don't understand why t.getName() is Keen if t is assigned to u.
public class StringProgram{
public static void main(String[] args) {
Person t = new Person("Gene");
Person u = t;
u.setName("Keen");
System.out.println(t.getName());//Keen
System.out.println(t.equals(u));//true
}
}
Person class
public class Person{
private String name;
public Person(String d){
name=d;
}
public void setName(String a){
name=a;
}
public String getName(){
return name;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Person)) {
return false;
}
return ((Person) o).name.equals(this.name);
}
}

I am somewhat new too, but I think this is why it will print "Keen".
This will take a foray into java object usage
First thing first, Person t=new Person("Gene") creates a person object that has the name variable, "Gene". Then, it uses a reference, in your case t, to refer to the object. So t will always refer to that Person object.
Then, with your next line, Person u=t, you are creating a new reference that actually refers to the same Person object with "Gene" as the original t reference. Using the = sign made them do the same thing, refer to "Gene", just like equality with math operations in Java makes the left hand equal to the right hand.
Hence, whether you refer to the "Gene" object with u or t, you are referring to the same thing. Hence, in either u.setName("Keen") or t.setName("Keen"), you are reaching for the same object somewhere in memory and doing something to/with it, in this case changing the name variable to "Keen".

It is exactly like user4932934 mentioned in their comment above.
Note that line:
Person t = new Person("Gene");
uses "new" keyword - it tells you that new object is created.
Line:
Person u = t;
simply assigns "t" to "u". Now they refer to the same object in memory, no new instance of Person was created.

Person u = t; makes u refer to the exact same object as t. The same memory location, if that helps. So changing the contents of t changes the contents of u too. Because they're the same object.

I will share with you metaphor regarding the references i once read.
Imagine that your Person object is balloon. Your reference t is a string (rope, not java String) attached to balloon.
So, when you create another reference u which is same like t, you created another string(rope) attached to the one and same balloon (Person).
If you change property of your balloon, e.g. colour, both u and t will see this change, since you only have one balloon attached to both u and t.
So when you assign reference to another reference, you are not creating new object.

Related

How does upcasting works in Java?

I was going with the concept of upcasting and downcasting in java, which are also referred as widening and narrowing.
UpCasting (Widening) happens automatically from derived class to base class. i.e if it has a is-a relationship.
Downcasting has to be done explicitly for run time check.
Okay, I got the concept and everything. But, how its working in this case?
public class ObjPair {
Object first;
Object second;
public ObjPair(Object first, Object second) {
this.first = first;
this.second = second;
}
public Object getFirst() {
return first;
}
public Object getSecond() {
return second;
}
public static void main(String[] args) {
ObjPair objPair = new ObjPair("A",2.2); // Goes widning conversion
System.out.println(objPair.getFirst());
System.out.println(objPair.getSecond());
}
}
ObjPair objPair = new ObjPair("A",2.2);
This is going through upcast, String to object and Double to object and the state gets store in the objPair. Great..!!!
Now,when i do objPair.getFirst() and objPair.getSecond(). It returns me A and 2.2.
How does it remember the string and double, widening/upcast is supposed to remember the super-class states and methods.
How is it able to access sub-class types and values?
Casting of object references does not change the object. It simply allows assigning it into a reference of a different type. The object itself remains the same.
In your case, it needs two Object references, it checks compatibility (no problem there), and then the references are set in variables of type Object. The instances themselves do not change. If they have methods that override those of Object, then the overriding methods will be called.
Thus, when it comes to the part where it prints the object, it simply uses String.valueOf, which calls the object's toString() method. The instance accessed from the Object variables is actually a String object, and String overrides toString() to return itself. Double also overrides toString. These overrides are called, as the instance is still an instance of String and an instance of Double. Only the reference is Object.
Note that you also have a cast from double to Double there. This implicit boxing does change the object - it takes a primitive and creates a new Double from it.
If you simply test this code:
public class Main {
public Object first;
public Object second;
public static void main (String[] args){
Main a = new Main();
a.first = new String("foo");
a.second = 5;
System.out.println(a.first.getClass().toString());
}
}
It outputs class java.lang.String. You can see that it isn't stored as an Object. This is achieved through the use of metadata.
Keep in mind: the object in memory is what it is. If you create a Double object, then it is a Double object resembling the numerical value.
The fact that the variable that holds the reference uses a super type doesn't affect the object referenced to at all!
In your example, the auto-boxing create a Double object under the cover, andgetSecond() returns a reference to that Double object.
That is all there is to this.
Okay so here it is, lets take an example. You have a big square box,named Object and another small box. If you keep this small box inside your big box,all the properties of small box and big box are in the big box.
Then inside the small box,there are two sticks,you are labeling the first stick as 'A' and second as '2.2'.
Now the big box can see what is inside of small box. Now for that instant, the small box is having two sticks and labelled as the way they are.
(Rememeber the Object class is always the super class/parent of every classes in java).

Stack variables in Java (newbie)

I am staring to study java and currently I am learning about the classes setters.
I see that the most common way to make a setter is something like this.
class Apple{
private String _name;
//Setters
public void setName(String name){
_name = name;
}
}
I am used to C so this code raises me a question. If I am setting _name = name in a function, after this function is completed and his stack is discarded why does the variable _name still stores the right value? This is confusing because in C if I assig a pointer to another pointer inside a function like this it would probably cause a segmentation fault (since name is a temporary variable).
In Java, you as an user don't have control over the stack as in C/C++ languages.
In addition, all non-primitive data types (int, double, etc.) are stored in the heap. The user is only able to use references or pointers and is not required to perform any kind of memory management, since a mechanism known as garbage collector already frees those instances which haven't any reference to them. Therefore, there are no such thing as pointers in Java, although you can assign a null value to a non-primitive variable: Foo f = null;
Therefore, in Java you could literally behave what this C++ code does:
class Foo {
Foo( int a ) {}
};
void bar( int a ) {
Foo f(a); // f is placed in the stack
}
The only way you can create an instance of Foo in java would be like this:
void bar( int a ) {
Foo f = new Foo(a); /* f is a reference to the new instance
* (placed in heap) */
}
Actually, name is an instance variable and setName() is an instance method. This means that there is a separate copy of name for every object of the class Apple. The setName() method sets the value for the global variable of the object it is called with to that of its argument. So, even after the stack of the method is discarded, the object exists and so does the value of this object's copy of name. See this example below:
class Apple {
private String name; //instance variable
public void setName(String name) {
this.name = name; //same as what you have written
}
//main method
public static void main(String[] args) {
Apple obj = new Apple(); //object created
Apple obj2=new Apple();
obj.setName("Yolo");
obj2.setName("Yay!");
System.out.println(obj.name); //displays obj's copy of name that holds the value "Yolo"
System.out.println(obj2.name); //displays obj2's name
}
}
This displays
Yolo
Yay!
I hope this makes it clear to you.
You are setting the reference of name to the reference of _name so they look in the same spot in memory. Therefore when the instance of setName disappears and the variable name with it the reference stored in _name remains.
Since you set _name to private it can only be accessed inside the class Apple. You cant change it within your main method and that's why you create the set method so it can be changed by outside classes (I.e. Your main method)

Method taking reference to an array of references?

I missed one of my lectures in Java, and the subject was classes, methods, constructors etc. The homework is one task:
Create a class Person, objects of which describe persons, and which
contains only two felds: name (String) and year of birth (int). In
this class, define
constructor taking name and year of birth;
constructor taking only name and setting the year of birth to default value 1990;
method isFemale returning true if this person is a woman (we assume, not very sensibly, that only women and all women have names ending
with the letter 'a'); otherwise the method returns false;
static function getOlder taking two references to objects of class Person and returning the reference to the older of these two persons;
static function getOldest taking the reference to an array of references to objects of class Person and returning the reference to
the oldest person represented in the array;
static function getYoungestFemale taking the reference to an array of refe- rences to objects of class Person and returning the reference
to the youngest woman represented in the array, or null if there is no
woman in the array.
In a separate class, write a main function in which the whole
functionality of the class Person is tested.
I checked some tutorials and explanations, I didn't go straight here asking for help but after 2 hours of ripping my hair out I've been only able to come up with this:
public class Person {
String name;
int yob; //year of birth
public Person() {
Person jan = new Person("Jan", 1995); //the names are polish
Person joanna = new Person("Joanna", 1993);
Person michal = new Person("Michal", 1980);
Person beata = new Person("Beata", 1979);
Person kazimierz = new Person("Kazimierz", 1998);
Person magdalena = new Person("Magdalena", 1999);
}
public Person(String name, int yob) {
this.name = name;
this.yob = yob;
}
public Person(String name) {
this.name = name;
this.yob = 1990;
}
public static boolean isFemale(String name) {
if(name.equals("Joanna")) {
return true;
} else {
return false;
}
}
public static String getOlder(Person x?, Person y?) { // if I understand the task correctly, I should reference any two names?
if(x?.yob>y?.yob) {
return x?.name;
} else {
return y?.name;
}
//getOldest and getYoungestFemale methods go here
}
}
However, I can't wrap my head around the last three steps. My brain is literally boiling. It would really help if anyone could explain the last three bullet points (getOlder reference to any 2 people and getOldest/getYoungestFemale)
If you don't have time to explain, some example of a "method taking a reference to an array" should be enough for me to get a basic understanding.
Thanks in advance.
Usually.. you don't call it "reference to an array of references of something" You just say "array of something". Even though arrays of objects are arrays of references to objects. Just like a variable for an object is just a reference to an object.
Type heyImAReference = new ImTheObject();
So when you write
Person person = new Person();
You'll have the class Person as type, person as a reference to an instance (or object) of that class and the resulting entity of new Person() as the actual thing that is being referenced. Usually called "instance" or in your case "object".
When it comes to arrays of persons and you do
Person[] persons = new Person[5];
You create via new Person[5] an array instance that has 5 slots, in each slot can go a Person instance figuratively, actually though you have 5 references. Person[0] being the first, Person[1] being the second and so on. So that is an "array of references to objects of class Person".
And persons is a reference to that. So it is a "reference to an array of references to objects of class Person"
static function getOldest taking the reference to an array of references to objects of class Person and returning the reference to the oldest person represented in the array
means nothing more than
static Person getOldest(Person[] persons) {
...
}
I would call that a method that takes an array of Persons and returns a Person. Though technically, it's all just references that go in and come out. The Person objects don't "move"
Firstly create another class which will have main method. Within main create an array:
Person[] parr = new Person[6];
//Then fill all your person to this array:
parr[0] = new Person("name", year);
parr[1] = ....
Then pass this array handler to your methods:
Person p1 = Person.findSomething(parr);
In Person class:
public static Person findSomething(Person[] parr){
for (Person p : parr){
if (p.name.endsWith("a")) return p;
}
return null;
}
Here are some hints which should help you work out the answer yourself without me giving away the solution ;)
1)
public static String getOlder(Person x?, Person y?) {
// if I understand the task correctly, I should reference any two names?
if(x?.yob>y?.yob) {
return x?.name;
} else {
return y?.name;
}
}
This code is almost correct! Just remove the question marks! Also remember that the older person will have an earlier yob. EDIT, also you need to return the reference to the person, not their name, so return either x or y.
2) getOldest and getYoungestWoman
Person[]
is an array of references to Person objects. You should be able to read up on how to loop through the elements of an array and compare values.
3) an extra: if you declare those 6 Person objects inside the constructor, you won't be able to access them in other methods of the class. it is ok to create the Person objects there, but you must declare them outside the constructor. Declare them in the class.

ArrayList references behavior

I am totally confused with ArrayList behavior. Wrote really long post, then realized no one is going to analyse huge code, so just core of the problem. Numbers are for convenience, but in my app these 0 and 24 are dynamic values.
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
vb3=sortedBlocks.get(0);
vb3.setPacketNumber(24);
Essentially my final aim is to: modify and add back to arrayList as new value. However when I do that the guy at position 0 in ArrayList -> unsortedBlocks.get(0); replicates all the changes done to vb3 which of course is not what I want. I want vb3 acquire same values as VoipBlock inside of ArrayList, but I want it to be detached.
This is yet another case of passing by reference. I hate technical explanations - Java passes everything by value, BUT in some cases it passes references by values - this is same as saying not-oily oil. Please help.
It reminds me my start of learning JavaScript - I hated the language - until I watched proper materials at lynda.com - JavaScript Good Practices? - Diagrams killed me. It is the lazy description that turns us-youth away from brilliant technology, not the technology itself.
Please don't let it bother my stress and don't be in any way offended by me, it is just general complaining, maybe someone will look at it and make life better :-)
Thanks for Your time,
Desperately awaiting for help :-)
To achieve your objective you can use clone method. you have to override this method in VoipBlock class
Lets say VoipBlock is as follows
public class VoipBlock {
private int packetNumber;
private String type;
public int getPacketNumber() {
return packetNumber;
}
public String getType() {
return type;
}
public void setPacketNumber(int value) {
packetNumber = value;
}
public void setType(String value) {
type = value
}
public VoipBlock clone() {
VoipBlock clone = VoipBlock();
clone.setType(this.getType());
clone.setPacketNumber(this.getPacketNumber());
return clone;
}
}
So, using the same code you can do like as follows
ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();
VoipBlock vb3 =new VoipBlock();
sortedBlocks.add(vb3);
vb3=sortedBlocks.get(0).clone();
vb3.setPacketNumber(24);
Note that upon calling clone method in above code segment, vb3 get assigned with a new VoipBlock instance. And already inserted VoipBlock to the array remains unchanged.
if you are looking to have kind of sample instances of VoipBlock instances which you later wanted to use in creating similar instances like them. check on immutability/mutability aspect of the code. check "Effective Java" by Joshua Blouch
The following will always copy the reference of b to a:
AnyClass a = ...;
AnyClass b = ...;
a = b;
What you want is probably to clone the object:
a = b.clone();
If I understand correctly, you're a bit unsure about how references and values work. I think the rule of thumb is that primitive types like int, char, boolean and maybe String are copied but Objects just have their reference passed.
The line vb3=sortedBlocks.get(0); completely replaces whatever vb3 used to be with the first thing in the ArrayList. And yes, it won't be a copy, it will be a reference to the same object in memory. So whatever you do will affect both of them. You need to either manually copy over all the information you need or to use a clone() or copy() function.
So for example, in your code, the line VoipBlock vb3 =new VoipBlock(); is a bit redundant because you're overwriting the new instance straight away.
What you really need here is to either use a copy constructor or declare VoipBlock to be Clonable so you can use the clone() method.
What you are interpreting as passing by reference is not actually passing by reference. Java objects are really pointers. Because of this you are passing the value of the pointer. So when you do:
vb3=sortedBlocks.get(0);
you are really assigning vb3 to point to the same locations in memory as sortedBlocks.get(0). Therefore when you manipulate vb3 properties through their setters, the result is seen in both.
If you want two separate pointers you need to use the new keyword or use the clone() method which does this under the hood.
An example to prove this is:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public void doSomething(Person p) {
p = new Person("Bob");
System.out.println(p.getName());
}
public static void main(String[] args) {
Person p = new Person("Billy");
System.out.println(p.getName());
doSomething(p);
System.out.println(p.getName());
}
}
Since Java is pass by value the output will be: Billy, Bob, Billy. If Java were pass by reference it would be Billy, Bob, Bob. If I did not do the new Person in the doSomething() method and instead used the setName() method I would end up with Billy, Bob, Bob also but this is due to the fact I'm now modifying off the same pointer not that I passed by reference as the example above proves that's not the case.

Java Object Reference and Java Methods

I am unable to understand how this works
public void addToRule(Rule r) {
if (!getRuleList().contains(r)) {
getRuleList().addElement(r);
}
}
If I run this code:
obj.addToRule(r);
System.out.println(getRuleList().contains(r));
it prints out true how can this happen?
btw ruleList is a vector member of the main class and is not a static variable(don't think this matters but sharing anyway).
import java.util.Vector;
public class RuleEngine{
private Vector ruleList = new Vector();
public Vector getRuleList(){
return ruleList;
}
public void addToRule(Rule r){
if(!getRuleList().contains(r))
getRuleList().addElement(r);
}
public static void main(String args[]){
RuleEngine re = new RuleEngine();
Rule r = new Rule("Rule1");
re.addToRule(r);
System.out.println(re.getRuleList().contains(r));
}
}
class Rule{
public String name = "";
public Rule(String nam){
this.name=nam;
}
}
OK people have told me that this works because of the pass by reference in java. I get it. but what can i do to get a copy of that object instead of its reference?
I'm guessing getRuleList() is returning a reference to a List (or something similar). Think of it as a pointer (or more specifically, a copy of a pointer) if you're familiar with C. You're working on the same underlying instance of the object when you call getRuleList().
For proof, try: System.out.println(getRuleList() == getRuleList()); The == operator will only compare if the two references are pointing to the same object (not a deep equal like .equals). You'll see that until you call setRuleList() with a different object reference that the statement holds true.
These assumptions are of course without seeing your full code.
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Hope I could help,
Ferdi265
From your comments it looks like you have not completely understood what the difference is between a value and a reference in Java. Basically, objects are always passed around as references in Java.
Consider
class Test {
private List list = new ArrayList();
public List getList() {
return list;
}
}
The getList() method will return a reference to the list object. It will not return a copy of the list object. Doing something like
Test test = new Test();
String s = "ABC";
test.getList().add(s);
System.out.println(test.getList().contains(s));
Will return true since the first time getList() is called, a referece to the list is returned, on which add(s) is invoked. The second time getList() is called, it returns a reference to the same list, not a copy of it, not a new list - the same reference. Calling contains(s) will return true since it the same list onto which the object s was added.
Consider this, however.
Test test1 = new Test();
Test test2 = new Test();
String s = "ABC";
test1.add(s);
System.out.println(test2.getList().contains(s));
This will print out "false". Why? test1.getList() returns a reference to the list inside test1 and test2.getList() returns a reference to the list inside test2. Here, s was added to test1:s list, so it will not be contained inside test2:s list.
It should always print true, because you add the rule to the rule list in case it is not there. What happens is:
you tell the object to add add a rule to its rule list
the objects checks if the rule exists, and if it doesn't, adds it
So it is guaranteed to contain the rule after the code is executed.

Categories