java-物件引用和物件本身
阿新 • • 發佈:2020-09-07
示意圖
應用場景
1.賦值
只有用新的物件本身直接賦值給對應引用,該物件引用的值會改變,因為物件引用指向的物件本身改變了。
2.方法入參
呼叫方法和被呼叫方法。
程式碼
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.如果是呼叫方法修改,應該通過返回值修改,而不是通過物件引用。