相信接触过C++的人,在学习Java的过程当中,会遇到这样一个问题:在Java中常常会在类定义中声明一个该类的对象(例如Person类定义中声明一些叫parents之类的Person对象),但是在C++中,这样的声明是会出现问题的。

例如,在C++中,如下的代码会出错:

class A
{
private:
A a;
};

而在Java当中,这样一段代码可以却可以使用:

class B{
private B b;
}

要理解这样一个问题,首先要知道的是,在Java中,只有基本数据类型和引用数据类型。对于一个类对象,都是使用引用的概念。而Java的引用和C++的引用是不同的,具体内容可以参考这篇博客 https://blog.csdn.net/WaitForFree/article/details/51030013 。

C++中的引用更像是一种“别名”(实质上是个指针常量),例如: Test & test2 = test1 ,test2就可以访问和修改test1内存中存储的内容。当改变test2的值时,改变的是存储在test1内存中的值。

Java中的引用实际上是一种隐藏的指针,例如:Test test2 = test1,这样的语句只是声明了一个名叫test2的引用,并将这个引用指向test1,可以通过test2这个名称访问test1内存中的值。但当改变test2的值时,是将test2这个引用指向一个新的位置,这一点类似于C++的指针。

在上面两段代码中,C++ 的A a是声明了一个A类对象,并为这个对象分配了内存空间,这就造成了无限递归创建对象,不停的分配内存空间,最后堆栈溢出。

而Java中引用数据类型的声明和分配内存是分开的,B b只是声明了B类的一个引用,并没有为它指定一个内存空间,因此不存在无限递归分配空间的问题。

而C++中的指针可以将声明和内存分配分开,因此,如果将上面那段C++代码改成指针形式,则不会出现问题:

class A
{
private:
A *a;
};

当然,如果在类声明中将指针指向new A()的内存空间,则还会出现堆栈溢出的问题。

同理,如果在Java中,为B的对象b new一个内存空间就会出错,此时Java会抛出一个异常。

class B{
private B b = new B();
}

所以,不论是Java还是C++,在实际使用过程中,如果想要在类定义中声明该类的一个对象,则应该使用引用/指针,且不能分配内存,否则在定义中无限递归分配内存会造成堆栈溢出的问题。

关于C++类定义中不能声明该类对象,而Java中可以的原因的更多相关文章

  1. java中replaceAll反斜杠\ or java中replaceAll 括号[

    java中replaceAll反斜杠\   String s=new String("this is a \\"); s.replaceAll("\\",&qu ...

  2. 用var声明变量,在java中居然有这么多细节,你都了解么?

    简介 Java SE 10引入了局部变量的类型推断.早先,所有的局部变量声明都要在左侧声明明确类型. 使用类型推断,一些显式类型可以替换为具有初始化值的局部变量保留类型var,这种作为局部变量类型 的 ...

  3. 类定义,创建/销毁OC对象

    类定义 1 OC类分为2个文件,一个是.h文件,一个是.m文件: 2 .h文件存放类.函数声明: 3 .m文件类的具体实现: 4 类声明使用关键字@interface.@end来声明: 5 类实现使用 ...

  4. Java中常用来处理时间的三个类:Date、Calendar、SimpleDateFormate,以及Java中的单例设计模式:懒汉式、饿汉式以及静态内部类式

    (一)java.util.Date类 1.该类有一个long类型的属性:用来存放时间,是用毫秒数的形式表示,开始的日期是从1970年1月1号 00:00:00.    2.该类的很多方法都已经过时,不 ...

  5. angularjs中directive声明scope对象的用法

    总的来说用法 分三种: >1: scope: false  --> 继承父域,实现 双向数据绑定 示例代码 可自测: <!DOCTYPE html> <html lang ...

  6. JSP中的内置对象和Struts中的Web资源的详解

    JSP中的内置对象有如下几种: request :继承于HttpServletRequest, HttpServletRequest继承ServletRequest, 获得的Request对象的方法: ...

  7. [hadoop] map函数中使用FileSystem对象出现java.lang.NullPointerException的原因及解决办法

    问题描述: 在hadoop中处理多个文件,其中每个文件一个map. 我使用的方法为生成一个文件,文件中包含所有要压缩的文件在HDFS上的完整路径.每个map 任务获得一个路径名作为输入. 在eclip ...

  8. python中print()函数的“,”与java中System.out.print()函数中的“+”

    python中的print()函数和java中的System.out.print()函数都有着打印字符串的功能. python中: print("hello,world!") 输出 ...

  9. 【问题记录】MySQL中时间戳转日期格式和Java中时间戳转日期格式偶尔不一致

    背景: MySQL的某个字段存放着一些时间戳格式的时间. 问题描述: Java程序将MySQL中的时间戳字段取出来,在Java程序中转成yyyy-MM-dd HH:mm:ss格式的时候,偶尔会出现转化 ...

随机推荐

  1. 搭建分布式事务组件 seata 的Server 端和Client 端详解(小白都能看懂)

    一,server 端的存储模式为:Server 端 存 储 模 式 (store-mode) 支 持 三 种 : file: ( 默 认 ) 单 机 模 式 , 全 局 事 务 会 话 信 息 内 存 ...

  2. Adobe AIR 应用程序图标详细描述

    官方PDF文档: http://help.adobe.com/zh_CN/air/build/WS901d38e593cd1bac1e63e3d129907d2886-8000.html#WS901d ...

  3. Spring cache源码分析

    Spring cache是一个缓存API层,封装了对多种缓存的通用操作,可以借助注解方便地为程序添加缓存功能. 常见的注解有@Cacheable.@CachePut.@CacheEvict,有没有想过 ...

  4. 《Java多线程编程核心技术》知识梳理

    <Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...

  5. 深入理解RPC—序列化

    深入理解RPC-序列化 xiaofang233 2020-09-18 16:38:22 1024 收藏 6分类专栏: 分布式服务版权为什么需要序列化?首先,我们得知道什么是序列化与反序列化. 我们先回 ...

  6. 怎么清屏?怎么退出当前命令?怎么执行睡眠?怎么查看当前用户 id?查看指定帮助用什么命令?

    清屏:clear 退出当前命令:ctrl+c 彻底退出 执行睡眠 :ctrl+z 挂起当前进程 fg 恢复后台 查看当前用户 id:"id":查看显示目前登陆账户的 uid 和 g ...

  7. 解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法?

    通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间:而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集 ...

  8. 内置对象session和application的作用是什么?

    Jsp调用Javeabean命令UseBean中有Scope设置,一般有Application session page等设置,Page就是每页重新产生usebean中的javabean新对象,一般情 ...

  9. 什么是 Spring 的 MVC 框架?

    Spring 配备构建 Web 应用的全功能 MVC 框架.Spring 可以很便捷地和其他 MVC 框架集成,如 Struts,Spring 的 MVC 框架用控制反转把业务对象和控制逻 辑清晰地隔 ...

  10. Redis报错:DENIED Redis is running in protected mode

    转:Redis使用认证密码登录   Redis默认配置是不需要密码认证的,也就是说只要连接的Redis服务器的host和port正确,就可以连接使用.这在安全性上会有一定的问题,所以需要启用Redis ...