• [Java基础]由数组到内存地址的使用及理解


    一.数组的概念

      1.数组是Java里自带的引用数据类型,是一个同一种数据类型的集合,数组的构成有四大要素:数组的数据类型,数组的长度,数组的数组名,数组的下标:语法如

    int[] a;
    a = new int[10]; String[] s = {"aaa","bbb","ccc"}; Student[] stu = new Student[10];

         i.数组的数据类型决定了这个数组内能放数组的类型,一个数组不能存放有不同的数组类型的数据

         ii.数组长度一旦定义下来了便无法更改

         iii.数组的名字是指向该数组内存地址的

         iv.数组的下标是从0开始的

      2.关于数组的补充和些许算法

        i.遍历数组,for()循环,从0下标到数组.length-1下标一个一个找就好了,或者使用Stream.of()把它变成一个流,或者用别的方法如forEach()遍历

        ii.数组的排序:

    int a[] = {1,5,3,9,4,5};
    //冒泡排序
    for(int i =0;i < a.length-1;i++){
         for(int j =0;j <a.length-i-1;j++){
              if(a[j] > a[j+1]){
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }                           
        }      
    }    
    //选择排序
    for(int i = 0; i < a.length-1;i++){
        for(int j = i+1; j < a.length;j++){
            if(a[i] > a[j]{
                int temp = a[j];
                a[j] = a[i];
                a[i] = temp;
            }
        }
    }

    二.内存地址的基础理解

      1.在数组里,对内存的理解:

        i.当代码运行至初始化一个数组如int[] a = new int[5];此时内存便会在堆内存里开辟一个能存放长度为5的整数数组的空间,而对数组名,jvm会在栈内存中开辟一个空间存放该数组名,而空间里的值则是一个指向堆内数组空间的内存地                   址

      2.如上所说,jvm里有一个栈的内存空间,一个堆的内存空间,那么这两个空间jvm到底会如何使用呢?

        i.栈内存,也就是方法栈,每当jvm编译运行一个方法时便会开辟一个方法栈帧,用来存放局部变量表,操作数栈,动态链接,方法出口等信息,显而易见该内存的存放数据的结构为栈,先进后出,这也是为什么局部变量会覆盖全局变量的原因,而在这个方法栈帧中,jvm每读取一个基础数据类型的变量名,都会把他存放在一个栈内,而里面存放的都是基础数据类型变量,引用对象变量名,方法出口等信息

        ii.堆内存,这个内存是jvm管理的最大的内存空间,里面存放了引用数据类型的数据,如各种类的实例,各种数组,各种接口

        iii.栈内的引用对象变量名是怎么指向堆内存的实例的呢,那是因为栈内的每个引用对象变量名里存放的数据都是指向相应实例的内存地址

      3.==和.equals()的区别

        i.在Object类内其实.equals()和==没区别,代码如下:

     public boolean equals(Object obj){
        return (this == obj);
    }

         所以说都是判断两方在栈内存中存放的数据

        ii.那为什么说引用数据类型要用.equals()呢,如String之类

          

    String a = new String ("aaa");
    String b = new String ("aaa");
    System.out.println(a == b);   //输出的是false
    System.out.println(a.equals(b)); //输出的是true
    /*
      那为什么会出现这种情况呢?不是说都是比较栈内存中存放的数据吗?
      那要回到上方的栈与堆内储存数据的情况解析了,明显栈内存放的两个引用变量 a,b 指向的是不同的引用对象实例
      而如果要比较他们的值 == 显然不能排上用场,因为存放的是不同的内存地址,== 返回的肯定是false,那为了解决这一情况java在常用类内如String 重写了.equals()这一方法
      使得其return的不是 this == obj 而是 this.value == obj.value
      所以如果使用这种引用类型数据的时候请使用.equals()
      我们下面再看另一种情况
    */
    String c = "abc";
    String d = "abc";
    System.out.println( c == d); //这次输出的是true
    /*
      那这次又是因为什么呢?
      这要讲一下jvm内的常量池空间,当给String 类型直接赋值一个字符串 如"abc"这种,jvm就会自动在常量池内放一个值为"abc"的字符串并把它认为是一个常量
      而一个常量池内最多只能有一个相同的字符串常量,那后来给d赋值"abc"时,jvm自动把d的内存地址指向了这个字符串常量
      因此这个时候 c d 两个引用变量内存放的内存地址都是指向这个字符串常量的,因此这个时候使用 == 两个相同的内存地址比较 返回的boolean值必然是 true
    */


      4.对于方法内参数的传递

        i.当jvm在一个方法栈帧内读取到了另一个方法的出现,就会开辟另一个方法栈帧存放里面的新的数据,如局部变量表之类

        ii.新的方法帧栈存放的数据由原方法帧栈传递而来所以就会出现下方的情况:

    public static void main(String[] args){
      int a = 0;
      String s = "a";
      int[] array = {1,5,3,6};
    }
    public static void function(int a){ }
    public static void function(String s){
    }
    public static void function(int[] array){
    }
    /*
      显然这三个方法传递的值都不同,一个是基础数据类型,一个是String引用数据类型,一个是数据引用数据类型
      由原方法栈帧到新方法栈帧内的数据转移情况因参数传递的都是一个变量表内的值,但因为这两种数据类型变量在表内存放的数据不同而产生了两个不同的结果
      1.基础数据类型
        新方法栈帧接受到了一个基础数据类型的变量的值后会在自己的栈空间内新开辟一个与之相同的空间存放这个值,所以这个空间内无论这个值怎么变都不会影响到原方法栈帧内那个栈空间内的值
      2.引用数据类型
        新方法栈帧接收到了这个变量的值后也会做与接受基础数据类型相同的操作,但因为这种变量存放的数据是指向一个对象实例的地址,所以新栈内的对这个数据的操作都会映射到那个储存在堆内的对象实例,所以这里的操作会影响到实例数据的变化
    */
  • 相关阅读:
    部署kube-prometheus,添加邮件报警
    kubernetes1.8开启swagger-ui
    使用alien命令让deb包和rpm包互相转换
    debian开启cgroup memory子系统
    debian9使用systemd部署etcd集群
    装饰器
    mysql根据经纬度求两地距离
    使用rem编写自适应屏幕网页造成div被span撑高的解决办法
    java绘图合并图像AlphaComposite模式测试
    spring data jpa查询部分字段、多余附加字段
  • 原文地址:https://www.cnblogs.com/Lzzycola/p/13375602.html
Copyright © 2020-2023  润新知