1、Java中对象的存储方式

Java是一种面向对象的语言,所以对象的使用极为常见。与基本数据类型不同的是,对象是一种应用类型的数据,存储方式与基本数据类型有一些区别,如果不弄明白存储方式对程序的理解是会有出入的。

Java对象在内存中是以堆栈的方式存储的

eg:
新建一个对象

class Book {
	//书名
	String name;
}
//新建一个Book对象
Book b1 = new Book();
book.name = "十宗罪";

book在内存中的存储方式如下:

java如何将值存储 java存储数据的方法_System

栈中存放的是对象名和对中Book对象的地址,而对象的内容则是存放在堆中,对象名通过地址来访问对中的对象。

Book b2 = b1;

如果进行这种复制操作,实际上是把b1所存放的地址复制给b2,此时b1与b2指向的是堆中同一块地址,如果对任何一个对象的属性进行更改,则b1与b2的属性值都会更改。

java如何将值存储 java存储数据的方法_Java_02

如果一开始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 = "白夜行";

在内存中的存储方式是:

java如何将值存储 java存储数据的方法_Java_03

这样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中的语句对对象的属性值进行改变但是地址没有改变,所以返回的是修改过后的属性值。

java如何将值存储 java存储数据的方法_java_04

但是如果不是引用类型的数据,那么久不能被修改

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块不会被执行。