ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

for循环内外创建对象

2021-12-20 10:31:37  阅读:147  来源: 互联网

标签:obj 对象 Object 创建对象 System 循环 new 内外


参考:https://www.cnblogs.com/qlqwjy/p/7598773.html

有时候奇怪的发现往list添加数据的时候,一直被最后一个元素覆盖,首先 ,我们得明白原理:

  •  在new 一个对象的时候,对象的ID是唯一确定的;将对象add入list中时,放入list中的其实是对象的引用 ;而每次循环只是简单  的set 对象的属性,set新的属性值,而add进list中的对象还是同一个对象id,也就是同一个对象;
  • 所以每次add之后,list发现对象引用和之前元素一样,就覆盖掉了之前add的对象。所以循环之后list中的对象是重复的对象。
  • 想要避免这个问题只要每次add时保证对象引用都是不同的即可,即每循环一次重新new一个对象。
  • new的对象应该放在for循环内,每循环一次重新new一个新对象
复制代码
public class Test
{
public static void main(String[] args)
{
for(int i=0;i<10;i++)
{
Object obj = new Object();
}
}
}
复制代码

它的确是在main方法栈中先后创建了10个引用叫obj,然后每个obj指向不同的new出来的对象。

关键是:每次循环体执行完后,循环体内定义的代码块局部变量、对象如果没有被继续引用,就立即被销毁了;即obj变量、new出来的对象都被销毁了。

 一般是循环一次一个新对象,所以如非必要,不要在循环里面创建对象。(有其他的方法嘛???)

 

   用内存角度来解释的话,在JVM的方法栈和堆内存这两个内存中,当运行Object obj = new Object();时,在方法栈的栈顶中放入Object obj,然后在堆中生成一个Object对象,最后方法栈中的obj指向Object对象,这时完成一次循环的内存动作。接着第二次循环, new Object();又产生一个新的Object对象,然后方法栈中的obj指向新的Object对象,第一次循环的Object对象没有被任务变量引用, 成为了垃圾,等JVM垃圾回收器回收。其它循环以此类推了。
  在这里我提一下题外话,JVM有个优秀的算法是,JVM的方法栈,一个方法的调用产生一个栈帧,这个栈帧在方法调用时计算出你有几个局部变量,这个计算会 过滤作用域的,如你的循环后面再建立一个局部变量,那JVM认为只有一个局部变量,因为你的Object obj = new Object();在大括号内,出了大括号就没有了,所以只需要一个位置来存放局部变量即可,也就是说运行到大括号时用这个位置来执行代码,出了大括号后 下一个局部变量就可以接着使用这个栈的这个位置来执行下面的代码了

 

 

再看一个例子:

复制代码
import java.util.ArrayList;
import java.util.List;

public class WWWW {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        List<Integer> nums_1 =new ArrayList<Integer>();
        List<Integer> nums_2 =new ArrayList<Integer>();
        long start_1 = System.currentTimeMillis();
        System.out.println("第一种方法开始:");
        Integer num = null;
        for(int i=0;i<10;i++){
       //十个引用十个对象 num = new Integer(i); nums_1.add(num); } long end_1 = System.currentTimeMillis(); System.out.println("程序结束,用时:"+(end_1-start_1)); long start_2 = System.currentTimeMillis(); System.out.println("第二种方法开始:"); for(int i=0;i<10;i++){
       //一个引用是个对象 Integer num1 = new Integer(i); nums_2.add(num1); } long end_2 = System.currentTimeMillis(); System.out.println("程序结束,用时:"+(end_2-start_2)); } }
复制代码

 

结果:

第一种方法开始:
程序结束,用时:1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
第二种方法开始:
程序结束,用时:0
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

 

解释:

 在for循环内部创建的话,每次执行循环都会创建对象,没什么特别明显坏处,只是会消耗内存。所以我们通常在for循环外部实例化对象,因为它执行一次

 Object obj是创建对象引用,引用的实例地址。 new Object();是创建对象实例
两者都会占用系统资源。
改进之前for循环中创建了10次引用和10实例,改进后是创建了1次引用,10实例。
在方法执行完后内存资源会被回收

 

标签:obj,对象,Object,创建对象,System,循环,new,内外
来源: https://www.cnblogs.com/WLCYSYS/p/15709784.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有