20200818 丁浪

个人展示

环境变量是什么


Java中只有局部的引用 & Java中没有局部的实例


两个内存区域 栈 & 堆

  • 栈中存储基本数据类型
  • 堆中存储由new关键字创建的对象

Java中基本数据类型的特点:只能由编译器分配内存,作用域只在块内

理解Java中引用数据类型要理解两个点:

  1. 实例
  2. 引用

实例是什么?实例是类的一个具体的对象,有的习惯叫做对象,我习惯并且喜欢将这个“具体的对象”叫做实例。实例只能由new关键字去创建,如:

new String("abc");
new Object();

new关键字在创建一个类的实例,并将其放在堆中,注意:还没结束

引用又是什么呢?引用可以类比于C中的指针,甚至可以说是等同于,当然不明白C也没关系,我虽然熟悉C,但是却很反对将引用和C的指针进行类比和等同,在Java中,你可以视引用为一条有指向的线,线的作用是指向一个实例或者null,当然你也可以指向一个非法区域。

上文中说道new 关键字创建了一个类的实例,并将其放入一个堆中,到这一步还未结束,是因为new关键字还会返回一个引用,理解下面这句简单的代码:

String s01=new String("abc");

new 关键字创建一个实例之后随后将该实例的引用返回给了s01,我们通过s01去访问已经创建好的实例。

嗯,到此步为止,什么是实例,什么是引用应当有一个初步的认识了,然后这里必须得声明一下,可能以前你听过的实例与引用和我这里的有些差别,我希望在此先以我的为主,之后再去看差别再那些地方。然后接下来我们会真正的去理解这句话:Java中只有局部的引用 ,没有局部的实例。

现在看这样一段代码

public class A{
    public static void main(String[] args) {
        String s01=new String("abc");
        doIt(s01);
        System.out.println(s01);
    }
    public static void doIt(String s) {
        s=null;
    }
}

主程打印了什么

  1. abc
  2. 无打印
  3. 程序出错报空指针异常

再看这样一段相似的代码

    public static void main(String[] args) {
        String s01=null;
        s01=doIt02();
        System.out.println(s01);
    }
    public static String doIt02() {
        String s=new String("aaa");
        return s;  //return null
    }

主程打印了什么?

这两段代码实际上只证明了一件事:Java中类的实例不是局部的,我在doIt02中创建了一个实例,并将该实例的引用返回到主程中;主程用s02去保存该引用,并通过该引用成功地去访问实例(整个过程没有新建实例),这表明Java中的实例不是局部的。而关于引用是局部的,这很好理解,只要处理doIt02的块,引用s就无法在访问,这点不需要过多解释。

理解这句话有什么好处吗?

或许到这个位置,你会觉得这玩意没价值,那我们来看下面这段代码

class B {
    public static void main(String[] args) {
        int[] myArray = { 1, 2, 3, 4, 5 };
        ChangeIt.doIt(myArray);
        for (int j = 0; j < myArray.length; j++)
            System.out.print(myArray[j] + " ");
    }
}
class ChangeIt {
    static void doIt(int[] z) {
        z = null;
    }
}

主程打印的是什么(一点解释:Java中数组是特殊的类)?

细心的会发现,实际上这和上面的一个案例完全一致,只是看起来复杂一点,本质上是一致的。若果你做错了,按这我的解释去想,或许这会是你的收获。好的,更有趣的题目没有发现,下面我们会更深入的讨论一些东西。

更深入的理解

学过Java的小伙伴应当知道Java数据类型被划分为了两大类:基本数据类型、引用数据类型,嗯,那引用又是啥玩意?引用是指的引用数据类型吗?这个有两种理解,一种就是答案是肯定的:引用就是指引用数据类型。另一种答案是保留的,引用不是引用数据类型,我的答案是如此,并且我不会使用引用这个术语,而是使用引用变量,为什么要这样且听下面的解释,注意这两句话,解释将围绕着这两句话进行:

  1. 引用变量是一个变量
  2. Java中变量存储在栈去

变量每个同学都不陌生,下面代码声明了一个int基本数据类型的变量,有一个细节的:你可以立马把a作为一个右值使用吗?不行的,编译器不运行你这样做(C中可以,但是这是不安全的做法,并且是个非常坏的做法)。

int a;

引用是一个变量,变量存储在栈区,嗯,你可能会去想说,为什么要去强调这一点,嗯,如果要真回答这个问题的话,也许是因为有趣吧,初学Java的时候一直被引用这个词搞得昏头转向,有一天突然明白这玩意之后就好像明白Java是个啥玩意了...这种明白不是指一下子变得很厉害,二是指遇到很多问题之后能大致的明白这些问题是那么肥事了,比如equals和究竟是有啥区别(声明的一点时,有其他办法去理解equals和的区别,这仅仅适用于我自己),就好像环境变量这玩意一样。

然后我们再最后来看一个很简单的图:

1597761441502

评论