Java语言学习--Java引用以及NullPointerException问题的解决

本文深入探讨Java中引用的概念及其实质,通过实例详细解释Null Pointer Exception (NPE) 的原因及其解决方法。同时对比指针变量,帮助理解Java引用机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

  前段时间在部署JPA项目时被一个java.lang.NullPointerException卡住了好久,后来搞明白了,是一个很基本的java引用的问题,也是一个涉及到Java语言本质的问题,整理了相关资料,记一博客分享之。

二、变量的本质

2.1 概念

  计算机语言中能储存计算结果或能表示值的抽象概念,它分为变量名和变量值两部分。

2.2 变量与变量名

  变量分为变量名和变量两个部分。在创建一个变量时,会在计算机中开辟一块内存,变量名就是人为地为这块内存起的一个名字,我们可以通过变量名来识别变量,便于我们区别和调用等等。这就相当于一间房子,这间房子又门牌号和房间两部分组成,门牌号是这间房子的标识,住户可以通过门牌号找到你对应的房间并入住。
  (而在C和Java等语言的基本数据类型中,基本数据类型的变量不是引用,变量的名字就是存储的内容。)

2.3 变量创建的全程及其本质

如下图:
blog

三、指针变量

  指针变量是C语言中所特有的一种数据类型。也就是说,指针变量不同于普通变量,一般变量存储的是变量本身,而指针变量存储的是存放数据的内存单元的地址。可以通过内存单元的地址来访问内存单元,从而获取该内存单元的数据信息。
  问题:那么指针变量存在的意义是什么呢?普通变量是如何被访问的?

四、Java中的引用

4.1 Java引用代码解析

如下代码

Person person = new Person();
Person personA = new Person();
Person personB = new Person();

  在这里,严谨地说,person、personA、personB仅仅是对象的名字而已,并不是对象本身,而是指向Person这个对象类型的一个对象名。
通过下面的验证即可证明之:

package cn.edu.sdut.softlab.test;

import cn.edu.sdut.softlab.person.Person;

public class PersonTest {

    public static void main(String args[]) {

        Person person = new Person();
        Person personA = new Person();
        Person personB = new Person();

        //打印测试各个对象的值
        System.out.println("三个对象的值:");
        System.out.println("person的值:" + personC);
        System.out.println("personA的值:" + personC);
        System.out.println("personB的值:" + personC);

        // 打印测试String常量
        System.out.println("三个对象的String常量:(意味着已经开辟内存空间)");
        System.out.println("person的String常量:" + person.toString());
        System.out.println("personA的String常量:" + personA.toString());
        System.out.println("personB的String常量:" + personB.toString());

        // 打印测试Class类型
        System.out.println("三个对象的类型:");
        System.out.println("person的Class:" + person.getClass());
        System.out.println("personA的Class:" + personA.getClass());
        System.out.println("personB的Class:" + personB.getClass());
    }

}

测试结果

三个对象的值:
person的值:null
personA的值:null
personB的值:null
三个对象的String常量:(意味着已经开辟内存空间)
person的String常量:cn.edu.sdut.softlab.person.Person@15db9742
personA的String常量:cn.edu.sdut.softlab.person.Person@6d06d69c
personB的String常量:cn.edu.sdut.softlab.person.Person@7852e922
三个对象的类型:
person的Class:class cn.edu.sdut.softlab.person.Person
personA的Class:class cn.edu.sdut.softlab.person.Person
personB的Class:class cn.edu.sdut.softlab.person.Person

  显然,上面三个变量person、personA、personB都已经实例化,但没有初始化,所以值为null,但是指向的都是同一个变量类型,并且已经开辟了属于自己扥内存空间,只是它们所占据的内存空间的位置不同而已。

4.2 从”NPE”的角度解释Java引用

如下代码所示:

package cn.edu.sdut.softlab.test;

import cn.edu.sdut.softlab.person.Person;

public class PersonTest {

    public static void main(String args[]) {

        Person personC;

        System.out.println("personC的值:" + personC);
        System.out.println("personC的String常量:" + personC.toString());
        System.out.println("personC的Class类型:" + personC.getClass());
    }
}

测试结果如下:

Exception in thread "main" java.lang.NullPointerException

原因分析
  这里只是声明了一个Person类型的引用,并没有实例化(初始化),所以,该personC对象没有指向任何实质的Person类型的对象。所以在访问该对象时无法找到其所指向的Person类型的对象,报出NullPointerException错误。
从这个角度也可以看出Java引用以及对象与对象名的本质区别。

4.3 基本数据类型的测试

如下代码所示:

package cn.edu.sdut.softlab.test;

import cn.edu.sdut.softlab.person.Person;

public class PersonTest {

    public static void main(String args[]) {

        String username = null;

        System.out.println("username的值:" + username);
        System.out.println("username的String常量:" + username.toString());
        System.out.println("username的Class类型:" + username.getClass());
    }
}

测试结果

Exception in thread "main" java.lang.NullPointerException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值