I have a problem with one class in java
this class is public and extends of DefaultHandler
all method of this class are public too ... but the variables are private...
My problem is that if I copy the value in other variable and modify this second variable the first change too.
is like static variables.. but they are no static... any idea!!!
thanks in advance
This is because you are actually modifying the same object. For instance, if you have
Object obj = new Object();
Object obj2 = obj;
You don't actually copy anything, you simply make obj2 "point" (not quite the right term, but it will work for now) to obj. Any changes to obj2 will be reflected in obj. Therefore, if you want to actually copy it, you need to physically create a new Object and then manually copy all of the values into the new creation. You could implement the prototype pattern to copy the object. Primitives don't behave this way so if you were to do the same thing with a double or an int for instance, it would behave the way you expect.
Does all of that make sense?
You are probably having a problem with passing by reference versus passing by value. This page explains what I mean http://www.cs.umd.edu/class/sum2004/cmsc420/sum4v3e01/node6.html.
You probably are copying a reference to a changeable object, not the object itself; so after the copy, you have two references to the same object. Changing that object through either reference will have the same effect.
I can't tell you how to copy the actual object because there's no generic way to do it, but many classes provide a copy constructor or some other way to duplicate themselves. If you need help with that you'd have to provide more details.
Related
Context: I'm making a mini-interpreter-ish calculator thing. I figured that the best way to hold the symbol table was to make an ArrayList of an Object that I've defined (name of the object is WiP). Setting up the ArrayList looks like.
ArrayList<miniVariable> vList = new ArrayList<miniVariable>();
Simple enough, and the miniVariable Object contains the following variables
public String name;
public double value;
public boolean initialized;
They are public because I already made setter/getters in the class with the ArrayList, when I didn't realize you could make one of Objects, and I don't want to move everything over. I probably should.
Question: If I were to call vList.get(index) .value = 5; would it actually change the value being stored in the vList(index)'s value variable? Or does .get(index)just return a copy of the data, and so changing this copy doesn't actually do anything?
It changes the value on the original instance, as one would expect.
Creating a copy of an object in Java only happens explicitly (and usually with some difficulty at that).
A few other notes:
Class names in should be CapitalCase.
Implementing getters and setters on an object holding a list of objects is bad practice as it violates encapsulation. If you're implementing getters and setters, it's best to put them on the class they apply to.
What you are storing in the ArrayList is not the object itself, but reference to object.
So when you do vList.get(i) it is returning you the reference that you previous put in. Which means you are going to access the same object that you previous put in the list, instead of a copy of it.
Get yourself familiar with one of the basic concept of Java, which is Reference and Primitive types.
Some off-topic suggestions:
Make sure you are aware of Java's naming convention. For example, for the class name, it should be MiniVariable instead of miniVariable.
Just to be more accurate: "and the miniVariable Object contains the following variable", MiniVariable is a class, but not an object. You may say "and a MiniVariable object (instance) contains these member fields", or "in MiniVariable class defined the following member fields"
All collections objects stores reference to object , if you change any thing on object directly(accessing through collection) or indirectly ( already have reference of it) it will change the state of the object stored in collection
This question already has answers here:
Java: recommended solution for deep cloning/copying an instance
(10 answers)
Closed 8 years ago.
I have a question about using a LinkedList and the .get() operation. Java as I understand passes objects by reference, so if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B that I can modify and the changes are reflected in A.get(i).
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct? Is the solution that I must create a copy constructor for my class 'temp' in this example. Or is there a better, built-in way to do this?
Thanks for your help.
Java as I understand passes objects by reference..
No. Java pass everything by value. If you have a reference type, the reference is passed by value. See this question.
if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B that I can modify and the changes are reflected in A.get(i).
If you have a list of reference types get(i) will return a reference to a particular instance. The element in the list and your retrieved reference will refer to the same object. So if you change the object in some way, it will be "visible" from both references.
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct?
Correct. You get a reference.
Is the solution that I must create a copy constructor for my class 'temp' in this example. Or is there a better, built-in way to do this?
If you need a deep copy of your object, you must implement it yourself.
Java as I understand passes objects by reference
No. It passes references by value. It doesn't pass objects at all [except in the case of RMI.]
so if I have a linked list called A, and I do temp B = A.get(i), I retrieve an object B
No. You retrieve a reference that refers to B. The same B whose reference you passed when you added it to the list.
that I can modify and the changes are reflected in A.get(i).
Yes, see above.
However, if the object B has within it (Say another LinkedList object), I do not get a deep copy correct?
Correct. Just like the first case. No difference whatsoever.
Is the solution that I must create a copy constructor for my class 'temp' in this example.
Solution to what? I've never used a copy constructor or the clone() method in Java since 1997. What problem are you trying to solve?
Or is there a better, built-in way to do this?
To do what?
It does not return a "deep copy" because there is no copying done at all, at least, not at the object level. Let me explain.
When you have an instance of an object, the variable that references that object is a pointer to the object. The object can be referenced and modified by many variables (pointers). Observe the following code:
// Let's assume I have a custom object class called Student
// Here the object is created and s now points to the new Student object
Student s = new Student();
// Here I create another variable that points to the same object
Student s2 = s;
Those two variables both point to the same object and any changes that one variable makes to the object will then be reflected in the other.
This ties into your list example. If you have a LinkedList of objects, it is actually a list of pointers to objects. So calling get(2) on the list will get a reference to the 3rd object in the list. The object that it's referencing is the object, not a copy. So any references, variables, methods etc. that were in this object will still be there.
I hope that answers your question :)
I don't fully understand when Java passes a copy/value and when it passes a "reference" (the pointer).
I'm trying to assign a copy of a static object I have, but I'm not sure how to go about it.
I have this:
static ArrayList<MyObject> myObjects;
I want to get a copy of myObjects so that I can play around with the values without affecting the original. Does it pass a reference or a copy/value when I use a getter like so:
public static ArrayList<MyObject> getMyObject()
{
return ThisClass.myObjects;
}
What does that return? If it's a reference, how can I get a copy?
I've seen these:
(How do I copy an object in Java?)
(Java: getter method vs. public instance variable: performance and memory)
(Is Java "pass-by-reference" or "pass-by-value"?)
(How can Java assignment be made to point to an object instead of making a copy?)
But I still don't quite understand what I'll get back.
Java will always return a reference and not a copy as long as it's not a primitive type (aka long,int,short,etc or one of the primitive wrappers Long,Integer, Short.
To get a copy you will need to either copy the data, use a copy constructor, or use the method clone which will create a new object with the appropriate values.
Example of a copy constructor with a list, by default this is a "shallow copy" meaning the objects inside are the same.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>(oldList);
For a "deep copy", meaning the objects inside can be mutated without affecting the originals you will need to make a new List then add copies/clones of the object and add.
Example, assuming MyObject has a copy constructor or a clone method.
List<MyObject> myNewCopiedList = new ArrayList<MyObject>();
for (MyObject myo : oldList){
myNewCopiedList.add(new MyObject(myo)); // if there is a copy constructor
myNewCopiedList.add(myo.clone()); // if there is clone method
}
Think of it this way. Java is always pass by value.
For primitives, it is pass by value(actual value).
For objects, it is pass by value-of-reference.
public int square(int a) { //The parameter a is copy of actual int itself.
//So now there are 2 ints
a=a*a; //Only local copy a is actually modified.
//The integer variable passed(in caller function) is not modified.
return a;
}
If you call doSomething(d) where d is an object, a copy of reference pointing to this object is assigned to parameter a but there is only one object.
public void doSomething(Object a) {
// Here the parameter is a reference which points to an
// object, not the object itself
a.doMore(); //But doMore() does things using a different ref but on the same object.
//The object can be modified!
Object b = new Object();
a = b; //Object referenced by passed parameter does not change but
//copy of reference now points to different object.
// Now there is no reference of original object passed in this method.
}
Technically, Java is always pass-by-value. However, for a beginner's thinking, it's easier to think about it this way:
If it's a primitive type, it's pass-by-value.
If it's an object, it's pass-by-reference.
So in your example, you are returning a reference to the same static object in ThisClass. The reason I say this is technically pass-by-value is because your variable myObjects actually stores the memory address of the ArrayList<MyObject> which you declared, and it's this which is passed.
In order to properly make a copy of an object, one must know which non-primitive fields encapsulate
Mutable aspects of the object's state, but not its identity
The identity of an object and other immutable aspects, but no mutable aspects.
Aspects of the object which are expected never to be exposed to any code which might mutate them (and not identity)
Mutable aspects of the object's state, as well as its identity
Based upon what a field encapsulates, a correct copy of Foo
If one of Foo's field which encapsulates mutable state, a the corresponding field in a copy of Foo should hold a reference to a different object with the same state.
If a field encapsulates object identity, that field in the copy must hold a reference to the same object as in Foo--not a copy.
If a field encapsulates only immutable aspects other than identity, then a copy of Foo may either hold a reference to the same object as in Foo, or any object which has the same immutable state, as convenient.
If a field encapsulates both mutable state and identity, because the first two requirements will conflict, it will not be possible to copy the object in isolation.
In some cases, it may be possible to copy a set of mutable objects which use references to each other to encapsulate both state and identity. Such a copy must be performed on the set as a whole; for each object within the set, any field which in the original object encapsulates both the mutable state and identity of another object in the original set must in the copy refer to the corresponding object in the copied set.
To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.
I have a function that returns a user-defined object. First I want to know if that object is returned by reference and what if it was private?
Also, how do I return it as Constant (final) reference because I don't want someone to mess with it? I'm so confused between returning an object and returning object.copy(); or object.clone();
In Java, You always return a reference (unless returned value is a primitive type such as int, float, char, ...).
So, if you don't want the returned object to be modified, you must return a full copy of it (you could use Clonable interface and clone method if your class defines it).
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.
Now to your questions:
1. As you can read here, yes Java always passes the Reference Adress of the Object.
2. If you don't want someone to mess with the values of your Objects, you HAVE to first create a new Object with that information (e.g with Cloneable and clone()), but it's a real mess because you have to make sure, that everything in your Object that is not primitive gets re-created, which is just awful when you have huge Tree-structures of Objects.
I hope I could help,
Ferdi265
What you should really realize is that there is nothing special about "passing" or "returning". Whenever you "pass" or "return" something, it just passes the value of the thing. Period. For any type. Whenever you "pass" or "return" something, it's exactly the same as simply assigning it to a variable.
However, what is the value of the thing you are passing or returning? That is where your confusion seems to lie. Your question asks about "returning an object"; however, such a thing does not make sense in Java. Objects are not values in Java. It is impossible to have a variable whose value is an object.
The only types in Java are primitive types and reference types. Hence the only values are primitives and references. (References are pointers to objects.) In Java, we only manipulate objects through references (pointers to objects). We cannot store an object in a variable; but we can store a reference (pointer to an object) in a variable. So when you talk about passing or returning objects, you are almost certainly instead talking about passing or returning references. And, as said before, there is nothing special about passing or returning references -- the value of the reference (a pointer) is passed or returned.
It returns the object's reference.
say suppose you have a method call like.
Object obj = makeObject();
which creates an Object and returns(which is the reference of the object created in the makeObject method).
1) Yes, it returns a reference to the object.
2) If the method is private, then it can only be called from within the class itself.
3) Making an object final does not stop others from calling methods on it. There are ways to make an object immutable by using packages and method visibility. (Look up how public, protected, and private work)
4) There is no Object.copy()
5) Object.clone() is a messy beast.