从数组来看值传递和引用传递

惯例先看一段代码

public class DemoCollection14 {
public static void main(String[] args) { String [] strs = {"zs", "ls", "wu"}; for (String str : strs) {
strs[0] = null;
System.out.println(str);
} for (String str : strs) { System.out.println(str);
}
}
} //输出:
// zs
// ls
// wu
//
// null
// ls
// wu
要想搞懂这道题,先看下面讲解

重新学习数组(此处引用了廖雪峰老师的讲解)

基本类型数组

数组是引用类型,并且数组大小不可变

public class Main {
public static void main(String[] args) {
// 5位同学的成绩:
int[] ns;
ns = new int[] { 68, 79, 91, 85, 62 };
System.out.println(ns.length); // 5
ns = new int[] { 1, 2, 3 };
System.out.println(ns.length); // 3
}
}

数组大小变了吗?看上去好像是变了,但其实根本没变。

对于数组ns来说,执行ns = new int[] { 68, 79, 91, 85, 62 };时,它指向一个5个元素的数组:

     ns


┌───┬───┬───┬───┬───┬───┬───┐
│ │68 │79 │91 │85 │62 │ │
└───┴───┴───┴───┴───┴───┴───┘

执行ns = new int[] { 1, 2, 3 };时,它指向一个新的3个元素的数组:

     ns ──────────────────────┐


┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ │68 │79 │91 │85 │62 │ │ 1 │ 2 │ 3 │ │
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

但是,原有的5个元素的数组并没有改变,只是无法通过变量ns引用到它们而已。

字符串数组

如果数组元素不是基本类型,而是一个引用类型,那么,修改数组元素会有哪些不同?

字符串是引用类型,因此我们先定义一个字符串数组:

String[] names = {
"ABC", "XYZ", "zoo"
};

对于String[]类型的数组变量names,它实际上包含3个元素,但每个元素都指向某个字符串对象:

          ┌─────────────────────────┐
names │ ┌─────────────────────┼───────────┐
│ │ │ │ │
▼ │ │ ▼ ▼
┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┐
│ │░░░│░░░│░░░│ │ "ABC" │ │ "XYZ" │ │ "zoo" │ │
└───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┘
│ ▲
└─────────────────┘

names[1]进行赋值,例如names[1] = "cat";,效果如下:

          ┌─────────────────────────────────────────────────┐
names │ ┌─────────────────────────────────┐ │
│ │ │ │ │
▼ │ │ ▼ ▼
┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┬───────┬───┐
│ │░░░│░░░│░░░│ │ "ABC" │ │ "XYZ" │ │ "zoo" │ │ "cat" │ │
└───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┴───────┴───┘
│ ▲
└─────────────────┘

这里注意到原来names[1]指向的字符串"XYZ"并没有改变,仅仅是将names[1]的引用从指向"XYZ"改成了指向"cat",其结果是字符串"XYZ"再也无法通过names[1]访问到了。

对“指向”有了更深入的理解后,试解释如下代码:

public class Main {
public static void main(String[] args) {
String[] names = {"ABC", "XYZ", "zoo"};
String s = names[1];
names[1] = "cat";
System.out.println(s); // s是"XYZ"还是"cat"?
}
} //输出"XYZ" //解释原因:
//names字符串数组创建好后,s指向names[1]这个位置。
//但是呢,name[1]可不是把原数据XYZ更改为了cat,而是重新指向了存有cat的那个空间地址。
//故s还是指向原来那个位置,故输出的是XYZ

再回到开始的那个问题:

public class DemoCollection14 {
public static void main(String[] args) { String [] strs = {"zs", "ls", "wu"}; for (String str : strs) {
strs[0] = null;
System.out.println(str);
} for (String str : strs) { System.out.println(str);
}
}
} //输出:
// zs
// ls
// wu
//
// null
// ls
// wu foreach,其实就是迭代器。迭代器,不是传统意义的for循环输出数组数据。
而是定义了String str,依次str=strs[i],并输出str。故和前面的xyz,性质一样了。

Java 从数组来看值传递和引用传递的更多相关文章

  1. 堆栈详解 + 彻底理解Java的值传递和引用传递

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

  2. Java的值传递和引用传递的说法

    学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java ...

  3. 多图证明,Java到底是值传递还是引用传递?

    开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见正文. 说到值传递和引用传递我们不得不提到两个概念:值类型和引用类型. 1.值类型 通俗意义上来说,所谓的值类型指的就 ...

  4. Java的参数传递是值传递还是引用传递?

    一.前言 首先先说结论,Java中方法参数传递方式是按值传递.如果参数是基本类型,传递的是基本类型的字面量值的拷贝.如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝. 接下来深入了解一 ...

  5. Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义

    一.Java中什么叫做引用类型变量?引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...

  6. java的值传递和引用传递

    昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...

  7. 理解java值传递与引用传递

    1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变 ...

  8. Java是值传递还是引用传递?

    Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...

  9. java中的值传递和引用传递有什么区别呀?

    值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...

随机推荐

  1. Kotlin 简单使用手册

    在昨天和做android的前辈一番交谈后,觉得很惭愧,许多东西还只是知其然而不知其所以然,也深感自己的技术还太浅薄.以后要更加努力地学习,要着重学习原理.方法论,不能只停留在会用的阶段. 今天又要献丑 ...

  2. 【代码周边】Idea设置类注解和方法注解(带图)

    Idea版本: 类注解 打开setting→Editor→Code Style→File and Code Templates /** * Created with IntelliJ IDEA. * ...

  3. 华为存储18500 V5配置SNMP

    配置流程 配置SNMPV1/V2C 配置端口 admin:/>show snmp port SNMP Listening Port : 161 admin:/>change snmp po ...

  4. docker容器中布置静态网站

    docker容器中布置静态网站(基于云服务器ubuntu系统) 服务器准备(ubuntu) docker nginx 静态网页制作 浏览器测试 服务器布置 这里推荐使用云服务器(阿里云.华为云.腾讯云 ...

  5. JUC包-原子类(AtomicInteger为例)

    目录 JUC包-原子类 为什么需要JUC包中的原子类 原子类原理(AtomicInteger为例) volatile CAS CAS的缺点 ABA问题 什么是ABA问题 ABA问题的解决办法 JUC包 ...

  6. Kafka知识总结及面试题

    目录 概念 Kafka基础概念 命令行 Kafka 数据存储设计 kafka在zookeeper中存储结构 生产者 生产者设计 消费者 消费者设计 面试题 kafka设计 请说明什么是Apache K ...

  7. 一、linux安装mysql

    一.下载mysql免编译包: wget http://cdn.mysql.com/archives/mysql-5.6/mysql-5.6.33-linux-glibc2.5-x86_64.tar.g ...

  8. 【函数分享】每日PHP函数分享(2021-1-8)

    explode() 使用一个字符串分割另一个字符串. array explode( string $delimiter , string $string [, int $limit ]) 参数描述de ...

  9. 【Linux】ssh远程连接到指定ip的指定用户上

    通过ssh可以远程连接到其他的机器上,但是如果只想连接到指定的用户的话 需要这样做: -l 选项 (是L不是I,小写) ssh IP -l 用户名 这里的ip如果在hosts下就可以直接输入域名或者主 ...

  10. 【葵花宝典】kolla部署OpenStack-AllinOne

    1.关闭防火墙以及内核安全机制 systemctl stop firewalld systemctl disable firewalld ##永久性关闭 setenforce 0 sed -i 's/ ...