基于Java 数组内存分配的相关问题

VLV素颜神膜

VLV素颜神膜

2016-02-19 09:41

每个人都希望每天都是开心的,不要因为一些琐事扰乱了心情还,闲暇的时间怎么打发,关注图老师可以让你学习更多的好东西,下面为大家推荐基于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里面的指针是一样的,这样的变量叫做引用变量。数组对象是保存在堆内存当中,大小当然是不能改变的,但是数组变量却能够指向其他的数组对象,可以看看下面这个图:

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)蓝虚线是赋值语句 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 所指向的都是相同的堆内存空间。
展开更多 50%)
分享

猜你喜欢

基于Java 数组内存分配的相关问题

编程语言 网络编程
基于Java 数组内存分配的相关问题

Java内存泄露问题分析

Java JAVA基础
Java内存泄露问题分析

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

VC中结构体内存分配问题透析

编程语言 网络编程
VC中结构体内存分配问题透析

基于Java内存溢出的解决方法详解

编程语言 网络编程
基于Java内存溢出的解决方法详解

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

解析C语言中位字段内存分配的问题

编程语言 网络编程
解析C语言中位字段内存分配的问题

C语言中多维数组的内存分配和释放(malloc与free)的方法

编程语言 网络编程
C语言中多维数组的内存分配和释放(malloc与free)的方法

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

scanfrm.exe进程是什么?

scanfrm.exe进程是什么?

服务器端C#实现的CSS解析器

服务器端C#实现的CSS解析器
下拉加载更多内容 ↓