Reputation: 4128
I was translating some code with a closure from C# to Java but I got an error, the code is this:
public ArrayList<String> getData(){
String pSentence = "SELECT * FROM EMPLOYEES";
ArrayList<String> pList = null;
_con.queryFB(pSentence, (PreparedStatement ps, ResultSet rs) -> {
pList = new ArrayList<>();
try {
rs = ps.executeQuery();
while (rs.next()) {
pList.add(rs.getString(1) + " : " + rs.getString(2) + " : " + rs.getString(3));
}
}
catch (Exception ex) {
}
});
return pList;
}
This is just a closure to execute a query, the closure just make sure that the connection to the database get always closed, but I get the error that "pList" method variable must be final to be used in the closure, a problem I don't have with C#, ok, I make it final and I get a new error that final var pList cannot be modified, so, what I do is move pList out of the method and put it in a private variable like this:
private ArrayList<String> pList = null;
public ArrayList<String> getData(){
String pSentence = "SELECT * FROM EMPLOYEES";
_con.queryFB(pSentence, (PreparedStatement ps, ResultSet rs) -> {
pList = new ArrayList<>();
try {
rs = ps.executeQuery();
while (rs.next()) {
pList.add(rs.getString(1) + " : " + rs.getString(2) + " : " + rs.getString(3));
}
}
catch (Exception ex) {
}
});
return pList;
}
And then it Works, but, I'd like to know if there will be a memory leak or to know if there is a better way to do it, thanks.
Upvotes: 1
Views: 71
Reputation: 1540
You are assigning the pList inside the closure, which is disallowed in java for variables declared outside. Try constructing the ArrayList in the variable initializer (List<String> pList = new ArrayList<>();
), then consider clear
ing it at the top of your callback (if your database utility performs retries).
Incidentally, a decent connection-management utility should allow you to return your result directly from the callback-closure; I'd recommend looking into that approach, to avoid these concerns entirely.
Upvotes: 1
Reputation: 306
if you want to use pList outside the method, then define it outside, but use instead another variable inside the method. This inner variable will be deleted after the method finishes, by the garbage collector so would be something like this:
private List<String> pList = getData();
// ... do what you want with it
public List<String> getData() {
public List<String> innerPList = new ArrayList<String>();
String pSentence = "SELECT * FROM EMPLOYEES";
_con.queryFB(pSentence, (PreparedStatement ps, ResultSet rs) -> {
pList = new ArrayList<>();
try {
rs = ps.executeQuery();
while (rs.next()) {
innerPList.add(rs.getString(1) + " : " + rs.getString(2) + " : " + rs.getString(3));
}
} catch (Exception ex) {
ex.printStackTrace();
}
return innerPList;
});
Upvotes: 1
Reputation: 2003
Your function should not both return the result and also assign it to a member variable. It is enough to return the result. In that case, pList can be a local variable.
If you want to cache the result, do that in another function which calls getData()
Upvotes: 0