8.Java内存分配和static关键字

Java内存分配

1.内存区域

栈内存 stack
作用 : 展示程序的执行流程的 (进栈出栈) / 给方法的执行提供空间
特点 :

  1. 先进后出 -> 弹夹
  2. 栈内存中的数据使用完毕立刻回收
  3. 在方法内有局部变量,方法又在栈内存中,所以局部变量在栈里


堆内存 heap / memory
作用 : 存 new 出来的东西 -> 对象
特点 :

  1. 存对象
  2. 只要在堆中开辟空间那么堆内存会给这个空间一个唯一的地址值
  3. 对象内部空间的数据都是有默认值(数组,对象的属性)
    整数 : 0 浮点数 : 0.0 字符 : ‘\u0000’ 布尔 : false 所有引用数据类型 : null
  4. 堆中数据使用完毕后不是立即回收,等到垃圾回收机制(gc)空闲的时候回收
    //空闲时机 : 无法预见(时间一定不会很长)


方法区
作用: 存放字节码对象 (.class 文件生成的对象) -> 通过类加载器(classloader)完成字节码文件到字节码对象的转换
 //字节码对象中有啥 ? 类的目录/模板(成员变量,成员方法)
作用: 常量池 -> 存放程序执行过程中使用的常量值 //常量可以被共用
 字面值常量 : 整数常量,小数常量,字符常量,字符串常量,布尔常量,空常量(null)
 常量的作用: 给变量赋值
 //常量池在JDK7时,搬到了堆内存中


本地方法区 : 给本地方法提供执行空间
本地方法 : 跟计算机系统进行交互的方法 -> native
寄存器 : 跟CPU运算相关


Java数据类型 :
 基本数据类型 : 数量固定 (四类八种)
 引用数据类型 : 无数种(五大类)
    类 class ,数组 Array ,接口 interface , 枚举 enum , 注解 @interface

2.两个数组的内存图

public class Demo {
    public static void main(String[] args) {
        //动态初始化
        int[] arr = new int[5];
        System.out.println("arr = " + arr);//地址值

        //对数组元素进行操作
        for (int i = 0; i < arr.length; i++) {
            System.out.println("arr[i] = " + arr[i]);
        }

        //修改数组的元素值
        arr[3] = 444;

        for (int i = 0; i < arr.length; i++) {
            System.out.println("arr[i] = " + arr[i]);
        }

        //静态初始化
        double[] ds =  {1.1,2.2,3.3};
        System.out.println("ds = " + ds);//地址值
        for (int i = 0; i < ds.length; i++) {
            System.out.println("ds[i] = " + ds[i]);
        }
    }
}

在这里插入图片描述

3.方法调用的内存图

调用方法的诀窍 :
 要什么给什么 -> 类型
 要多少给多少 -> 个数
 怎么要怎么给 -> 类型顺序

有返回值方法三种调用方式 : 赋值调用,输出调用,直接调用
直接调用 : 方法虽然执行了,但是没有处理结果 -> 无意义
输出调用 : 把结果直接输出,不能继续操作
赋值调用 : 接收方法的结果,可以继续操作结果

无返回值的方法调用方式 : 直接调用

方法调用调错:
 1. 实参位置报错 : 形参和实参不匹配
 2. 方法名报错 : 没有这个方法
 3. 整个调用方法语句报错 : a.接收结果的变量类型报错 b.调用方式错了

结论 :
 1. 如果方法的形参是基本数据类型,形参接收的是实参的具体值 //形参的改变不影响实参
 2. 如果方法的形参是引用数据类型,形参接收的是实参的地址值 //一变则都变

public class Demo {
    public static void main(String[] args) {
        //启动方法
        int sum = sum(20, 10);
        System.out.println("sum = " + sum);

       int[] arr = {1,2,3,4,5};
        System.out.println("arr = " + arr);
       System.out.println(Arrays.toString(arr));
       change(arr);
       System.out.println(Arrays.toString(arr));
    }

    //基本数据类型的方法
    public static int sum(int a, int b) {
        int sum = a + b;
        return sum;
    }

    public static void change(int[] arr){
        System.out.println("arr = " + arr);
        System.out.println(Arrays.toString(arr));
        for (int i = 0; i < arr.length; i++) {
            if (i % 2 == 0){
                arr[i] *= 2;//2,2,6,4,10
            }
        }
        System.out.println(Arrays.toString(arr));
    }
}

在这里插入图片描述

4.两个对象的内存图

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //行为
    public void eat(String food){
        System.out.println("姓名是 : " + this.name + " 年龄是 : " + this.age + " 的学生对象在吃 " + food);
    }
}
public class Demo {
    public static void main(String[] args) {
        //创建对象
        Student stu1 = new Student();
        System.out.println("stu1 = " + stu1);//地址
        //给学生对象的属性赋值
        stu1.setName("迪丽热巴");
        stu1.setAge(18);
        //调用学生对象的方法
        stu1.eat("切糕");

        //创建对象
        Student stu2 = new Student("古力娜扎", 19);
        System.out.println("stu2 = " + stu2);//地址
        //调用学生对象的方法
        stu2.eat("哈密瓜");
    }
}

在这里插入图片描述

static

1.static关键字

static : adj. 静态的 -> 状态修饰符
被修饰的成员就是类中的静态成员

static 关键字可以作用在 : 成员位置

被 static 修饰的成员具备以下4个特点 :

  1. 被static所修饰的成员被所有对象共享 -> 一变则都变
  2. 被static所修饰的成员不再属于单个对象,属于类 -> static成员 : 类属性/类方法
  3. 被static修饰的成员可以直接使用类名调用 -> 类名.静态成员 (关乎static成员的使用方式)
  4. 被static修饰的成员随着类的加载而加载优先于对象 -> 早于对象加载的

在这里插入图片描述

public class Student {
    //为了方便不写 private
    String name;
    int age;
    static String graduateFrom;//毕业院校

    //构造方法
    public Student() {
    }

    public Student(String name, int age, String graduateFrom) {
        this.name = name;
        this.age = age;
        this.graduateFrom = graduateFrom;
    }

    public void show(){
        System.out.println(name +" --- "+ age +" --- "+ graduateFrom);
    }
}
public class Demo {
    public static void main(String[] args) {

        //创建3个学生对象
        Student stu1 = new Student("迪丽热巴", 18, "五道口职业技术学院");
        Student stu2 = new Student("古力娜扎", 17, "厦门反散步职业学院");
        Student stu3 = new Student("马尔扎哈", 20, "战争学院");

        Student.graduateFrom = "武汉大学";

        stu1.show();
        stu2.show();
        stu3.show();

    }
}

在这里插入图片描述

2.static访问问题

非静态成员变量非静态成员方法静态成员变量静态成员方法
非静态方法
静态方法××
  1. 静态虽好,但是只能访问静态; -> 好在可以直接使用类名调用,不需要创建对象
  2. 为什么静态只能访问静态 ? 静态是随着类的加载而加载是更早出生的,不可以访问随对象加载的非静态成员
  3. 非要在静态方法内访问非静态成员 ? : 把对象在静态方法内创建出来

3.static 关键字的问题

冲突场景 :

  1. static 方法内不可以使用 this/super 关键字
  2. static 方法不能重写 //但是可以重载

4.static 关键字的常用场景

工具类的编写时,会大量的用到static关键字;

工具类的编写步骤 :

  1. 定义一个类,类名叫 XxxUtils.java -> 一般会放在util包下
  2. 私有无参构造方法,并不提供任何其他构造方法
    //Do not let anyone instance this class !!!
  3. 把所有成员变量和成员方法全部用static修饰即可


JDK中的很多工具类:
  Arrays 数组操作的工具类
  Math 数学操作工具类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值