copying instances to avoid changing java instance state - java

Suppose I have a class
public class Test{
Point[] pq = null;
public Test(int Capacity) {
Point[] pq = new Point[Capacity];
}
public static void main(String[] args) {
Point point = new Point(); // suppose it has a given state `state` equal to 0
Test test = new Test(1);
test.pq[0] = point; // here test[0] has a `state` equal to 0
point.state = 1 //Suppose now I change the `state` of the point instance variable to 1
}
...}
public class Point{
public Integer state = 0;
...
}
I changed the state of the point instance variable to 1
then test.pq[0].state is now equal to 1. How can I prevent my code from this behavior ?
Edit 1, in the Point class, I added getter and setters and turned public Integer state into private Integer state = 0, I added this
public void copy(Point point){
this.setState(point.getState())
}
when I call Test test = new Test(1); test.pq[0].copy(point);, I still get te same problem

The clean way to avoid this problem is to make the Point class immutable:
public final class Point
private final int state;
public Point(int state) {
this.state = state;
}
public int getState() {
return state;
}
// no setter !
}
That way, nobody can modify the state of a point, and everything is safe.
If the point needs to be mutable, and you don't want to let callers modify the state of the points of your Test, then you'll have to make copies:
public class Test {
private Point point; // it would be the same with an array or a list
public class Test(Point p) {
// defensive copy
this.point = new Point(p.getState());
}
public Point getPoint() {
// defensive copy
return new Point(p.getState());
}
}
Or course, if your Test has a list or array of points, and if you make the array or list of points accessible from the outside, you can't guarantee anything. That's why every modification should go through a method of the test (that's what encapsulation is all about):
public void addPoint(Point p) {
pointList.add(new Point(p.getState());
}

Related

Why is global object array suddenly null when it enters a method?

Why would a non-null global array suddenly become null in a method?
I have tried to move the method into the object class and access it that way since the getWeight() method works fine, but I have the same issue. As soon as I step into the viablePaths method the global arrays are null. I am using eclipse to toggle breakpoints and I can see everything in the arrays before I step into the method.
I would like the method to be able to access the paths and archs arrays and return an integer value. With the content of the arrays right now the method should set the pathIndex integer variable to -1. I do not know what else to put for the desired behavior. The desired behavior should be for the the global object arrays to not become null when the method is called.
Currently the error I get is a NullPointerException from the line where the determineViable paths method is called.
public class StackHelpProblem {
public static int numEdges;
public static int queries;
public static Edge[] paths;
public static Edge[] archs;
public static void main(String[] args) {
numEdges = 3;
queries = 2;
Edge[] paths = new Edge[numEdges];
paths[0] = new Edge(1);
paths[1] = new Edge(2);
paths[2] = new Edge(3);
Edge[] archs = new Edge[queries];
archs[0] = new Edge(10);
archs[1] = new Edge(10);
int pathIndex = 0;
// Reachable artifacts set
for (int i = 0; i < queries; i++) {
System.out.println(archs[i].getWeight());
pathIndex = determineViablePaths(archs[i].getWeight());
}
}
// Method to return last index of path that can be traversed
public static int determineViablePaths(int weight) {
for (int i = 0; i < numEdges; i++) {
if (paths[i].getWeight() <= weight)
continue;
else {
return i - 1;
}
}
return numEdges-1;
}
// The edge class
public static class Edge implements Comparable<Edge> {
int weight;
Edge(int weight) {
this.weight = weight;
}
public int getWeight() {
return this.weight;
}
// The Edge comparison method
public int compareTo(Edge other) {
if(this.weight < other.weight)
return 0;
else if (this.weight == other.weight)
return 1;
return -1 ;
}
}
}
the getWeight() works and the determineViablePath(int weight) method does not work. As soon as that method is entered the global arrays become null.
Thank you for any assistance.
Let us analyze the relevant parts of the code to understand why the Exception is thrown and how we can prevent it.
public class StackHelpProblem {
...
public static Edge[] paths;
public static Edge[] archs;
...
}
The two static fields Edge[] paths and Edge[] archs are not initialized and thus implicitly initialized with null.
public class StackHelpProblem {
...
public static void main(String[] args) {
...
Edge[] paths = new Edge[numEdges];
...
Edge[] archs = new Edge[queries];
...
}
...
}
In method static void main(...), two new arrays paths and archs are created. Those do not reference the static fields. Thus, the static fields are still initialized with null.
In method static int determineViablePaths(...), no local variable paths is found, thus static field paths is used, which still is null. Thus, the array-access will result in a NullPointerException.
We can get rid of the NullPointerException by using the existing static fields instead of creating new variables in method static void main(...):
public class StackHelpProblem {
...
public static void main(String[] args) {
...
paths = new Edge[numEdges];
...
archs = new Edge[queries];
...
}
...
}
Ideone demo

Java oop - inheritance

I'm copy and paste this code from the website that I'm working on.
* A Line composes of two Points - a begin point and an end point.
*/
public class Line {
// The private instance variables
Point begin, end; // Object members - instances of the Point class
// Constructors
public Line(int x1, int y1, int x2, int y2) {
begin = new Point(x1, y1); // Construct the instances declared
end = new Point(x2, y2);
}
public Line(Point begin, Point end) {
this.begin = begin; // The caller constructed the instances
this.end = end;
}
// The public getter and setter for the private instance variables
public Point getBegin() {
return begin;
}
public Point getEnd() {
return end;
}
public void setBegin(Point begin) {
this.begin = begin;
}
public void setEnd(Point end) {
this.end = end;
}
public int getBeginX() {
return begin.getX(); // Point's getX()
}
public void setBeginX(int x) {
begin.setX(x); // Point's setX()
}
public int getBeginY() {
return begin.getY(); // Point's getY()
}
public void setBeginY(int y) {
begin.setY(y); // Point's setY()
}
public int[] getBeginXY() {
return begin.getXY(); // Point's getXY()
}
public void setBeginXY(int x, int y) {
begin.setXY(x, y); // Point's setXY()
}
public int getEndX() {
return end.getX(); // Point's getX()
}
public void setEndX(int x) {
end.setX(x); // Point's setX()
}
public int getEndY() {
return end.getY(); // Point's getY()
}
public void setEndY(int y) {
end.setY(y); // Point's setY()
}
public int[] getEndXY() {
return end.getXY(); // Point's getXY()
}
public void setEndXY(int x, int y) {
end.setXY(x, y); // Point's setXY()
}
// The toString() describe itself
public String toString() {
return "Line[begin=" + begin + ",end=" + end + "]";
// Invoke begin.toString() and end.toString()
}
public double getLength() {
return begin.distance(end); // Point's distance()
}
}
So here we have to classes public class Point and public class Line
in the first constructor Public line ....
so as we see here we contruct the class , it's a constructor and there is nothing wrong about how it used or anything wrong about it's logic doesn't exist
but there is also this method public Point... this is not the Point class so how come we can use this method here.
I kinda figured that out since Point acts like some sort of areturn type since in that method we wan't to get begin and begin is a point, an object defined udner the point class. so i get that, that's the only way we can get begin. But once we do
public static void main(String[] args) {
Line l1 = new Line(new Point(7,8), new Point(2,5));
The constructor starts acting here. So at the end new line is formed. but in the constructor there is no such thing as
return line;
or is there return line; but we can't see it? I don't know.
However in the method which takes return type as Point there is a
return point;
But no
return x;
in constructors, I'm having trouble understanding the logic here.
and by the way we can benefit from this method
public Point getBegin() {
return begin;
}
in this way :
l1.getBegin().SOMEPOINTMETHOD;
but what if we don't do such a thing and just initiate
l1.getBegin();
what kind of output will we get? I know the output type is going to point, but since point is an object and since we didnt input the instances of the object we won't get anything right? Eclipse gives kind of a strange error in this case.
I know it's been so long but I'm just trying to understand the logic here, sorry if I'm too "DUMMY" and please don't judge right away -.- (Same case for off-topicing this topic)
Constructors are a special kind of (class bound) method that implicitly create an instance of the class type. You'll have to use the new keyword to retrieve this instance.
If you use a method with a non-void Returntype, the method body will execute and in the end, it will return an object of type Returntype. It's up to you (e.g. your program) to do something with the returned object, but you can as well just ignore it.
And, above all: This doesn't have anything to do with inheritance!

Making a Class Immutable

I am learning about immutable Objects. I have to make following class immutable. Did i do it right?
import java.awt.Point;
public class MyImmutablePoint {
Point point;
public MyImmutablePoint(Point point) {
super();
this.point = point;
}
public MyImmutablePoint() {
this (new Point (0,0));
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point
}
}
"Immutable" Class:
public final class MyImmutablePoint {
private final Point point;
public MyImmutablePoint(Point point) {
this.point = point;
}
public MyImmutablePoint() {
this (new Point (0,0));
}
public Point getPoint() {
return point;
}
}
Iam not sure about the toString method though.
and maybe returning an object like Point can be modified as well like an array but not sure
No
final Point p = new Point(0,0);
final ImmutablePoint ip = new ImmutablePoint(p);
Two examples:
//change the original Point passed in
p.x = 10
//use the getter and change the Point
ip.getPoint().x = 10
So, first you need to create a defensive copy of the Point taken in the constructor:
public MyImmutablePoint(Point point) {
this.point = new Point(point);
}
Then you need to create a defensive copy of the Point returned from the getter:
public Point getPoint() {
return new Point(point);
}
This all leads me to suggest that it would probably be better not to expose the internal point at all:
public final class MyImmutablePoint {
private final Point point;
public MyImmutablePoint(Point point) {
this.point = new Point(point);
}
public MyImmutablePoint() {
this.point = new Point (0,0);
}
public int getX() {
return point.x;
}
public int getY() {
return point.y;
}
}
Further format your code and order your members.
No it is not immutable. Point can still be modified by the creator of MyImmutablePoint. Ex:
Point point = new Point(1, 1);
MyImmutablePoint immutablePoint = new MyImmutablePoint(point);
point.setLocation(0, 0);

List add function does not operate properly?

public static void main(String[] args) {
// TODO Auto-generated method stub
List<item> l = new ArrayList<item>();
List<Integer> ll = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
l.add(new item(i,i));
ll.add(i);
}
System.out.println(l.get(4).getWeight());
System.out.println(ll.get(4));
}
public class item {
private static int value;
private static int weight;
public item(int val, int w) {
setValue(val);
setWeight(w);
}
public static int getValue() {
return value;
}
public static void setValue(int value) {
item.value = value;
}
public static int getWeight() {
return weight;
}
public static void setWeight(int weight) {
item.weight = weight;
}
}
This is my code, and then item is class take two paratemers. But when I add the item into list, the elelments in list have same value(in this case it is 9). For Integer, there is no problem. I think I miss some critical parts of java feature.
Any help appreciated, thank you in advance.
All of your methods and members of item are static. That is, they belong to the item class, rather than a specific instance of that class. The static members are shared among every instance of the class, and so every new item you create is using the same set of data. You will want to make them not be static.
Check out the following official tutorials for more info, they are concise and well-written and will help you:
Non-static, member variables: Declaring Member Variables
Non-static, methods: Defining Methods
static class members: Understanding Class Members
Once you have done this, as Takendarkk astutely points out in a comment, be sure to use this.value = ... instead of item.value = ... (no longer valid) or value = ... (uses local scope value instead of member).

Is this an immutable class?

I have no idea what immutable class should look like but am pretty sure this one is. Am I right? If I'm not please specify what should be added/removed.
import java.io.Serializable;
public class Triangle implements IShape, Serializable {
private static final long serialVersionUID = 0x100;
private Point[] points;
public Triangle(Point a, Point b, Point c) {
this.points = new Point[]{a, b, c};
}
#Override
public Point[] getPoints() {
return this.points;
}
#Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if (getClass() != obj.getClass()) return false;
Point[] trianglePoints = ((Triangle) obj).getPoints();
for (int i = 0; i < points.length; i++){
if (!points[i].equals(trianglePoints[i])) return false;
}
return true;
}
}
Will this do the trick?
#Override
public Point[] getPoints() {
Point[] copyPoint = {
new Point(points[0]),
new Point(points[1]),
new Point(points[2]),};
return copyPoint;
}
Point class:
import java.io.Serializable;
public class Point implements Serializable {
private static final long serialVersionUID = 0x100;
public int x;
public int y;
public int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this.x = that.x;
this.y = that.y;
this.z = that.z;
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
No, you can change what's in the Points array. If you want to make it immutable, have the getter hand out a copy of the Points array, not the original.
try this:
Triangle triangle = new Triangle(a, b, c);
triangle.getPoints()[1] = null;
System.out.println(Arrays.toString(triangle.getPoints()));
Also Point needs to be immutable (as Nikita Rybak points out). For how to copy arrays see how to copy an array in Java.
No, it's not. You expose the Point[] and a caller could modify its contents. Also, your class is not final, so someone could subvert it by subclassing it.
No, it's definitely mutable.
Not only do you expose the actual Point[] array, you don't defensive-copy (Bloch 2nd ed., Item 39) the Point objects themselves when taking them in via the constructor.
The Point[] array could have items
removed or added to it, so it's
mutable.
You could pass in Points a,
b, and c, then call setX() or setY()
on them to change their data after
construction.
Close. For one thing, an immutable class should make it's fields final, but that's not a requirement.
However, you are exposing an array through the getter, and that is not immutable. Make a defensive copy using Arrays.copyOf(array, length):
#Override
public Point[] getPoints() {
return Arrays.copyOf(this.points,this.points.length);
}
Here's what I'd do to make this class immutable, with the help of Guava. I see from the #Override in the code you posted that IShape seems to require a Point[] from the getPoints() method, but I'm ignoring that for the sake of example since the use of object arrays is a rather poor idea, especially if you want immutability (since they cannot be immutable and all).
public final class Triangle implements IShape, Serializable {
private final ImmutableList<Point> points;
public Triangle(Point a, Point b, Point c) {
this.points = ImmutableList.of(a, b, c);
}
public ImmutableList<Point> getPoints() {
return this.points;
}
// ...
}
Point should also be more like:
public final class Point implements Serializable {
/*
* Could use public final here really, but I prefer
* consistent use of methods.
*/
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
// getters, etc.
}
In order to be an immutable class, it is not enough that your methods promise not to change the object. In addition to having all fields be private and the methods not allow changing, you must also guarantee that the subclasses have the same promise of immutability. This includes making the class itself final, and ensuring that no references to the fields are ever returned.
A short, but excellent treatment of this can be found in this article:
http://www.javaranch.com/journal/2003/04/immutable.htm
Not only do you need to provide an immutable copy of the internalised array, you also need to make sure that the Point object is immutable.
Consider the following use of the Point class in the standard Java API:
Point a = new Point(1,1);
Point b = new Point(1,1);
Point c = new Point(1,1);
Triangle triangle = new Triangle(a, b, c);
System.out.println(Arrays.toString(triangle.getPoints()));
c.setLocation(99,99);
System.out.println(Arrays.toString(triangle.getPoints()));
It is not immutable because ...
Triangle t1 = new Triangle(new Point(0,0), new Point(0, 10), new Point(10, 10));
Triangle t2 = t1;
System.out.println( t1.getPoints()[0] ); // -> 0
t2.getPoints()[0].x = 10;
System.out.println( t1.getPoints()[0] ); // -> 10
Thus the class is not immutable because you can change the state of an instance (internal Point[] exposed) and this also changes the state of a reference to the same instance.
To make it a true immutable class, you would need methods to separately get X and Y from each point, for example:
public int getPointX(int point) { return points[point].x; }
public int getPointY(int point) { return points[point].y; }
or
public Point getPoint(int point) { return new Point(points[point]); }
or return a copy of the points like you suggested in your edit.
In addition to what others have already noted, you should:
Make your Triangle class final to prevent the creation of mutable Triangles by subclasses.
Declare all the fields final, to catch accidental modification of fields by the class itself.
In "Effective Java," Joshua Bloch provides a list of rules for immutable classes in general, in Item 15: Minimize Mutability.
1) Make members private and final - so
private Point[] points; //should be
private final Point[] points;
2) Make class final so it cannot be sub-classed
3) Exclusive access to mutable members (array) - meaning return copy of and not the reference to mutable members
For the best treatment of this subject refer to Joshua Bloch, Effective Java- item 15
This could be a better Point implementation.
import java.io.Serializable;
public final class Point implements Serializable {
private static final long serialVersionUID = 0x100;
private final int x;
private final int y;
private final int z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(Point that) {
this(that.x, that.y, that.z );
}
public boolean equals(Object obj) {
// assume this is a typical, safe .equals implementation
// that compares the coordinates in this instance to the
// other instance
return true;
}
}
Other than exposing the array (as getters are wont to do) and not being final, being serialisable is "problematic".
As a very nasty man, when deserialising, I can get another reference to the internal array. The obvious fix for this is:
private void readObject(
ObjectInputStream in
) throws ClassNotFoundException, IOException {
ObjectInputStream.GetField fields = in.readFields();
this.points = ((Point[])(fields.get("point", null)).clone();
}
That still leaves the problem of points not being final and exposing the object without points initialised (or worse, but a bit thoeretical, partially initialised). What you really want is a "serial proxy", which you can find out about on the internets...
Note: If you implement equals you should also implement hashCode, probably toString and possible Comparable.
Point itself doesn't have to be immutable for Triangle to be immutable. You just have to do a lot of defensive copies so that nobody has a reference to the Point objects stored in the Triangle.
Also, shouldn't triangle a-b-c equal triange b-c-a (and 4 other permutations)
A immutable class example with mutable field:
public final class ImmutabilityTest {
private final int i;
private final C c1;
ImmutabilityTest(int i, C c1){
this.i = i;
this.c1 = c1;
}
public int getI() {
return i;
}
public C getC1() {
return (C)c1.clone();//If return c1 simply without calling clone then contract of immutable object will break down
}
#Override
public String toString() {
return "ImmutabilityTest [i=" + i + ", c1=" + c1 + "]";
}
public static void main(String[] args) {
ImmutabilityTest i1 = new ImmutabilityTest(10, new C(new D("before")));
System.out.println(i1);
i1.getC1().getD1().name = "changed";
System.out.println(i1);
}
}
class C implements Cloneable{
D d1;
public C(D d1) {
super();
this.d1 = d1;
}
public D getD1() {
return d1;
}
public void setD1(D d1) {
this.d1 = d1;
}
#Override
public String toString() {
return "C [d1=" + d1 + "]";
}
public C clone(){
C c = null;
try {
c = (C) super.clone();
c.setD1(c.getD1().clone());// here deep cloning is handled if it is commented it will become shallow cloning
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c;
}
}
class D implements Cloneable{
String name;
public D(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "D [name=" + name + "]";
}
public D clone(){
D d = null;
try {
d = (D) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return d;
}
}

Categories

Resources