为什么很多人会这么写?connection = null;、pstmt = null;
在 BaseDAO 中或其它类中:
public abstract class BaseDAO { /**
* 关闭数据库连接
*
* @param connection
*/
public void closeConnection(Connection connection) {
try {
if ((connection != null) && (!connection.isClosed())) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
connection = null; // 看这里
}
} /**
* 关闭语句
*
* @param pstmt
*/
public void closePreparedStatement(PreparedStatement pstmt) {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
pstmt = null; // 看这里
}
}
}问题如:pstmt = null ,只是把局部方法里的变量 pstmt 设为了 null,外面的客户程序不是还有一个引用吗?那个没有被设为 null,那方法里为什么要这么写?不是我要这么写,看过很多人的代码都是这样的,加个 finally 里放上 close 最终一定会将它关闭,很好,但为什么要加个 xxx = null 呢?再例如: /**
* 关闭记录集
*
* @param resultSet
*/
public void closeResultSet(ResultSet resultSet) {
try {
if (resultSet != null){
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
resultSet = null; // 看这里
}
}
LZ你理解错了.比如pstmt的使用,是属于引用传递.是传回的引用不是值的副本.引用传递便是传的实际的地址.这里关闭也就意味着外面的对象也关闭了.
值传递,引用传递.LZ你好生了解了解
值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值。
引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。
下面举例说明:
传值---传递基本数据类型参数
public class PassValue{
static void exchange(int a, int b){//静态方法,交换a,b的值
int temp;
temp = a;
a = b;
b = temp;
}
public static void main(String[] args){
int i = 10;
int j = 100;
System.out.println("before call: " + "i=" + i + "\t" + "j = " + j);//调用前
exchange(i, j); //值传递,main方法只能调用静态方法
System.out.println("after call: " + "i=" + i + "\t" + "j = " + j);//调用后
}
}
运行结果:
before call: i = 10 j = 100
after call: i = 10 j = 100
说明:调用exchange(i, j)时,实际参数i,j分别把值传递给相应的形式参数a,b,在执行方法exchange()时,形式参数a,b的值的改变不影响实际参数i和j的值,i和j的值在调用前后并没改变。
引用传递---对象作为参数
如果在方法中把对象(或数组)作为参数,方法调用时,参数传递的是对象的引用(地址),即在方法调用时,实际参数把对对象的引用(地址)传递给形式参数。这是实际参数与形式参数指向同一个地址,即同一个对象(数组),方法执行时,对形式参数的改变实际上就是对实际参数的改变,这个结果在调用结束后被保留了下来。
class Book{
String name;
private folat price;
Book(String n, float ){ //构造方法
name = n;
price = p;
}
static void change(Book a_book, String n, float p){ //静态方法,对象作为参数
a_book.name = n;
a_book.price = p;
}
public void output(){ //实例方法,输出对象信息
System.out.println("name: " + name + "\t" + "price: " + price);
}
}
public class PassAddr{
public static void main(String [] args){
Book b = new Book("java2", 32.5f);
System.out.print("before call:\t"); //调用前
b.output();
b.change(b, "c++", 45.5f); //引用传递,传递对象b的引用,修改对象b的值
System.out.print("after call:\t"); //调用后
b.output();
}
}
运行结果:
before call: name:java2 price:32.5
after call: name:c++ price:45.5
说明:调用change(b,"c++",45.5f)时,对象b作为实际参数,把引用传递给相应的形式参数a_book,实际上a_book也指向同一个对象,即该对象有两个引用名:b和a_book。在执行方法change()时,对形式参数a_book操作就是对实际参数b的操作。
/**
* 关闭数据库连接
*
* @param connection
*/
public void closeConnection(Connection connection) {
try {
if ((connection != null) && (!connection.isClosed())) {
connection.close(); // 不要看这里,这我懂的
}
} catch (SQLException e) {
e.printStackTrace();
connection = null; // 看这里,这我不懂,我觉得这是多此一举,但为什么很多人这么写
}
}唉! 你们看好题!!我不懂的地方是 为什么要设为 = null;我知道里 面和外面 引用的是一个对象,里面 .close(),外面也就关闭了 - . - !我想知道的是 为什么要在关闭之后,把里面的引用设为 null 值, = null 不会影响到外面。我做过实验了
connection = null;
pstmt = null;
纯是多此一举!, 这么写的人对java理解有问题,给楼主造成了误解。
pstmt = null;
为了释放 资源啊! 这样 gc 会 自动回收的 ! 一把都 是 写在 finnally 中 if(pstmt!=null ) pstmt.close();
if(connection!=null) connection.close();
资源都关闭了,写这个有啥用
我还是头次见到这种写法 呵呵
这是因为当读取connection状态时或者在关闭connection时有异常抛出,那么这个connection是处在一个未知状态的,gc并不会回收。所以要在catch中将其置为null,方便回收。这是很严谨的写法。
public void closeConnection(Connection connection) {
try {
if ((connection != null) && (!connection.isClosed())) {
connection.close(); // 不要看这里,这我懂的
}
} catch (SQLException e) {
e.printStackTrace();
connection = null; // 看这里,这我不懂,我觉得这是多此一举,但为什么很多人这么写
}
}这种用法的使用前提是:1,多线程并发访问的安全性。 2,使用到第三方连接池的情况。
请楼从上面两个方面考虑下,就知道为什么了。
虽然说局部变量设置为null是没必要的 但是我在实际的使用中遇见过这种没有设置null就出现了问题.我好像记得是没设置成null 虽然gc会回收但是不是即时的(尽管变量的索引数量在gc里面=0)也就是gc会在你的程序空隙里面抽出来一小段时间来释放资源,也就是说你在没有设置null的时候再次使用这个conn就会出现异常.也许我描述的不够清楚,总之一句话 设置null是必须的好习惯
try {
if(this.rs != null) {
this.rs.close();
this.rs = null;
}
if(this.sta != null) {
this.sta.close();
this.sta = null;
}
if(this.conn != null) {
this.conn.close();
this.conn = null;
}
System.out.println("数据库关闭成功!");
} catch (SQLException e) {
System.out.println("close SQL异常!");
e.printStackTrace();
}
}
我有一个程序,每0.1s采集一次数据,并写入数据库,先没有加这句,结果每天就会因为OutOfMemory而程序死掉,加入后连续工作1年没问题。
另外建议有的人,有理说理,别没事上来就扯淡.
public class Worker extends Thread { private boolean isRunning; public void process() {
LargeObject x = null;
while(this.running) {
X = null; // 这里必要,如果不写运行千次万次就很容易出现内存溢出,特别是放在服务器上 跑上几个月不关机的 J2EE 程序。
X = new LargeObject();
... if (...) break;
}
} public void stop() {
this.isRunning = false;
}}
while(this.running) {
X = null; // 这里必要,如果不写运行千次万次就很容易出现内存溢出,特别是放在服务器上 跑上几个月不关机的 J2EE 程序。
X = new LargeObject();
... if (...) break;
}
这种写法就不合理。局部变量的使用有个规则,尽量减小其作用域:while(this.running) {
LargeObject x = new LargeObject();
...
}
北大青鸟出人才啊呵呵,多学点吧。
http://topic.csdn.net/u/20110301/18/cbe35575-bd30-4b3a-8384-308596d949ed.html
楼主的程序里设置为 null 的是传进来的引变量,就算不把它设置成 null,等这个方法执行完成之后,参数变量马上就失去其作用域。至于说你的数据采集程序,一定跟楼主的程序有不一样的地方