2

Good morning, i'm learning java and i have a question. I have a class "table" with a constructor, that accept a "fields", and put it in PRIVATE variable.

the question is: it is right to pass the object and use a "=" to put in the PRIVATE variable, or it's better to clone it? if i use a "=", the variable inside my class are still editable from the method that used the constructor of the class, and eventually put NULL inside it.

for example:

class Table{
private Field field;

table (Field field)
{this.field=field;}

public String getValue()
{return field.toString(); }

}

main{

Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";

System.out.println(table.field.getValue());
}

and the result is "VALUE2". So in the table passed a value, and then i alter it. but for the "good programming art", it is acceptable, or is better

class Table{
private Field field;

table (Field field)
{this.field=field.clone();}

public String getValue()
{return field.toString();}
}

main{

Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";

System.out.println(table.field.getValue());
}

prints VALUE1

so if i pass a value to a Table, i can't modify it without using the Table methods?

what is the right way to to this?

  • It depends. If the field only contains data then it should be immutable. In that case you don't need to clone it because it can't change. If the object you're storing in the field is something with mutable state, then it still depends, but you probably want to avoid shared mutable stuff. – Mike B Jan 02 '14 at 21:01

4 Answers4

1

This is a good question and points to a real problem. The recommended way to do this would be to have your classes immutable.

So the problem is not in the Table class, but in the Field class - it should only allow the modification of the value through the constructor, not through direct changes or with setters. Doing that you won't have this issue.

eis
  • 51,991
  • 13
  • 150
  • 199
1

Declaring a variable private has nothing to do with its immutability. If the object passed to you is not immutable then I would suggest making a (deep) copy, otherwise you cannot rely on it not being changed elsewhere.

Other way would be making the Field class immutable, then you wouldn't have to make a copy, you would just save the reference in a private field.

Kuba Spatny
  • 26,618
  • 9
  • 40
  • 63
0

There is no right or wrong way to do this in Java. Java passes objects by reference, and you need to understand that objects passed by reference are usually mutable, meaning they can change state. In Java, this is the expected behavior, but it can be confusing at first. It can also be very difficult to manage in a multi-threaded environment.

You do have the option, as @eis has indicated, to use immutable objects. There are many advantages to this, especially in multi-threaded code, but also some disadvantages. That discussion is too long and involved to get into here.

If you are concerned specifically with Java collections, the collections framework allows you to make a collection immutable. See the java.util.Collections.unmodifiable* methods for details on how to do that. Those methods can make an unmodifiable view of a collection without the overhead of cloning the data.

When you want the second object to see your original object over its lifetime, no matter how you change it, clone it before you pass it, or use an immutable object in the first place. When you want to ensure the second object cannot change your object, make it either immutable or use a read-only view as the Java collections do.

dlaidlaw
  • 1,643
  • 17
  • 16
0

Good morning to you too. I guess that you already know that Java is pass by reference value, so in the first case, table.field and field are "pointers" to the same object. Thus, modifying one will modify the other and viceversa. If that is what you want in this case then your first implementation would be correct.

On the other hand, if you just want to pass an object and you wouldn't be using the object field that you created, the following would be better suited:

Table table(new Field("Value 1"));

Lastly, if you just want to pass the value and you field and table.field referencing different objects that happen to have the same value. Modifying one won't modify the other. The clone() method is a valid solution, but not all classes implement this method. If the class Field didn't support the method clone(), your best bet is to implement a method similar to this in the Field class:

class Field {
    //...Your code...
    //First possibility
    public void copyField(Field originalField) {
        this.atribute1 = originalField.attribute1;
        this.atribute2 = originalField.attribute2;
        //This way you copy all the attributes manually
    }

    //Second possibility (a static method)
    public static void copyField(Field newField, Field originalField) {
        newField.atribute1 = originalField.attribute1;
        newField.atribute2 = originalField.attribute2;
        //This way you copy all the attributes manually
    }
}

//**Using each method to make a copy of field1 in field2**
Field field1 = new Field(...);
Field field2 = new Field();
field2.copyField(field1);    //Non-static method
Field.copyField(field1, field2);    //Static method

Yet another solution would be to make a copy constructor which would be almost exactly the same as the non-static method:

public Field(Field fieldToCopy) {
    this.atribute1 = fieldToCopy.attribute1;
    this.atribute2 = fieldToCopy.attribute2;
    //...
}

As you can see there are several correct ways to do this. You need to be able to chose and implement any of them depending on the particular problem you are solving.

user3146897
  • 541
  • 1
  • 5
  • 15
  • 1
    Thanks to all! i'm not new to programming (i was a professional programmer. in my past life:) ), i know that all object are passed for reference, but i'm studing vary books for enhancing my skills, and i would to know the "right way" to do this in programming art. for me it's not enough to do the things works, i want to do the things in the right way! ;) – OppobbaccoOhiOhiOhi Jan 02 '14 at 21:41
  • Java is not pass by reference, it is pass by value - including references, and object variables are references to objects. For more discussion, see [this thread](http://stackoverflow.com/questions/40480/is-java-pass-by-reference). – eis Jan 02 '14 at 22:52