1、Java中对象的存储方式
Java是一种面向对象的语言,所以对象的使用极为常见。与基本数据类型不同的是,对象是一种应用类型的数据,存储方式与基本数据类型有一些区别,如果不弄明白存储方式对程序的理解是会有出入的。
Java对象在内存中是以堆栈的方式存储的
eg:
新建一个对象
class Book {
//书名
String name;
}
//新建一个Book对象
Book b1 = new Book();
book.name = "十宗罪";
book在内存中的存储方式如下:
栈中存放的是对象名和对中Book对象的地址,而对象的内容则是存放在堆中,对象名通过地址来访问对中的对象。
Book b2 = b1;
如果进行这种复制操作,实际上是把b1所存放的地址复制给b2,此时b1与b2指向的是堆中同一块地址,如果对任何一个对象的属性进行更改,则b1与b2的属性值都会更改。
如果一开始b1和b2指向的是不同的内存地址,当进行上述操作后,b1和b2都指向了同一块地址,那么另一块地值就会被Java的GC就会自动回收垃圾内存。
2、 static关键字的说明
static关键字所修饰的属性或方法的创建时机与对象的创建没有关系,在它们所在的类被加载的时候他们就已经被创建了,而没有被static关键字修饰的属性和方法只有在对象创建的时候才会被创建,所以静态属性或方法创建时非静态的属性或方法可能还没有被创建,因此非静态的不能调用静态的。
而static所修饰的对象是放在一个方法区中
class Book {
String name;
//将出版商设置为静态,则所有创建的对象的pulisher属性都会是相同的
static String publisher = "WuHan";
}
Book b1 = new Book();
Book.name = "十宗罪";
Book b2 = new Book();
Book.name = "白夜行";
在内存中的存储方式是:
这样b1和b2就拥有了相同的出版社属性,所以如果多个相同类型的对象拥有一些相同的属性,可以把该属性设置为static这样就可以使得操作简洁。
3、异常处理中finally块中的语句执行情况
在使用try…catch处理异常时会使用到finally,而finally中的语句是必然执行的。但是在某些情况下也可能不会执行。
必然执行的情况
finally块在return返回语句执行之前执行。
public static void main(String[] args) {
haha();
System.out.println("程序执行完毕");
}
public static void haha() {
try {
System.out.println("1");
System.out.println("2");
System.out.println("3");
return;
}catch (Exception e) {
System.out.println("必须输入数字");
haha();
}finally {
System.out.println("必然执行!");
}
}
执行结果为:
1
2
3
必然执行
程序执行完毕
如果return语句中还存在函数调用并有return语句,则先执行return语句再执行finally。
public static void main(String[] args) {
text();
}
public static int text() {
try {
System.out.println("1");
return haha();
}catch (Exception e) {
}finally {
System.out.println("这个后执行");
}
return 1;
}
public static int haha() {
System.out.println("这个先输出");
return 1;
}
}
运行结果是:
1
这个先输出
这个后执行
还有就是与对象和变量有关的输出情况。
eg.
public static void main(String[] args) {
Person p = haha();
System.out.println(p.age);
}
public static Person haha() {
Person p = new Person();
try {
p.age = 18;
return p;
/*数据准备好之后复制一份,在准备的过程中执行finally块中的语句,因为P是引用类型,
复制的是地址,所以age可以修改*/
}catch (Exception e) {
return null;
}finally {
p.age = 28;
}
}
static class Person {
int age;
}
运行结果是:28
return语句返回前需要对返回对象进行复制,而对象是引用类型所以复制的对象的地址,在return返回前通过finally中的语句对对象的属性值进行改变但是地址没有改变,所以返回的是修改过后的属性值。
但是如果不是引用类型的数据,那么久不能被修改
public static void main(String[] args) {
System.out.println(haha());
}
public static int haha() {
int a = 10;
try {
return a;//a不是引用,而是一个新备份好的a值
}catch (Exception e) {
return 0;
}finally {
a = 18;
}
}
运行结果是:10
因为a不是引用类型,return返回时复制的是旧的值10,finally尽管在return语句前执行了,但是修改了变量a的值之后,复制的值已经不能再改变了。
不执行的情况
finally中的语句在这些情况下不执行:程序结束(内存中没有了,电脑断电了等情况),使用System.exit()语句时,finally中的语句不执行。
public static void main(String[] args) {
haha();
}
public static void haha() {
try {
int a = 10;
int b = 0;
System.out.println(a/b);
}catch (Exception e) {
//退出jvm,0表示正常退出,1,2,3表示非正常退出
System.out.println("出现异常");
System.exit(0);
}finally {
System.out.println("这里不会执行");
}
}
运行结果:出现异常
调用System.exit()时退出JVM,此时finally块不会被执行。