The Question
In Java, according to standard code style and design principles, when is it more appropriate to modify an object's internal data, and when is it more appropriate to create a new object using the modified data?
For example, let's say I have some class, Vector2D, which holds an x component and a y component, and I want to rotate that vector:
Approach A
public class Vector2D{
private int x;
private int y;
public Vector2D(int x, int y){
this.x = x;
this.y = y;
}
public void rotate(double angle){
//code for finding rotated vector
x = rotated_x;
y = rotated_y;
}
}
A Vector2D object could then be rotated with vector1.rotate(angle)
Approach B
public class Vector2D{
private final int x;
private final int y;
public Vector2D(int x, int y){
this.x = x;
this.y = y;
}
public Vector2D rotate(double angle){
//code for finding rotated vector
Vector2D rotated = new Vector2D(rotated_x, rotated_y);
return(rotated);
}
}
A Vector2D object could then be rotated with vector1 = vector1.rotate(angle)
Findings so far
My research into the issue so far has led me to believe that approach B is useful for allowing method chaining, e.g. vector1 = vector1.rotate(angle).scale(scalar), which has it's own benefits, more on the readability side of things.
It has also led me to realise that approach B allows you to make an object immutable, so I suppose by extension my question is also:
When is it appropriate to make an object immutable, especially in this example case? (and in general, for Points, Vectors, Polygons, etc. Should all these types be immutable?)
Edit:
The project I had in mind while creating this post is a game, in which entities are represented by Polygons, and are manipulated using vectors.
I believe that because of intended application, making sure the classes are thread-safe should not be an issue, as Vector and Polygon data should only ever be altered by the logic thread anyway.
This also means that these operations could potentially be being done 60 times per second (every game tick), for every single entity. Does this mean that any overheads from instantiating new objects each time could quickly add up?