类、对象、引用与内存详解

对象

对象的创建

     Merchandise m1 = new Merchandise();
    // >> TODO 使用new操作符,可以创建一个类的实例/对象(instance/object)
    // >> TODO 使用new创建一个类的实例后,类中定义的每种变量会被赋予其类型的初始值

点操作符

点操作符是用来访问/操作前面实体的属性的

数据类型

是基本数据类型

在这里插入图片描述

引用数据类型

除了基本数据类型,其他都是引用数据类型,比如数组,对象等

Order oder = new Order();

order就是Order类的引用,只能指向Order类型的实例
引用数据类型变量包含两部分信息:类型和实例
每个引用都是指向某个类(class/自定义类型)的一个实例/对象(instance/object)。
引用的类型信息在创建时就已经确定。

引用数据类型和基本数据类型的区别

相同点

  • 都是用来创建变量,可以赋值和使用其值
  • 本身都是个地址
  • 基本数据类型占用的内存大小是固定的。引用类型(不是实例)占用的内存大小也是固定的,与JDK的版本有关系,64位的jdk占用的是8个byte ,32位占用的是4个byte
    不同点
  • 基本数据类型的值,就是地址对应的值,引用数据类型的值还是一个地址,需要通过 二级跳 来找到实例
  • 引用数据类型是java的一种内部类型,是对所有自定义类型和数组引用的统称,并非特指某种类型

类,对象和引用的关系

类和对象的关系
  • 类是对象的模板,对象是类的一个实例
  • 一个Java程序中类名相同的类只能有一个,也就是类型不会重名
  • 一个类可以有多个对象
  • 一个对象只能根据一个类来创建‘
引用和类以及对象的关系
  • 引用必须是,只能是一个类的引用
  • 引用只能指向其所属的类型的类的对象
  • 相同类型的引用之间可以赋值
  • 只能通过指向一个对象的引用,来操作一个对象,比如访问某个成员变量
引用的详解
    Merchandise m1;
    m1 = new Merchandise();
    Merchandise m5 = new Merchandise();
    // >> TODO 给一个引用赋值,则两者的类型必须一致 . m5可以给m1赋值 因为他们类型是一样的
    m1 = m5;
    // >> TODO 这块输出的内容是一样的,因为m1和m5都是指向同一个实例。但是m1的地址和m5的地址是不一样的,只是他们指向的实例是一样的
    System.out.println("m1=" + m1);
    System.out.println("m5=" + m5);
    // >> TODO System.out.println(对象名)  输出的是个string,就是这个应用调用toString方法返回的那个String,也就是利用这个对象名操作对象,调用其toString方法,然后把结果输出出来。当然,调用方法什么的,是在priinltn这个方法的代码里面完成的
引用到底占用多少内存
  • JVM规范没规定
    JVM规范从来没有规定每种数据类型占用多大的内存。他只是给出了每种数据类型的值域。既然规范没有说,那具体占用多少,还得看规范的实现
  • JDK实现:看位数
    引用类型作为一种非常特殊的类型,和内存寻址相关。所以JDK底层实现上一般会使用C/C++的poiter来封装成Java里面的引用。那么它占用的内存就是和JDK的位数有关系。如果是64位JDK,引用类型都是占用8个字节的内存。如果是32位的JDK,就占用4个字节。但是引用类型毕竟太多,而且绝大多数情况下用不了这么大的空间,太浪费。所以Oracle的JDK就针对这种情况,开发了一个压缩指针的功能,主要是针对Java内存堆小于32g的情况。这个JVM参数就是 -XX:+UseCompressedOops 下面是ORacle官方文档对这个参数的说明
Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.

对象的创建过程与内存详解

对象的创建

  • 使用new操作符可以创建某一个类的示例。
  • 在java程序运行的时候,所有创建出来的实例都被放在 堆(heap)内存中。而引用则是放在了栈内存中。
  • 对于栈内存来说,如果该数据是基本类型,那么栈里面存放的是这个基本类型的值;如果是引用类型,那么这块地址存放的是 堆这个实例中的地址

内存详解

java中内存主要分为内存堆,方法栈和方法区。

方法区

方法区是一块连续的内存,存放的是CLass文件加载到Java虚拟机内部之后的数据。
表现在代码中: 方法区的东西就是我们Class类的实例,包含类中变量的定义,静态变量的值和定义,方法(所有方法,不管静态还是非静态)的字节码等数据。 我们可以通过反射每个类的Class实例来获取这些数据。
所以每个方法区的数据是相对来说是静止的。因为类一旦加载进来,就不会变了,唯一会变的可能就是静态变量的值。
一个类无论创建多少个实例,他都不会增加方法区占用的内存。因为方法区就好比一个模板,不因为赋值出来多少实例而变大或者变小

内存堆(Heap)

内存堆与数据结构的堆没有任何关系。
创建对象的时候,对象实例存放到内存堆中。
具体的例如
比如 A a = new A();
new A() 生成一个A对象实例,然后把它存放到堆中( 对象A中的所有属性,都存放在堆中,如果是属性基本数据类型,直接存的是值,如果属性是引用数据类型,存放的是它的引用 ),然后把它存放堆中的具体的地址赋值给a;

涉及的知识点

一个对象占用的内存,是固定的

  • 数组
    每种数据类型的数据,占用的内存大小是固定的,数组的长度也是创建的时候确定的,所以一个数组占用的内存就是 (数据类型大小*数组长度) 。至于多维数组,多维数组里面除了最低的一个维,其余的都是引用,指向低一个维度的数组对象引用。所以无论多少维的数组,占用的内存都是一样
  • 普通的类的对象
    上面方法区讲解过,方法字节码的数据,静态数据,变量定义等数据都在方法区里,那么一个对象占用的额外的数据,其实也就是成员变量。一个类中有几个成员变量是固定 。如果一个类就一个long,一个int,一个String引用,一个类A的引用,那么一个类应该占用多少内存呢? long 8 + int 4+ 引用4 *2 = 20个字节。当然每个对象还有一些额外的内存占用,这个所有的对象都是一样的。 至于两个引用类型占用的内存,这块要理解,String和类A的引用,其实是个引用,而不是对象本身。比如说类A的引用这个成员变量,这个引用可以指向A类的示例,A类的实例占用多少内存,这与包含这个引用的对象没关系。当然A类的实例也可以是null,但是null也占内存(因为引用占用内存)。

方法栈

栈就是stack,是一种先进后出的数据结构。方法栈里面存放的是执行方法需要的内存和对象的引用。

涉及的知识点
  • 执行方法需要什么内存呢?
    解释 :参数和局部变量。 每次执行一个方法,都要为这个方法的执行创建其中定义的参数和局部变量
  • 每次执行一个方法,占用的内存都是一样的。
    解释:因为一个方法的参数和定义的局部变量的数量都是一样的。 可能有一个疑问,就是循环中定义的局部变量。 循环中定义的变量,其实是被重用 。一个for循环,定义了一个int变量,无论循环多少次,新的循环开始的时候,就可以重用之前定义的变量占用的内存,因为一个循环一旦结束,它占用的内存就没用了,可以被下次循环重新使用
    Stack的先进后出特性,和方法调用一样。比如m1方法调用m2方法,m2方法调用m3方法,过程是如下
  1. 先调用m1,根据m1的代码、确定m1执行的时候需要多少内存,在栈上分配相应大小的内存供m1执行使用,同时将分配的内存进栈
  2. 执行过程中调用m2,同样的过程,在栈上分配m2需要的内存,然后内存进栈
  3. 执行m2的时候,m2调用m3, 还是分配m3需要的内存,然后内存进栈
  4. m3执行完毕,释放m3占用的内存(内存出栈),然后m2继续执行,执行完毕内存释放,最后是m1继续执行,执行完毕内存释放
    如何访问栈上内存?
    因为每个方法执行需要的内存是固定的,那么在分配的这一截内存上,每个变量的地址都是固定的。正所谓冥冥之中自有定数,正是此意。所以这个和堆上面的内存是不一样的。堆上的内存需要根据引用,找到堆上面的对象,然后每个成员变量对应的内存地址,也都是冥冥中自有定数。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值