Java 基本类型和引用类型

328 阅读2分钟

基本类型和引用类型

Java中数据类型分为:基本类型 和 引用类型。

一、基本数据类型:

Java中基本类型一共4类,把这4类展开后共8种基本类型。

(图:参考:blog.csdn.net/weixin_4514…

image.png

二、引用数据类型

分类方式1:类(class)、接口类型(interface)、数组类型(Array)、注解类型(Annotation)。

分类方式2

  • a: Java为我们提供好的类,比如说:Scanner,Random,ArrayList等。
  • b: 我们自己创建的类,按照类的定义标准,可以在类中包含多个方法与属性,来供我们使用。
ArrayList arr=new ArrayList<>(); //引用库里面已经有的,当然也包括接口

三、区别:

一、从概念上来说:

  • 基本数据类型:变量名指向具体的数值
  • 引用数据类型:变量名指向存数据对象的内存地址。(即变量名指向hash值)

二、从内存构建方面来说:

  • 基本数据类型:变量在声明之后java就会立刻分配给他内存空间
  • 引用数据类型:它以类似C指针的方式指向对象实体,这类变量声明时不会分配内存,只是存储了一个内存地址。

(这个引用数据类型变量本身是存储在内存栈上面,它指向对象实体,这个对象实体本身是存储在内存堆上面。 下面提到)

三、从使用方面来说:

  • 基本数据类型:使用时需要赋具体值,判断时使用“==”号
int a,b;
if(a == b){ ... }
  • 引用数据类型:使用时可以赋null,判断时使用equals方法
People p1=new People(“张三”);
People p2-new People(“李四”);
if(p1.equals(p2)){ ... }

两种数据类型的对于栈和堆的解读

1:基本数据类型的存储原理: 所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,八种数据类型是该存储模型;

2:引用类型的存储原理: 引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲, “引用”是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的;

区别:基本数据类型和引用类型的区别主要在于基本数据类型是分配在栈上的,而引用类型是分配在堆上的(需要java中的栈、堆概念) ,基本类型和引用类型的内存模型本质上是不一样的。

四、扩展举例

图和解析:参考:www.jianshu.com/p/587625e39…

int num =10;
String str="hello";

image.png

num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。

一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。

扩展:那么运算符 =对于二者是不同的作用。

num=20;
str="java";

此时修改内容,会发生什么?

image.png

对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。

对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变(重要)。

如上图所示,"hello" 字符串对象没有被改变。(但是,没有被任何引用所指向的对象是垃圾,会被垃圾回收器(GC)回收

调用方法时发生了什么?参数传递本质上就是赋值操作!(但是对于基本数据类型和引用数据类型的赋值操作的作用是不一样的!)

第一个例子:基本类型

void foo(int value) { 
    value = 100;
}
foo(num); // num 没有被改变

第二个例子:没有提供改变自身方法的引用类型

void foo(String text) { 
    text = "windows";
}
foo(str); // str 也没有被改变

第三个例子:提供了改变自身方法的引用类型

StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
     builder.append("4");
}
foo(sb); // sb 被改变了,变成了"iphone4"。

第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。

StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) { 
      builder = new StringBuilder("ipad");
}
foo(sb); // sb 没有被改变,还是 "iphone"。

重点理解为什么,第三个例子和第四个例子结果不同? 下面是第三个例子的图解:

image.png

builder.append("4")之后

image.png

下面是第四个例子的图解:

image.png

builder = new StringBuilder("ipad"); 之后

image.png