为什么很多人会这么写?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; // 看这里
}
}

解决方案 »

  1.   

    局部变量设为空?
    LZ你理解错了.比如pstmt的使用,是属于引用传递.是传回的引用不是值的副本.引用传递便是传的实际的地址.这里关闭也就意味着外面的对象也关闭了.
    值传递,引用传递.LZ你好生了解了解
      

  2.   

    java中的值传递和引用传递 
    值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参 数的值。
    引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。
    下面举例说明:
    传值---传递基本数据类型参数
    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的操作。
      

  3.   


        /**
         * 关闭数据库连接
         * 
         * @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 不会影响到外面。我做过实验了
      

  4.   

    确实不需要 
        connection = null; 
         pstmt = null;
    纯是多此一举!, 这么写的人对java理解有问题,给楼主造成了误解。
      

  5.   

    connection = null;  
      pstmt = null;
    为了释放 资源啊! 这样 gc 会 自动回收的 ! 一把都 是 写在 finnally 中 if(pstmt!=null ) pstmt.close();
    if(connection!=null) connection.close();
      

  6.   

    确实是多此一举,没必要再写一句connection = null; 
    资源都关闭了,写这个有啥用
    我还是头次见到这种写法 呵呵
      

  7.   


    这是因为当读取connection状态时或者在关闭connection时有异常抛出,那么这个connection是处在一个未知状态的,gc并不会回收。所以要在catch中将其置为null,方便回收。这是很严谨的写法。
      

  8.   

     
    public void closeConnection(Connection connection) {
            try {
                if ((connection != null) && (!connection.isClosed())) {
                    connection.close();  // 不要看这里,这我懂的
                }
            } catch (SQLException e) {
                e.printStackTrace();
                connection = null; // 看这里,这我不懂,我觉得这是多此一举,但为什么很多人这么写
            }
        }这种用法的使用前提是:1,多线程并发访问的安全性。 2,使用到第三方连接池的情况。
    请楼从上面两个方面考虑下,就知道为什么了。
      

  9.   

    上面connection = null;的地方写错了还,放到finally块里,第二段关闭代码那样。
      

  10.   

    确实是多此一举,有一种情况是需要设为null的,就是比如connection是类的成员变量的时候,设为null使得Connection可以被GC,但是你举的这个例子里的connection是方法的参数,完全没必要,估计你看到的代码的作者也是从别的地方copy的,copy来copy去把一些代码也想当然的直接照搬了
      

  11.   

     为什么在关闭connection或statement之后要设为 null ?这貌似是北大青鸟都这样写吧,这种写法是对的,为什么这样说呢:因为一旦出现了异常你不把它们置为空那么它们还会被引用的,这样gc就不会回收它,你只有把它们置为空它们才会被gc回收
      

  12.   

    你仔细看LZ的代码了没?这里的connection是个方法参数而已,方法结束后本来就出作用域了,连引用本身都不存在了,更谈不上还持有对象的引用,而你把方法参数置null了,方法外部该引用的还是引用着,所以说方法参数(同理还有局部变量)置null是没有任何意义的
      

  13.   

    楼主的例子里被设置为 null 的都是局部变量,确实是多此一举不过养成这样的习惯也不是一件坏事
      

  14.   

    fianlly里放这个一般都是需要用完一次之后清除对象时使用的吧,,对象没有被引用就会被java垃圾回收机制回收来释放内存(这个要自己写!),,可以想象下如果超过几千个链接访问数据库每次都不释放用不了多久服务器就不行了吧。
      

  15.   


    虽然说局部变量设置为null是没必要的 但是我在实际的使用中遇见过这种没有设置null就出现了问题.我好像记得是没设置成null 虽然gc会回收但是不是即时的(尽管变量的索引数量在gc里面=0)也就是gc会在你的程序空隙里面抽出来一小段时间来释放资源,也就是说你在没有设置null的时候再次使用这个conn就会出现异常.也许我描述的不够清楚,总之一句话 设置null是必须的好习惯
      

  16.   

    多此一举?太搞了。存在不一定合理,但有他存在的理由。这么多老鸟的经验,你们有人认为多此一举。也许你现在没有遇到让你头痛的问题。一旦遇到了别来论坛JJWW来诉苦就成。
      

  17.   

    public void close() {
    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();
    }
    }
      

  18.   

    置null有没有意义,不光要看作用域,还要看是传值还是传引用,对于对象而言,这个connection传过来的是引用,也就是方法外部那个connection的引用,所以这个方法里所作的操作都是针对方法外部的那个connection的,所以置null是有意义,一方面可以加速gc的工作,另一方面在connection关闭过程有异常抛出的情况下,也可确保connection及时被回收掉。这个问题在小压力的环境不显露,一旦并发数很高的情况,或者被频繁执行的情况下,这句话就极为有意义了。
       我有一个程序,每0.1s采集一次数据,并写入数据库,先没有加这句,结果每天就会因为OutOfMemory而程序死掉,加入后连续工作1年没问题。
       另外建议有的人,有理说理,别没事上来就扯淡.
      

  19.   

    变量的作用域在最近的一对花括号内,如果走出了这对花括号,变量就失去了存在的价值。如果 JVM 内存空间很紧张的时候,待 GC 睡醒会立马进行回收和清理工作。所以是否将变量名指向 null 与不指向都没有什么区别的。
      

  20.   

    对于不定长度的循环是有必要的,比如后台处理,只有检测到某个标记位变化时才停止,如果标记位不变永远运行的那种。
       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;
       }}
      

  21.   

              LargeObject x = null;
              while(this.running) {
                  X = null; // 这里必要,如果不写运行千次万次就很容易出现内存溢出,特别是放在服务器上 跑上几个月不关机的 J2EE 程序。
                  X = new LargeObject(); 
                  ... if (...) break; 
              }
    这种写法就不合理。局部变量的使用有个规则,尽量减小其作用域:while(this.running) {
        LargeObject x = new LargeObject(); 
        ...
    }
      

  22.   


    北大青鸟出人才啊呵呵,多学点吧。
    http://topic.csdn.net/u/20110301/18/cbe35575-bd30-4b3a-8384-308596d949ed.html
      

  23.   


    楼主的程序里设置为 null 的是传进来的引变量,就算不把它设置成 null,等这个方法执行完成之后,参数变量马上就失去其作用域。至于说你的数据采集程序,一定跟楼主的程序有不一样的地方