问题
This question relates to my answer of another of my question. The original question is here
Can anyone explain why the bad code fails in the way explained in the comments (by the wy it is in pseudo code)
// bad code
ResultSet rs = getDataFromDBMS("Select * from [tableName];");
//temp uses a collection member within it to hold a list of column names to data value pairs (hashmap<String,String>)
Object temp = new objectToHoldInfoFromResultSet();
// loop over the result set
while (rs.next)// for each row in the result set
{
for (int i = 1; i <= rs.getNumberColums; i++) {
temp.add(infoAboutColumn);
}
temp.printInfo();// always prints correct (ie current) info
//the print just takes the hashmap member and asks for a
//toString() on it
anotherObject(makeUseOf(temp));// always uses info from first
//iteration. Essentially grabs the hashMap member of temp, and puts
//this into another collection of type
//HashMap< HashMap<String,String>, temp> see the linked question
//for more detail.
}
// Seemingly each loop into the while the temp.doSomethingToData(); uses
// the temp object created in the first iteration
// good code
ResultSet rs = getDataFromDBMS("Select * from [tableName];");
// loop over the result set
while (rs.next)// for each row in the result set
{
Object temp = new objectToHoldInfoFromResultSet();// moving
// declaration
// of temp into
// the while
// loop solves
// the problem.
for (int i = 1; i <= rs.getNumberColums; i++) {
temp.add(infoAboutColumn);
}
temp.printInfo();// always prints correct (ie current) info
anotherObject(makeUseOf(temp));// also uses the correct (ie current)
// info.
}
回答1:
We can't reliably answer this without knowing what temp.printInfo()
and makeUseOf()
are doing. It is easy to implement them to behave the way you describe though.
When you instantiate temp
outside the loop, you will be using the same object throughout all iterations of the loop. Thus it is possible for it to gather data from each iteration (e.g. into a collection). And then it is possible for methods to get data accumulated in the current iteration, as well as from any previous iteration, which may cause problems if it was not intended.
So let's assume temp
contains a collection and in each iteration a column from the resultset is added to it. Now if temp.printInfo()
is implemented to print info about the last element in this collection, while makeUseOf()
is implemented to do something with the first element in the collection, you get the behaviour you observed.
OTOH when you instantiate temp
inside the loop, you will get a new, distinct object in each iteration, which won't "remember" any data from earlier iterations. Thus even with the implementations of temp.printInfo()
and makeUseOf()
outlined above, you will get correct results.
回答2:
I am not sure why the one is good and the other bad. My guess (without knowing what objectToHoldInfoFromResultSet and the other methods behaviour are) is the following:
In the first instance, the "objectToHoldInfoFromResultSet" (should be capitalised) is created once and everytime
temp.add(infoAboutColumn);
is called, new record data is added to the object. I would guess that this info should be cleared for each record... otherwise you'll get a lot of duplication. The duplication is taken care of by re-initialising the holder object. I.e. (1 2 3 4 5 6) instead of the (1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6).
Without knowing more about the various propriety objects, there is not much more I can tell you.
来源:https://stackoverflow.com/questions/11242488/where-to-initiate-object-in-java