Java进基础阶-4-对象内存、存活、回收+构造函数

目录

1、Java内存分配

2、方法栈

3、一个对象的内存

4、构造函数

4.1、继承与构造函数

4.2、如果我们没调用super()函数会怎样?

4.3、this()函数

5、对象的存活

6、释放对象的3种方式


1、Java内存分配

栈: 局部变量中的基本数据类型直接存入栈中

        局部变量中对对象的引用(指针)存在栈中

堆: 成员变量全部存在堆中(包括:基本数据类型、对象引用和对象引用的实例)

      【成员变量属于类,类最终都是要被new 出来的,所以成员变量全部存储在堆中】

public class Test_Subject {

    //成员变量
    private String  hello;  //存储于堆中
    
    //成员变量
    private Person  per=new Person();   //per是对Person对象的引用,存储于堆中,new出来的Person对象也存储于堆中
    
    class  Person{
        //实例变量
        String name;  //name存储在Person对象所属的堆空间中
    }
    
    public void showAge(int a){   //参数a也是局部变量 存储于栈中

        //局部变量
        int age=23;               //age存储在栈中
        //p也是局部变量
        Person p=new Person();    //p存储在栈, new Person()这个对象存储在堆中
    }
}

2、方法栈

存放方法的栈中保存了方法的状态,包括执行到了那一行代码,还有所有的局部变量。

下面是各个方法互相调用时,它们存放于栈中的状态。(正在执行的方法都会被放在栈顶。)

3、一个对象的内存

一个对象的内存=所有实例变量使用的内存+对象本身的开销(一般是16字节)

对象本身的开销=一个指向对象类的引用+垃圾回收信息+同步信息

另外一般内存的使用都会被填充为8字节(64位计算机中的机器字)的倍数。不够8的倍数,填充为8的倍数。

      Integer对象内存(24字节)= 对象开销(16字节)+int(4字节)+填充字节(4字节)

      Date对象内存(32字节)=对象开销(16字节)+3*int(12字节)+填充字节(4字节)

     Counter对象内存(32字节)=对象开销(16)+String(8)+int(4)+填充字节(4)、

     Node内存(40)=对象开销(16)+额外开销(8)+Item的引用(8)+Node的引用(8) 

因为Node是一个非静态的内部类,所以它持有对外部类的引用,额外开销就是来之于对外部类的引用。

对对象的引用,其实就是一个机器地址,一个机器地址所需内存一般是8字节(64位架构的计算机,32为架构的是4字节)

4、构造函数

  1. 构造函数会在new的时候被调用,它快于赋值给引用它的变量的赋值过程。
  2. 构造函数不会有返回类型。
  3. 构造函数不会被继承。
  4. 构造函数只有在你没有写任何构造函数的时候,才会给你创建一个没有参数的构造函数。
  5. 如果你写了有参数的构造函数,如果你还想要有一个没有参数的构造函数,就必须自己写出来,编译器不会给你创建。

4.1、继承与构造函数

  • 一个子类占用的内存大小除了自身的对象开销+所有实例变量的大小以外,还要加上父类的内存。
  • 当你在new一个子类的时候,第一件事会调用父类的构造函数,而且一定会调用(因为完整的对象也需要完整的父类,你想要调用父类的所有方法和状态,就必须构造父类)。
  • 在构造函数中,通过super()函数来调用父类的构造函数。
  • 抽象的类也有构造函数,虽然你不能new一个抽象类,但是当你在new它的子类的时候会调用抽象类的构造函数。

4.2、如果我们没调用super()函数会怎样?

编译器会帮我们加上super()的调用。添加的方式会有两种:

1、如果你没有写构造函数,它会默认会给你添加一个无参的构造函数,并添加上super()函数。

2、如果你有构造函数,那么它会对每个重载版本的构造函数上添加上super()函数。

注意:编译器添加的一定是没有参数的构造函数和super()函数,假如父类有多个版本的构造函数,那么只有无参的版本会被调用。

对于super()的调用必须是构造函数的第一条语句。

public class Test_Constructor {

    static class Animal{
        public String name;
        public final int age=1;
        public Animal() {
            System.out.println("你好");
        }
    }

    static class  Dog extends Animal{
        public Dog() {
            System.out.println("汪汪");
        }
        public Dog(String name) {
            System.out.println("汪汪");
        }
    }

    public static void main(String[] args) {
        Dog a=new Dog();
        Dog b=new Dog("小花");
    }
}

//输出结果
你好
汪汪
你好
汪汪

4.3、this()函数

  • this()函数是从某个构造函数调用同一个类的另外一个构造函数,只需要改变this()的参数就可以调用;
  • this()函数只能在构造函数中,且只能是第一条语句;
  • super()与this()不能兼得,只能出现一个。

5、对象的存活

public class Test_Object {

    static class Person {
        String name; // 实例变量的寿命与Person对象相同,如果该对象存活,该变量也会存活
    }

    public void showAge(int a) {
        int age = 23; // 局部变量只会存活在该方法调用的时候,当该方法执行完毕,那么该变量消失
        showName();
    }
    /**
     * 1、当showAge方法在调用ShowName方法的时候,showAge方法以及它的变量age都是存活的,只是不处于栈顶;
     * 2、这个时候的age变量是无法被使用的,只有在栈顶的showName函数中的name变量可以被使用;
     * 3、当这两个函数都执行完成之后,showAge函数和它的变量才会消失。
     */
    public void showName() {
        String name = "zhangSan";
        System.out.println("name");
    }

    public static void main(String[] args) {
        /**
         *  Perosn对象的生命周期取决于它的引用变量p,只要p一直引用着Person对象,那么该对象就会一直存活。
         */
        Person p=new Person(); 
    }
}

6、释放对象的3种方式

public class Test_Clear_Object {

    class Person {
        String name;
    }

    /**
     * 方式一:将对象的引用变量放在方法中,这样在方法执行完成之后,p1引用变量就会消失,
     *        这样对Person对象的引用就没有了,该对象就可以被GC回收了。
     */
    public void clear1(){
        Person p1=new Person();
    }

    /**
     * 方式二:引用被赋值到其他对象上,这样new的第一个Person对象就没有了引用,可以被回收。
     */
    public void clear2(){
        Person p2=new Person();
        p2=new Person();
    }
    /**
     * 方式三:直接将引用置空,这样Person对象就没被引用了。
     */
    public void clear3(){
        Person p3=new Person();
        p3=null;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值