.堆内存:保存对象真正的数据,就是每一个对象的属性内容如cat对象的颜色color,age属性的具体数值;
.栈内存:保存的是一块堆内存的空间地址,简易理解为对象的名称如Cat cat中的cat(对象名称);
联系与区别:一块堆内存可以被多个栈内存所指向,但反之,一块栈内存只能保存一块堆内存的地址;
.数组
package org.java.array;
/**
* 数组的引用传递
*
* @author coder
*
*/
public class ArrayDemo {
public static void main(String[] args) {
int data[] = new int[3];// 声明并开辟一个3个长度的数组
data[0] = 10;
data[1] = 20;
data[2] = 30;
int temp[] = data;//数组传递引用,新开辟的temp栈内存也指向data所指向的堆内存
temp[0] = 99;
System.out.println("输出1:");
for (int arr : temp) {
System.out.print(arr+" ");
}
System.out.println();
/**
* 数组的静态初始化:
*
*/
int data2[]=new int[]{1,2,3,4,5,6};
System.out.println("输出2:");
for(int i=0;i<data2.length;i++)
{
System.out.print(data2[i]+" ");
}
System.out.println();
/**
* 数组与方法参数的传递 实质就是数组的引用传递
*/
int data3[]=new int[]{6,7,8};
change(data3);//引用传递等价于:int temp[]=data3;
System.out.println("输出3:");
for(int i=0;i<data3.length;i++)
{
System.out.print(data3[i]+" ");
}
System.out.println();
/**
* 简化理解
*/
int data4[]=new int[]{1,2,3};
int temp2[]=data4;//
System.out.println("输出4:");
for(int x=0;x<temp2.length;x++){
temp2[x]*=2;
System.out.print(temp2[x]+" ");
}
//上述代码主要用于对比数组的方法参数传递的简化理解
}
/*数组与方法传递的main方法之外的方法测试*/
public static void change(int temp[]){
for(int j=0;j<temp.length;j++){
temp[j]*=2;
}
}
}
运行结果:
输出1:
99 20 30
输出2:
1 2 3 4 5 6
输出3:
12 14 16
输出4:
2 4 6
.数组的复制:可以用System.arraycopy(原数组名,原数组复制开始索引,目标数组名,目标数组开始索引,长度)方法实现数组复制。
常用方法:利用java.util.Arrays.sort(数组名)实现数组排序。
.对象数组的动态初始化与静态初始化与数组的格式基本类似:
动态初始化:类名 对象数组名[]=new 类名[长度] eg: Book books[]=new Book[3];
静态初始化:类名 对象数组名[]=new 类名[]{实例化对象,实例化对象} eg: Book books[]=new Book[]{
new Book(1),new Book(2)};
String类的相关知识:
1.String类的两种实例化方式
.直接赋值 String str="Java";这种方式赋值在相同内容的情况下不会开辟新的堆内存空间,而是指向已有的堆内存空间
.利用构造方法实例化 String str=new String("Java");会开辟的新的堆内存空间,由于每一个字符串都是一个String类匿名对象,所以这种方式首先会在堆内中开辟一块空间用来保存Java,然后使用关键字new,开辟另一块内存空间。因此真正使用的是new开辟的堆内存,之前的堆空间没有任何占内存的指向,将成为垃圾杯GC回收
Java中只要是引用数据类型一定存在内存地址,“==”可用于引用数据类型的比较,但比较的是地址的数值内容,而equals方法是由String类提供的一个方法,此方法专门负责进行字符串内容的比较
.字符串常量就是String类的匿名对象(匿名对象,开辟了堆内存的实例对象,只能使用一次,使用一次就被GC收回)
.任何数据类遇见String类型都向String转换
.String定义的字符串一旦定义就不可改变,在修改String定义的字符串对象时,实际修改的是String类对象的 引用关系,而原始的字符串没有发生变化,但是原来的字符串对象不被任何栈内存所指向,会产生垃圾,因此在需要频繁修改字符您串内容的项目中一般不采用String去定义字符串,一般采用StringBuffer或者StringBuilder.
执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
.String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
. 总结一下
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况