zoukankan      html  css  js  c++  java
  • java对象引用-要掌握的细节

    hello ,好久没来了。

    今天我来和大家分享一下有关引用变量的注意事项,一是加深一下自己的理解,二是对这块不太理解的同学可以看看。

    大神可飘过,有什么不对或不足的地方请多多指教,谢谢。

    假设场景:

    有一个统计游戏玩家信息调查问卷系统,玩家填写了调查问卷,会给玩家一些奖励,当然目前这不是我们关注的部分。

    我们需要记录一下玩家的姓名,年龄,邮箱,以及玩家曾经玩过的游戏有哪些。

    既然要记录玩家玩过的游戏,必然要有Game类:

    package indi.bruce.summary;
    
    public class Game {
        
        private int id;   //随便填写一个id
        private String name; //总要有个游戏名字吧
        private String developer;  //游戏是谁开发的
        private String type;   //游戏总要有个类型吧 ,例如:策略,体育,动作等等
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getDeveloper() {
            return developer;
        }
        public void setDeveloper(String developer) {
            this.developer = developer;
        }
        
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        
        
    }

    现在定义玩家类 Player:

    package indi.bruce.summary;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Player {
        
        private int id ;  //玩家编号
        private String name;  //姓名
        private int age;  //年龄
        private  String email;  //邮箱
        
        private List<Game> gameList;  //曾经玩过的游戏,便于分析用户行为
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public List<Game> getGameList() {
            if(gameList == null){
                return new ArrayList<Game>();
            }
            return gameList;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }

    正题开始:

    假设场景1:玩家问卷数据已经存库,玩家要修改自己的信息,而系统需要记录一下到底修改了哪些地方。  

          1)从数据库读取用户的数据Player。

          2)将原来的对象player复制出来一份给temp对象,玩家修改信息在temp对象上修改(既然要记录玩家修改了什么,则需要原来的对象和现在的对象对比)。

          3)两个对象做一下对比,就可以做操作记录了。

    场景1测试代码:

    @Test
    public void sceneOne(){
      Player player = getPlayer(1110);  //从数据库获取的对象
      System.out.println("print player.getName() is:"+player.getName()); 
    
      Player temp = player;  //玩家修改信息全部在副本temp上操作,这样就可以对比到底玩家修改了什么信息,哈哈哈....
      temp.setName("moon");  //玩家修改了名字
      System.out.println("print temp.getName() is:" + temp.getName());  //哈哈...成功了,多简单的事情
      System.out.println("print player.getName() is:" + player.getName());
    	
      /*但是打印结果
      * print player.getName() is:sky
      * print temp.getName() is:moon
      * print player.getName() is:moon
      * 
      * 疑问:为什么只是修改temp属性name的值,而player的name值也变了呢?
          */
    }
    
    //假设该方法是从数据库获取该用户的数据对象,这不是我们目前关注的部分
    public Player getPlayer(int id){
      Player player = new Player();
      player.setId(1110);
      player.setName("sky");
      player.setAge(20);
      player.setEmail("brucetest@indi.com");
    
      return player;
    
    }
    

      

    为什么会出现上面的情况呢,来分析一下引用变量的工作原理:

      1.代码中"Player player = getPlayer(1110);"做了两件事:

        1)将玩家1110数据从数据库数据库读出来(这部分假设从数据库读出来),并加载的堆内存中(player对象实际上只存在堆内存中)。

        2)新建一个引用变量player(其实就是指针)指向堆内存的player对象(也就是记录堆内存中player的内存地址)

      2.代码"Player temp = player;"做了一件事:

        新建引用变量temp,并且指向堆内存中的player对象。

      总结:所以不管是针对栈中的引用变量temp,还是栈中的引用变量player操作,实际上都是操作堆内存中的player对象。

      注意:解决场景1出现的问题,需要引入一个概念"深拷贝",概念请问度娘.

         解决方案:1)首先Player类需要实现Cloneable接口:public class Player implements Cloneable 

              2)需要在Player中重写Object的clone方法

                    public Object clone(){

                       Object obj = null;
                     try {
                     return super.clone();
                     } catch (CloneNotSupportedException e) {
                        e.printStackTrace();
                    }
                    return obj;
                 }

              3)在调用的地方:Player player = getPlayer(1110); Player temp = (Player)player.clone();

  • 相关阅读:
    MySQL事务_transaction
    mysql
    反射跳过泛型检查
    spring java.io.FileNotFoundException cannot be opened because it does not exist
    Servlet中ServletConfig的作用
    Exception in thread "main" java.lang.ClassCastException: java.base/java.util.HashMap$Values cannot be cast to java.base/java.util.ArrayList
    java中字符串和其他数据类型之间使用“+”号连接
    comboBox加载数据
    自动填充
    3号随笔,搭建web环境
  • 原文地址:https://www.cnblogs.com/xxyfhjl/p/4574057.html
Copyright © 2011-2022 走看看