Variable reassignment and raw types :-)
John Hendrikx
john.hendrikx at gmail.com
Tue Apr 18 11:08:30 UTC 2023
So, I was doing raw type clean-up in some obscure graphics code, and I
noticed I couldn't get things to compile anymore when I fixed all the
raw types. It turns out that at some point a List (actually a Vector)
which was using raw types was being assigned to another variable that
also held a list, but after fixing the raw types those were actually two
different types of lists.
The code was like this:
public Vector calculate(Vector left, Vector right) {
Vector edges = new Vector();
addEdges(edges, left, AreaOp.CTAG_LEFT);
addEdges(edges, right, AreaOp.CTAG_RIGHT);
edges = pruneEdges(edges);
if (false) {
System.out.println("result: ");
int numcurves = edges.size();
Curve[] curvelist = (Curve[]) edges.toArray(new
Curve[numcurves]);
for (int i = 0; i < numcurves; i++) {
System.out.println("curvelist["+i+"] = "+curvelist[i]);
}
}
return edges;
}
The correct full signature of this method is supposed to be:
public Vector<Curve> calculate(Vector<Curve> left, Vector<Curve>
right);
In other words, Curves go in, and Curves come out. The code starts by
making a new Vector to hold edges (Edge class). It converts all the
curves to edges with the `addEdges` method. Then it calls `pruneEdges`.
Despite the name, this method converts these edges back into curves, but
here is where it gets confusing. The result of this method is assigned
to the variable edges, overwriting the existing Vector (that holds
Edges), and now it holds Curves. The debug code that follows shows
things being casted to Curve, which hints at what is happening (but I
disregarded this initially as it is debug code and might be out of
date). At the end edges are returned, or so you think.
To make things even more confusing, there is a bug in `pruneEdges` that
initially made me assume it actually returns Edges; after I added the
generic parameters this function looks like this:
private Vector<Curve> pruneEdges(Vector<Edge> edges) {
int numedges = edges.size();
if (numedges < 2) {
return edges; // COMPILE ERROR
}
... hundred more lines dealing with Curves ...
return curves; // actual curves!
}
The above doesn't compile anymore because you can't return a
Vector<Edge> as a Vector<Curve>. The correct code here would return an
empty vector, because when there are 0 or 1 edges, you can't make any
curves and they won't encompass any Area (which is what the class is
dealing with). Likely this case is never hit in tests or real use, so
it's not affecting anything in JavaFX.
Long story short, fixing raw type problems can not only lead to less
casting needed, but it can also uncover real bugs :)
--John
PS. in JIRA I noticed that this code sometimes is a bit of a performance
hog; it may help a bit to replace those Vectors for ArrayLists...
More information about the openjfx-dev
mailing list