1. 程式人生 > 程式設計 >淺析Java 物件引用和物件本身

淺析Java 物件引用和物件本身

示意圖

淺析Java 物件引用和物件本身

應用場景

1.賦值

2.方法入參

3.呼叫方法和被呼叫方法

程式碼

import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author gzh
 * @createTime 2020/8/25 8:41 AM
 */
public class Test {
 private static final Logger log = LoggerFactory.getLogger(Test.class);

 public static void main(String[] args) {
  //
  List<User> userList = new ArrayList<User>();
  User user1 = new User();
  user1.setName("gzh1");
  userList.add(user1);

  User user2 = new User();
  user2.setName("gzh2");
  userList.add(user2);

  log.info(JSONObject.toJSONString(userList));

  //
//  for (User user: userList) { //這裡的list元素最終是舊值,因為沒有被新的物件本身直接賦值
//   log.info(JSONObject.toJSONString(user));
//   User user3 = new User();
//   user3.setName("gzh3");
//
//   user = user3;
//   log.info(JSONObject.toJSONString(user));
//  }

//  for (int i = 0; i < userList.size(); i++) { //這裡的list元素最終是新值,因為被新的物件本身直接賦值
//   //
//   User user = userList.get(i);
//
//   //
//   log.info(JSONObject.toJSONString(user));
//   User user3 = new User();
//   user3.setName("gzh3");
//   user = user3;
//
//   //
//   log.info(JSONObject.toJSONString(user));
//   userList.set(i,user);
//  }

  for (int i = 0; i < userList.size(); i++) { //同上:這裡的list元素最終是新值,因為被新的物件本身直接賦值
   //
   log.info(JSONObject.toJSONString(userList.get(i)));

   //
   User user3 = new User();
   user3.setName("gzh3");

   //
   userList.set(i,user3);
   log.info(JSONObject.toJSONString(userList.get(i)));
  }

  //
  log.info(JSONObject.toJSONString(userList));
 }
}

執行結果

19:49:39.062 [main] INFO Test - [{"name":"gzh1"},{"name":"gzh2"}]
19:49:39.064 [main] INFO Test - {"name":"gzh1"}
19:49:39.065 [main] INFO Test - {"name":"gzh3"} //因為list的元素被新的物件本身直接賦值,所以值改變了
19:49:39.065 [main] INFO Test - {"name":"gzh2"}
19:49:39.065 [main] INFO Test - {"name":"gzh3"} //同上
19:49:39.065 [main] INFO Test - [{"name":"gzh3"},{"name":"gzh3"}] //同上

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author gzh
 * @createTime 2020/8/25 8:41 AM
 */
public class Test2 {
 private static final Logger log = LoggerFactory.getLogger(Test2.class);

 public static void main(String[] args) {
  User user = new User();
  user.setName("gzh1");

  log.info("呼叫方法之前:{}",JSONObject.toJSONString(user));
  updateUser2(user);
  log.info("呼叫方法之後:{}",JSONObject.toJSONString(user));
 }

 private static void updateUser(User user) {
  //
  log.info(JSONObject.toJSONString(user));

  //
  User user2 = new User();
  user2.setName("gzh2");

  user = user2;

  //
  log.info(JSONObject.toJSONString(user));
 }

 private static void updateUser2(User user) {
  //
  log.info(JSONObject.toJSONString(user));

  user.setName("gzh2");

  //
  log.info(JSONObject.toJSONString(user));
 }
}

執行結果

19:50:35.072 [main] INFO Test2 - 呼叫方法之前:{"name":"gzh1"}
19:50:35.077 [main] INFO Test2 - {"name":"gzh1"}
19:50:35.077 [main] INFO Test2 - {"name":"gzh2"}
19:50:35.077 [main] INFO Test2 - 呼叫方法之後:{"name":"gzh2"} //因為入參仍然指向同一個物件本身,並沒有被新的物件本身重新賦值,所以入參的值(即物件本身)改變之後,入參的原始物件引用的值(即物件本身)也改變了。

總結

1.不同的物件引用,存放在不同的記憶體地址,而該記憶體地址儲存的值又是物件本身的記憶體地址,物件引用正是通過物件本身的記憶體地址指向物件本身。

2.物件引用的值(即指向的物件本身)什麼時候會被改變?什麼時候不會被改變?

只有直接賦值了新的物件本身,對應引用的值才會改變。

不同的物件引用沒有關係,1)如果被同一個物件本身賦值,那麼兩個物件引用都指向同一個物件本身,除此之外,就沒有其他的關係,不同的物件引用是互相獨立的,且他們之間沒有任何關係2)如果一個物件引用被新的物件本身賦值,另一個物件引用仍然是指向舊的物件本身,所以再次證明兩個物件引用之間是沒有任何關係的,兩個物件本身之間也是沒有任何關係的。

3.如果改的是同一個物件本身,那麼物件引用1和物件引用2的值同時改變。

4.如果物件引用2是指向了新的物件,那麼物件引用2的值改變,物件引用1的值不變。

最佳實踐

1.如果想要改變引用的值,應該直接賦值,而不是間接通過其他物件引用來改變。

2.如果是呼叫方法修改,應該通過返回值修改,而不是通過物件引用。

以上就是淺析Java 物件引用和物件本身的詳細內容,更多關於Java 物件引用的資料請關注我們其它相關文章!