Java基础知识总结(四):引用数据类型与参数传递机制

在 Java 面试中,经常会出现这样的问题:

  • String 是基本数据类型吗?
  • 数组属于什么类型?
  • Java 到底是值传递还是引用传递?
  • 为什么方法中修改对象属性会影响原对象?

这些问题本质上都与引用数据类型和参数传递机制有关。

本文将系统讲解 Java 引用类型、内存结构以及参数传递原理。


目录

  • Java数据类型分类
  • 什么是引用数据类型
  • 常见引用数据类型
  • String为什么是引用类型
  • 引用变量与对象的关系
  • Java参数传递机制
  • 基本数据类型传参
  • 引用数据类型传参
  • String参数传递分析
  • 面试高频陷阱题
  • 常见面试题
  • 总结

一、Java数据类型分类

Java中的数据类型分为两大类:

基本数据类型(Primitive Type)

引用数据类型(Reference Type)

基本数据类型

Java共有8种基本数据类型:

byte
short
int
long

float
double

char

boolean

特点:

  • 直接存储值
  • 占用固定内存
  • 效率较高

示例:

int age = 18;

double salary = 12000.5;

char sex = '男';

引用数据类型

除了基本数据类型以外,其余均属于引用数据类型。

特点:

  • 保存对象地址
  • 数据存储在堆内存
  • 可以表示复杂结构

示例:

String name = "Tom";

int[] nums = {1,2,3};

二、什么是引用数据类型

先看一个例子:

String name = "Tom";

很多初学者认为:

name中保存的是Tom

实际上并不是。

真实情况:

栈
↓

name

↓

保存对象地址

↓

堆

↓

"Tom"

图示:

栈(Stack)

name
 │
 ▼

堆(Heap)

"Tom"

因此:

引用变量保存的是地址

对象存放在堆中

三、常见引用数据类型

Java中的引用类型主要包括:


1、类(Class)

例如:

String name = "Java";

Date date = new Date();

String、Date本质都是类。


2、数组(Array)

例如:

int[] nums = {1,2,3};

String[] names = {"Tom","Jerry"};

数组对象存放在堆中。


3、接口(Interface)

例如:

List<String> list = new ArrayList<>();

这里:

List

就是接口类型。


4、枚举(Enum)

例如:

public enum Gender {

    MALE,

    FEMALE

}

使用:

Gender gender = Gender.MALE;

5、注解(Annotation)

例如:

@Override
@Service
@RequestMapping

本质都是注解类型。


四、String为什么是引用类型

这是面试高频题。

很多人误认为:

String

属于基本数据类型。

实际上:

String

是JDK提供的一个类。

查看源码:

public final class String

说明:

String属于引用类型

示例:

String str = "hello";

内存结构:

栈

str

↓

堆

"hello"

因此:

String

不是基本类型。


五、引用变量与对象的关系

例如:

Student stu = new Student();

执行过程:


第一步:

栈中创建引用变量:

stu

第二步:

堆中创建对象:

Student对象

第三步:

引用指向对象:

stu → Student对象

图示:

栈

stu
 │
 ▼

堆

Student对象

六、Java参数传递机制

这是面试中的经典问题:

Java是值传递还是引用传递?

答案:

Java只有值传递

很多开发者对此存在误解。

下面通过示例说明。


七、基本数据类型传参

示例:

public static void change(int num) {

    num = 100;
}

public static void main(String[] args) {

    int a = 10;

    change(a);

    System.out.println(a);
}

输出:

10

为什么?

调用:

change(a);

相当于:

复制了一份10

传给num

图示:

a = 10

↓

复制

↓

num = 10

修改:

num = 100;

不会影响:

a

因此:

输出10

八、引用数据类型传参

定义对象:

class User {

    String name;
}

测试代码:

public static void change(User user) {

    user.name = "Tom";
}

public static void main(String[] args) {

    User user = new User();

    user.name = "Jack";

    change(user);

    System.out.println(user.name);
}

输出:

Tom

为什么?

很多人认为:

引用传递

其实不是。

仍然是:

值传递

只是传递的值是:

对象地址

图示:

user

↓

0x001

调用:

change(user);

变成:

复制地址

0x001

↓

传给方法参数user

因此:

两个变量

指向同一个对象

内存结构:

主方法

user
 │
 ▼

0x001

────────────

change方法

user
 │
 ▼

0x001

修改对象属性:

user.name = "Tom";

实际上修改的是同一个对象。

所以主方法中的对象也发生变化。


九、重新赋值对象会怎样?

看下面代码:

public static void change(User user) {

    user = new User();

    user.name = "Tom";
}

主方法:

User user = new User();

user.name = "Jack";

change(user);

System.out.println(user.name);

输出:

Jack

原因:

方法内部:

user = new User();

创建了新对象。

此时:

方法参数user

已经指向新对象

而主方法中的:

user

仍然指向原对象。

因此不会受到影响。


图示:

调用前:

user
 │
 ▼

对象A

调用后:

主方法user
 │
 ▼
对象A

方法user
 │
 ▼
对象B

已经不是同一个对象。


十、String参数传递分析

看下面代码:

public static void change(String str) {

    str = "Java";
}

测试:

String str = "Hello";

change(str);

System.out.println(str);

输出:

Hello

原因:

String具有不可变性。

执行:

str = "Java";

并不是修改原对象。

而是:

创建新字符串

重新赋值

因此:

原变量不受影响

十一、高频面试陷阱题

示例1

public static void test(int num) {

    num = 100;
}

结果:

原变量不变

示例2

public static void test(User user) {

    user.name = "Tom";
}

结果:

原对象被修改

示例3

public static void test(User user) {

    user = new User();
}

结果:

原对象不受影响

示例4

public static void test(String str) {

    str = "Java";
}

结果:

原字符串不变

十二、常见面试题

面试题1

String是基本数据类型吗?

答案:

不是

String是类

属于引用数据类型

面试题2

数组属于什么类型?

答案:

引用数据类型

面试题3

Java是值传递还是引用传递?

答案:

Java只有值传递

面试题4

为什么对象传参后能修改原对象?

答案:

传递的是对象地址的副本

两个引用指向同一个对象

面试题5

为什么String传参后无法修改原值?

答案:

String不可变

重新赋值会创建新对象

十三、总结

本文介绍了:

  • Java数据类型分类
  • 引用数据类型
  • String本质
  • 数组、接口、枚举、注解
  • 引用变量与对象关系
  • Java参数传递机制
  • 基本类型传参
  • 引用类型传参
  • String传参分析

需要牢记的一句话:

Java中只有值传递,没有引用传递。

对于引用类型来说,传递的是:

对象地址的副本

理解这一点后,大多数参数传递相关问题都能迎刃而解。


更多推荐