java内存基础(一)
关于Java 数组内存分配一点认识
数组引用变量不需要初始化,数组对象要进行初始化。
而且在堆内存当中的数组大小是不能改变的。
】
可能Java 数组大家都很熟悉,最近我遇到了一个关于Java 数组内存分配的问题。
呵呵。突然就发现许多书上“基本数据类型存储在栈内存当中,对象则保存在堆内存”这句话完全是错误的。下面是个简单的例子代码:

public class Test {
public static void main(String[] argv) {
// 静态初始化数组
String[] names = { "Michael", "Orson", "Andrew" };
// 动态初始化数组
String[] animal = new String[4];
// 让animal 指向 namens 数组所引用的数组
names = animal;
System.out.println(names.length);
System.out.println(animal.length);
}
}

“Java 数组大小是不能改变的”这可能大家都听过,那上面这段代码就有问题了,animal [] 长度为4,而names [] 数组的长度只有3,但是经过一个赋值语句,两个数组的大小就都变为4了。这不是改变了数组的大小吗? 问题就这样挡在面前了!好吧,问问技术前辈吧,就这样对数组的存储方式有了全新的认识。下面是我的一点理解:(如果有错误的,刚好被大神你看到了,也请你能够指出来。)
上面的的 names 和 animal 不代表这个数组对象,而仅仅是数组的变量而已,和C里面的指针是一样的,这样的变量叫做引用变量。数组对象是保存在堆内存当中,大小当然是不能改变的,但是数组变量却能够指向其他的数组对象,可以看看下面这个图:

蓝虚线是赋值语句 names = animal; 之前 names 和 animal 数组变量指向的堆内存当中数组对象;
红线是是赋值语句 names = animal;之后 names 和 animal 数组变量都同时指向一个数组对象。当然这时候 Java 垃圾回收机制这时候就会发现那个没人引用的数组对象然后把它带走。
从上面还可以看到,“Michael”,"Orson","Andrew" 这些都是基本的数据类型吧。但是他们却存储在堆内存当中。
实际上应该这样说:局部变量放在栈内存当中,(像上面的 names[],animal[] 这种引用类型的变量,还有一些基本类型的变量),但应用变量所引用的对象是保存是堆内存当中的。(包括数组还有一些我们平常写的普通的类对象)
Java在堆内存当中的对象通常是不允许直接访问的,但你可以想到直接访问的后果。为了访问堆内存当中的对象,这时候就需要引用变量这个中介。
什么时候Java存储在栈内存中的变量是仅仅是引用变量? 什么时候它又换了身份变为货真价实的JAVA对象纳?嗯,看看下面这个例子:

public class Animal {
private String name;
private int age;
Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void info() {
System.out.println(name + " " + age);
}
}
public class Test {
public static void main(String[] argv) {
// 动态初始化数组
Animal[] animal = new Animal[2];
Animal cat = new Animal("cat", 1);
Animal dog = new Animal("dog", 2);
animal[0] = dog;
animal[1] = cat;
// 当数组变量引用对象的方法(或者属性)的时候,它就变为实际的Java 对象
System.out.println(animal.length);
//dog 这个原本存储在栈内存当中的对象引用通过调用对象的方法变为实际的对象
dog.info();
animal[0].info();
}
}

只有当栈内存中的引用变量调用了对象的方法或者是指向了对象的属性的时候,它就从变量真正成了对象了。(比如上面例子中的 cat,dog 对象引用变量,animal[]数组变量)。
通过
animal[0] = dog;
animal[1] = cat; 使得两个变量都指向了存储在堆内存当中的对象,所以他们俩个打印出来的信息是一模一样的。上图中蓝线是赋值语句:
animal[0] = dog;
animal[1] = cat;
之前的变量指向的状态,红虚线是赋值语句之后的状态,animal[0]和dog ,animal[1] 和cat 所指向的都是相同的堆内存空间。 (PS:我还是要感谢这几个月来那几个面试官对我从头到尾的虐,虽然现在实习的事情还没有个准信,当我发现我要走的路还很长很长,上面这个问题的起因也是一个面试官的提问,“你知道Java 当中数组是怎样存储的吗?”)
java内存基础(一)的更多相关文章
- java基础知识(四)java内存机制
Java内存管理:深入Java内存区域 上面的文章对于java的内存管理机制讲的非常细致,在这里我们只是为了便于后面内容的理解,对java内存机制做一个简单的梳理. 程序计数器:当前线程所执行的字节码 ...
- java内存模型-基础
基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间 ...
- Jvm基础(2)-Java内存模型
Jvm基础(2)-Java内存模型 主内存和工作内存 Java内存模型包括主内存和工作内存两个部分:主内存用来存储线程之间的共享变量:而工作内存中存储每个线程的相关变量. 如下图所示: 需要注意的是: ...
- java基础(一):谈谈java内存管理与垃圾回收机制
看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...
- JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配
Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...
- Java内存模型基础
Java内存模型的基础 并发编程模型的两个关键问题 在并发编程种,需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在 ...
- 《成神之路-基础篇》JVM——Java内存模型(已完结)
Java内存模型 本文是<成神之路系列文章>的第一篇,主要是关于JVM的一些介绍. 持续更新中 Java内存模型 JVM内存结构 VS Java内存模型 VS Java对象模型(Holli ...
- 【java】java内存模型 (1)--基础
并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...
- Java基础学习总结(30)——Java 内存溢出问题总结
Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各 ...
随机推荐
- NumPy位操作
NumPy - 位操作 下面是 NumPy 包中可用的位操作函数. 序号 操作及描述 1. bitwise_and 对数组元素执行位与操作 2. bitwise_or 对数组元素执行位或操作 3. i ...
- 自己用java实现飞鸽传书 2 - 实现文件传输
第二步:实现文件传递. 上一步只是从服务端传递了一个字符串到客户端,这次需要对代码进行调整,实现从服务端获取文件,在客户端将文件存入目标地址. 调整后的代码: 服务端: import java.io. ...
- 全国城市部分js
var areaJson22 = { "id": "0", "name": "全国", "parentId&q ...
- git rm -r --cached 去掉已经托管在git上的文件
1.gitignore文件 在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改 .gitignore 文件的方法.这个文件每一行保存了一个匹配的规则例如: # 此为注释 – 将被 ...
- 完全卸载gitlab
完全卸载删除gitlab 2017年5月29日 wuhao 暂无评论 4,089次浏览 完全卸载删除gitlab 1.停止gitlab 1 gitlab-ctl stop 2.卸载gitlab ...
- mongodb停止遇到shutdownServer failed: unauthorized: this command must run from localhost when running db without auth解决方法
停止mongodb use admin db.shutdownServer(); mongos> db.shutdownServer(); assert failed : unexpected ...
- L126
Like so many things, it is not what's outside, but what is inside that counts. 许多事物都是如此,外表看起來虽不起眼,但是 ...
- 向重复劳动说不!——GMExplorer 1.0 Beta 发布
下载: GMExplorer 1.0 Beta 计算机网络诞生以来,各项技术日新月异.在浏览器器能做和看到的,早已不止网页了! 特别是近几年HTML5.云服务等技术的兴起,涌向大批优秀的Web应用.人 ...
- 【SQL查询】按照多个字段进行排序_order by
注: 1. 当前面的排序存在重复的项,后面的排序才会起作用. [示例1]:前面的排序不存在重复的项 [示例2]:前面的排序存在重复的项
- [置顶]
Kubernetes1.7新特性:新增自动伸缩条件和参数
一.核心概念 Horizontal Pod Autoscaling,简称HPA,是Kubernetes中实现POD水平自动伸缩的功能.云计算具有水平弹性的特性,这个是云计算区别于传统IT技术架构的主要 ...

上图中蓝线是赋值语句: