java透过内存看数据类型

-

Java数据类型

  • 基本数据类型

    • char
    • int
    • short
    • long
    • byte
    • float
    • double
    • boolean
      基本数据开辟空间在正常情况下都是在创建在栈内,并且基本数据类型有有一个特点,比如

      1
      2
      int a=1;
      int b=1;

      a和b引用的其实是同一块内存,值为1的内存,当在创建一个int c=1,c也会指向同一块内存,当
      a=2时,将会在java内存重新开辟一块值为2的内存,记住基本类型内存时开辟在Java的栈中的,
      栈不止有方法的栈入栈出,还会包含基本类型的数值。

  • 引用数据类型

    • class
    • interface
    • 数组
      引用数据类型和基本数据类型就完全不一样,引用类型会在栈创建一个指针,当数据实例化后就会在堆内存中创建一块内存,供创建的实例使用,栈内指针指向堆内对象,这里有一个注意点,就是Java中有一个Class对象,这个对象和class实例出来的对象不一样,一般Java在调用class对象中的静态方法或者静态值(其实实例化就是调用了静态方法)后,会先创建一个Class对象在运行时常量池中,大家都知道,常量池中存储的都是一些字符信息,这个Class对象就是按照这些来创建的,当你new一个对象后,你调用的方法入口都只有一个就是Class对象的描述的方法地址入口,不会改变,也就是说,你同一class对象类型的方法入口只有一个,java中的反射机制也是通过Class对象来实现的,所以我们总是会说,Java中的”==”,比较的是地址,其实比较的就是一块栈内的指针地址,所以我们就能够理解基本类型的比较为什么比较的值了有看过String源码的人会发现String中的equals其实是把字符一个一个拿出来比的,也就是变成基本类型char,基本类型的数组也是一样。

    Java的关键字

    • final

      • 这个关键字,就是在开始的时候就把这个字存储在了常量池中,并且不可改变,所以是一个常量,其实在Java中,当方法添加这个关键字后,java就会将这个方法优化,在编译时,将此方法内嵌到调用了此方法中的方法中,比如

        1
        2
        3
        4
        5
        6
        7
        8
        final fun(int a){
        System.out.println(a);
        }
        f(){
        int a=1;
        fun(a);
        int b=2;
        }

        变成

        1
        2
        3
        4
        5
        f(){
        int a=1;
        System.out.println(a);
        int b=2;
        }

        这是Java中的一个优化,叫内嵌调用,记住当数据添加了final关键字后就会直接放在常量池,并且初始化。这里还有一点一个class对象中的基本数据都会被初始化,而方法中的不会,方法中的数据会在运行时,在运行时常量池中进行初始化,并且使用。

    • static
      • 上面提到Class对象,其实这个值就会被放在此对象中,因为在Java中,无论你实现多少个同一类型对象,都只会对应一个Class对象,Class对象存在于运行常量池中,所以此值也就是在运行常量池中。
        常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References),运行时常量池用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

如上面有错误,望不吝指出,正在学习ing,害怕理解出错。