- 栈:存放8种基本数据类型的变量和对象的引用(对象的引用保存的只是对象本身的地址),对象本身不存放在栈中,而是存放在堆和常量池中。
- 堆:存放所有new出来的对象或数组。JVM不定时查看堆中的对象,如果没有引用指向这个对象就回收。
- 常量池:存放字符串常量和基本类型常量(public static final)
public static final 定义的变量是用来干什么的?
-
static是为了让其成为类的成员,而不是对象的成员,这样用起来就方便了
-
public是为了方便访问
-
final则是表明这是个常量,不能修改
-
private的对象,然后定义get、set是为了访问控制,是一种常规的封装
-
综上,
public static final
可以让访问变得很方便,而且不会被修改。一般可以放配置信息,还有一些状态码的定义。
其他的补充:
-
static修饰的对象是放在引用的根下的,意味着几乎不会被回收
只需说明java都是“值传递”即可,关键看这个值是什么,简单变量就是复制了具体值,引用变量就是复制了地址呗。字符串是不可变的,当然不会被修改.
传值的方式传引用。 或者说传值的方式传地址。
Java中只有值传递,参数类型是引用类型时,传递是引用类型的副本。
关于值传递和引用传递 参考:https://www.zhihu.com/question/31203609
str += "123" 实际上是 str = str + "123", 实际上是 str 指向一个新生成的字符串对象。而原来的字符串并没有改变。
赋值运算符只能让引用指向一个新的对象,而不会改变对象本身。
而如果String有能改变自身的方法的话(类似于setName这种的),那么你也可以看到String对象的改变,但是String对象的所有方法,都是不改变对象本身的。
substring(1)这种方法,也是返回一个新的String对象。
Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。
无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递(call by sharing)。其实Java中的参数传递严格意义上说应该是按共享传递。
按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值)。在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作。如果该值在栈中,那么因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响。如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作。因为传递的是地址的拷贝所以函数内对值的操作对外部变量是可见的。
简单点说,Java中的传递,是值传递,而这个值,实际上是对象的引用。
而按共享传递其实只是按值传递的一个特例罢了。所以我们可以说Java的传递是按共享传递,或者说Java中的传递是值传递。
一、基本数据类型
8种基本数据类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。
以int为例:
int m1 = 7;
int m2 = 7;
public static final int m3 = 7;
public static final int m4 = 7;
二、数组,字符串和其他引用类型
下面的例子对于数组,字符串和其他引用类型都是一样的,只是用字符串举例。
以String为例:
对于字符串:其对象的引用都是存储在栈中,对象本身如果是编译期已经创建好(直接用双引号赋值的:String s1 = “mistra1”; )的就存储在常量池中,如果是运行期(new出来的)就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
String m1 = "mistra";
String m2 = "mistra";
String m3 = new String("mistra");
String m4 = new String("mistra");
---------------------
基本数据类型跟堆没有任何关系。
三、什么是自动装箱拆箱
很简单,下面两句代码就可以看到装箱和拆箱过程
1 //自动装箱
2 Integer total = 99;
3 //自动拆箱
4 int totalprim = total;
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
上面我们看到在Integer的构造函数中,它分两种情况:
1、i >= 128 || i < -128 =====> new Integer(i)
2、i < 128 && i >= -128 =====> SMALL_VALUES[i + 128]
i >= 128 || i < -128是会创建不同的对象,在i < 128 && i >= -128会根据i的值返回已经创建好的指定的对象。
先来一段代码:
public class Topic1 {
/*
引用的问题
*/
public static void main(String[] args) {
//变量值 引用 常量池
System.out.println("---------Integer/Long---------");
Integer int1=60;
Integer int2=60;
System.out.println(int1==int2);
Integer int3=128;
Integer int4=128;
System.out.println(int3==int4);//比较两个对象的引用是否相等
System.out.println(int2==60);
System.out.println(int3.equals(int4));//比较这两个对象的属性值是否相同
System.out.println("-----------String------------");
String str1 = "111";
String str2 = "111";
System.out.println(str1==str2);
String str3=new String("111");
String str4=new String("111");
System.out.println(str1==str4);
System.out.println(str3==str4);
System.out.println(str1==str4.intern());
}
}
输出结果为:true
false
true
true
-----------String------------
true
false
false
true
java只有值传递,引用类型传递的是引用指向的地址,也是值
参考:Java 堆、栈、常量池和值传递、引用传递详解
https://blog.csdn.net/axela30w/article/details/79167361
详解Java的自动装箱与拆箱(Autoboxing and unboxing)
https://www.cnblogs.com/wang-yaz/p/8516151.html