精华内容
下载资源
问答
  • UE4《大象无形》学习笔记
    2020-02-13 23:15:46

    学习资料:《大象无形》罗丁力

    学习计划:看当日计划行事

    目录

    第1章 开发之前——五个最常见基类

    UObject

    Actor

    Pawn

    Character(继承Pawn)

    Controller

    总结

     

    第2章 需求到实现

    第3章 创建自己的C++类

    虚幻引擎类命名规则

    第4章 对象

    常见类对象的产生方法

    类对象的获取

    类对象的销毁

     

    第5章 从C++到蓝图

    UPROPERTY宏(变量)

    UFUNCTION宏(函数)

    第6章 UE4游戏性框架概述

    行为树

    广义的客户端-服务端模型

    第7章 引擎系统相关类

    在虚幻引擎4中使用正则表达式

    FPaths类的使用

    XML与JSON(TODO:解析)

    文件读写与访问(TODO:API熟悉)

    读写配置GConfig文件(TODO:就是Unity中的.Asset)

    UE_LOG

    字符串处理

    编译器相关技巧


    第1章 开发之前——五个最常见基类

    • UObject

      • Garbage collection垃圾收集
        • C++释放资源的解决方案,①继承UObject ②非UObject可以采用智能指针
      • Reference updating引用自动更新
      • Reflectio反射(TODO:第二章即将学习)
      • Serialization序列化:保存资源
      • Automatic updating of default property changes自动检测默认变量的 更改
      • Automatic property initialization自动变量初始化
      • Automatic editor integration和虚幻引擎编辑器的自动交互
      • Type information available at runtime运行时类型识别
        • UE4有自己的类型转换方案,Cast<TargetType>(OriginType)
      • Network replication网络复制
        • 构造函数会调用两次,自动处理变量同步是什么意思?P26
    • Actor

      • 它能够被挂载组件,但不是组件。组件都以U开头而不是A
    • Pawn

      • 国际象棋中的“棋子”,必须要被Controller所操控,可以是玩家也可以是AI
    • Character(继承Pawn)

      • 有特殊的Movement组件,提供了一个基于胶囊体的角色移动,包括了移动和跳跃功能
    • Controller

      • 控制Pawn和Character
      • AIController:使用UE4的行为树/EQS环境查询系统
      • PlyaerController:绑定输入,转化为对Pawn/Character的函数调用
    • 总结

      • M(Pawn)V(Pawn带的动态网格组件)C(Controller)

     


    第2章 需求到实现

    • 需求人持有武器,发射子弹
    • 武器继承Actor,子弹继承Actor,人继承Character

    第3章 创建自己的C++类

    • 继承UObject的类,类名上方需要加入UCLASS宏
    • 虚幻引擎类命名规则

      • F:纯C++类
      • U:继承UObject
      • A:继承
      • S:Slate空间相关类
      • H:HitResult相关类

    第4章 对象

    • 常见类对象的产生方法

      • 如果你的类是一个纯C++类型(F开头),你可以通过new来产生对象。
      • 如果你的类继承自UObject但不继承自Actor,你需要通过NewObject函数来产生出对象:NewObject<T>()
      • 如果你的类继承自AActor,你需要通过SpawnActor函数来产生出对象:GetWorld( )->SpawnActor<AYourActorClass>( )
      • 如果你需要产生一个Slate类,要么你在做深入开发(源码开发),要么UE版本过老
         
    • 类对象的获取

      • for(TActorIterator <ClassType> Iterator(GetWorld());Iterator;++Iterator)
         { 
            ...//do something 
        }
      • *Iterator访问对象,或者Iterator→function()
    • 类对象的销毁

      • 纯C++类
        • (TODO:验证)
        • 不是用new分配,会自动释放
        • 如果是new分配,尽量用智能指针TSharedPtr<YourClass> YourClassPtr=MakeShareable(new YourClass());
      • UObject类
        • 自带垃圾回收机制(智能指针)
      • ACtor类
        • MyActor->Destroy();

     


    第5章 从C++到蓝图

    • UPROPERTY宏(变量)

      • 变量注册到蓝图中:UPROPERTY(BlueprintReadWrite, VisibleAnywhere, Category = "Object")
      • 变量到处可见:UPROPERTY(EditAnywhere, Category = Collectable)
    • UFUNCTION宏(函数)

      • 注册函数到蓝图:UFUNCTION(BlueprintCallable,Category="Test")

    第6章 UE4游戏性框架概述

    • 行为树

      • 为什么选择行为树?UE3还是状态机,行为树“退行”特点,“逐个尝试,不行就换”,符合人类的思维方式。熟悉行为树的框架后,能更加快速地编写AI代码
      • 曾经在Unity学习过Behaviour Designer,主要是涉及了一些节点和装饰器。这个应该会成为以后的研究重点,概念感觉不是特别难理解,期待以后的学习,很有趣
    • 广义的客户端-服务端模型

      • 客户端是对服务端的拙劣模仿,不再时刻去"同步",而是去"预测",“模仿”

    第7章 引擎系统相关类

    • 在虚幻引擎4中使用正则表达式

      • 匹配CDEFGH,模式串和匹配串,想起了KMP算法,啧啧啧,整活
        void AMyActor::hhhh() {
            FString TextStr("ABCDEFGHIJKLMN");
            FRegexPattern TestPattern(TEXT("C.+H"));
            FRegexMatcher TestMatcher(TestPattern,TextStr);
            if (TestMatcher.FindNext()) {
                UE_LOG(LogTemp, Warning, TEXT("找到匹配内容 %d -%d"), TestMatcher.GetMatchBeginning(), TestMatcher.GetMatchEnding());//输出 找到匹配内容 2-8 
            }
        }
    • FPaths类的使用

      • 具体路径类,如:FPaths::GameDir()可以获取到游戏根目录
      • 工具类,如:FPaths::FileExists()用于判断一个文件是否存在
      • 路径转换类,如:FPaths::ConvertRelativePathToFull()用于将相对路径 转换为绝对路径
    • XML与JSON(TODO:解析)

    • 文件读写与访问(TODO:API熟悉)

    • 读写配置GConfig文件(TODO:就是Unity中的.Asset)

    • UE_LOG

      • 查看
        • Game模式 在Game(打包)模式下,记录Log需要在启动参数后加-Log
        • 编辑器模式 在编辑器下,需要打开Log窗口(Window->DeveloperTools->OutputLog)
      • 使用Log
        • UE_LOG(LogMy, Warning, TEXT("Hell World")); 
        • UE_LOG(LogMy, Warning, TEXT("Show a String %s"),*FString("Hello")); 
        • UE_LOG(LogMy, Warning, TEXT("Show a Int %d"),100);
        • 总结:第一个参数自定义,第二个参数Log灰,Warning黄,Error红
    • 字符串处理

      • FName:const 类型的 string,大小写不敏感
      • FText:不支持修改
      • FString:支持修改,但开销性能比上面两种要大
    • 编译器相关技巧

      • Images:图片的读取和类型转换

    第8章 模块机制(后面的东西学起来有点虚,没把握,以后再来)

    • 模块简介

      • 在不同模式(debug,release)下的包不同,引入了模块j机制
    • UBT(Unreal Build Tool)
      •  
    更多相关内容
  • 对于 Stiglitz (2002),需要找到可以限制这些对称性并减轻其后果的方法,这就是为什么我们在这里提出的研发建议是通过使用新的加密技术来解决对称信息的问题(区块链)允许操作的完全透明和交易对象的完全匿名...
  • 可以是无形的,如某项计划、某次商业交易。  对象是构成现实世界的一个独立单位,人们对世界的认识,是从分析对象的特征入手的。  对象的特征分为静态特征和动态特征两种。静态的特征指对象的外观、性质、属性...
  • 【C++】什么是对象?什么是类?

    千次阅读 2021-03-27 18:47:32
    ”当第一次接触面向程序设计语言Java时,大家都会拿这句话作为调侃,但是,作为一个大三的学生,如果还是对“对象”有着浅层次的理解,确实有点说过去啦! 文章目录1、什么是对象?1.1 现实世界中的含义:1.2 程序设计...

    “有对象吗?没有! new 一个。”当第一次接触面向程序设计语言Java时,大家都会拿这句话作为调侃,但是,作为一个大三的学生,如果还是对“对象”有着浅层次的理解,确实有点说不过去啦!

    在这里插入图片描述

    1、什么是对象?

    什么是对象?作为一个二十多岁的年轻人,乍一看,这还用说,当然就是结婚的对象啦。当然可以这样理解,但是世界这么大,我也想去看看万物世界,在看世界的过程中,我们在现实中能看到的每一个能叫出来名字的都可以被理解为对象,有些对象是抽象的,比如一场球赛,一场音乐会。有些是具体的,比如张三、李四、小花狗。

    1.1 现实世界中的含义:

    在现实世界中,任何事物都是对象。 它可以是一个有形的具体存在的事物,例如一张板凳,一台电脑,一个学生,一辆汽车,也可以是无形的,抽象的事物,例如一次演出,一场球赛等等,对象可以是简单的,也可以是复杂的。
    现实世界中的对象既具有静态的属性(或称之为状态),又具有动态的行为(或称操作,功能)。 静态属性指的是“是什么”,动态属性指的是“做什么”。 比如:潘小蓝的博客名称是潘小蓝,性别是男,年龄18岁 ,这些被称之为静态属性。潘小蓝看博客,写博客,或者正在看博客的你点击鼠标点赞收藏这些需要做的事情被称之为动态属性。
    有静态属性+动态属性的事物我们称之为对象。所以在现实世界中,对象一般可以表示为 属性 + 行为。一个对象往往是由一组属性和一组行为构成的。

    现实世界中的对象,具有以下特性:

    • 每一个对象必须有一个名字以区别于其他对象。
    • 用属性来描述对象的某些特征。
    • 有一组操作,每组操作决定对象的一个行为。
    • 对象的行为可以分为两类,一类是作用于自身的行为(例如我们在Java中的setXxx(),getXxx()方法,一种是作用于其他对象的行为。

    1.2 程序设计中的含义:

    程序设计中的对象是现实世界的另一种呈现。在面向对象程序设计中,对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体。

    在C++中,每个对象都是由数据和操作代码(通常用函数实现)组成的,数据就是上文提到的属性,操作代码是上文提到的动态行为。
    例如:一个学生就是一个对象,学号、姓名和成绩等数据就是它的属性,输入或输出姓名、学号、成绩等操作就是前面提到的行为。

    2、什么是类?

    如果说对象是我们常说的女朋友,那么类就是女朋友的生产者和制造者。如果将多个女朋友的共同特征抽象出来,比如都是女生,都是18岁这些共有的属性,或者共有的行为操作,比如爱生气,爱撒娇。将这些共有的属性和行为抽象出来,抽象出来的就是一个类。 如果下次还像找类似的女朋友,那么就可以直接通过类实例化一个对象,共同压马路啦。类是对象的抽象,而对象是类的实例。

    两者之间的关系:

    类和对象之间的关系是抽象和具体的关系。类是多个对象进行综合抽象的结果,对象又是类的个体实物,一个对象是类的一个实例。 例如 : 虽然张三、李四、王五、潘小蓝,每个人的性格、爱好、职业、特长等各有不同,但是基本特征是相似的,都具有相同的生理构造,都能吃饭、说话、走路等,于是把他们统称为“人”类,而具体的每一个人是人类的一个实例,也就是一个对象。

    在面向对象程序设计中,总是先声明类,再由类生成其对象。 类是建立对象的“模板”,按照这个模板所建立的一个个具体的对象,就是类的实际例子,通常成为实例。(就是我们通常所说的实例化,每个对象就是类的一个实际的例子)。举个例子就是,在手工制作月饼的时候,先雕刻一个有凹下图案的木模,然后在木模上抹油,接着将事先揉好的面塞进木模里,用力挤压后,将木模反扣在桌上,一个漂亮地 图案就会出现在月饼上了。这样一个接着一个地,就可以制造出外形一模一样的月饼。这个木模就好比是"类",制造出来的糕点就是所说的“对象”。

    在C++语言中,把类中数据称之为数据成员,类中的操作是用函数来实现的,这些函数成为成员函数。

    在这里插入图片描述

    展开全文
  • 然而,无形资产在我国高校一直得到重视,很多高校对其管理缺乏科学的规范,造成无形资产流失严重,从而制约了高校的发展。以11个影响高校无形资产管理的重要因素作为研究对象,采用解释结构模型法分析了各因素之间的...
  • 基于无形资产的重要性,整合我国一些学者对无形资产进行的实证研究,以我国汽车行业上市公司作为研究对象,采用格兰杰因果检验方法对上市公司无形资产与公司盈利能力之间的关系进行分析,随后探讨产生结论的原因并...
  • 吃人的那些 Java 名词:对象、引用、堆、栈

    万次阅读 多人点赞 2019-09-05 15:57:09
    作为一个有着 8 年 Java 编程经验的 IT 老兵,说起来很惭愧,我被 Java 当中的四五个名词一直困扰着:**对象、引用、堆、栈、堆栈**(栈可同堆栈,因此是四个名词,也是五个名词)。每次我看到这几个名词,都隐隐...

    作为一个有着 8 年 Java 编程经验的 IT 老兵,说起来很惭愧,我被 Java 当中的四五个名词一直困扰着:对象、引用、堆、栈、堆栈(栈可同堆栈,因此是四个名词,也是五个名词)。每次我看到这几个名词,都隐隐约约觉得自己在被一只无形的大口慢慢地吞噬,只剩下满地的衣服碎屑(为什么不是骨头,因为骨头也好吃)。

    记得中学的课本上,有一篇名为《狂人日记》课文;那时候根本理解不了鲁迅写这篇文章要表达的中心思想,只觉得满篇的“吃人”令人心情压抑;老师在讲台上慷慨激昂的讲,大多数的同学同我一样,在课本面前“痴痴”的发呆。

    十几年后,再读《狂人日记》,恍然如梦:

    鲁迅先生以狂人的口吻,再现了动乱时期下中国人的精神状态,视角新颖,文笔细腻又不乏辛辣之味。

    当时的中国,混乱成了主色调。以清廷和孔教为主的封建旧思想还在潜移默化地影响着人们的思想,与此同时以革命和新思潮为主的现代思想已经开始了对大众灵魂的洗涤和冲击。

    最近,和沉默王二技术交流群(120926808)的群友们交流后,Java 中那四五个会吃人的名词:对象、引用、堆、栈、堆栈,似乎在脑海中也清晰了起来,尽管疑惑有时候仍然会在阴云密布时跑出来——正鉴于此,这篇文章恰好做一下归纳。

    一、对象和引用

    在 Java 中,尽管一切都可以看做是对象,但计算机操作的并非对象本身,而是对象的引用。 这话乍眼一看,似懂非懂。究竟什么是对象,什么又是引用呢?

    先来看对象的定义:按照通俗的说法,每个对象都是某个类(class)的一个实例(instance)。那么,实例化的过程怎么描述呢?来看代码(类是 String):

    new String("我是对象张三");
    new String("我是对象李四");
    

    在 Java 中,实例化指的就是通过关键字“new”来创建对象的过程。以上代码在运行时就会创建两个对象——“我是对象张三"和"我是对象李四”;现在,该怎么操作他们呢?

    去过公园的同学应该会见过几个大爷,他们很有一番本领——个个都能把风筝飞得老高老高,徒留我们眼馋的份!风筝飞那么高,没办法直接用手拽着飞啊,全要靠一根长长的看不见的结实的绳子来牵引!操作 Java 对象也是这个理,得有一根绳——也就是接下来要介绍的“引用”(我们肉眼也常常看不见它)。

    String zhangsan, lisi;
    zhangsan = new String("我是对象张三");
    lisi = new String("我是对象李四");
    

    这三行代码该怎么理解呢?

    先来看第一行代码:String zhangsan, lisi;——声明了两个变量 zhangsan 和 lisi,他们的类型为 String。

    ①、歧义:zhangsan 和 lisi 此时被称为引用。

    你也许听过这样一句古文:“神之于形,犹利之于刀;未闻刀没而利存,岂容形亡而神在?”这是无神论者范缜(zhen)的名言,大致的意思就是:灵魂对于肉体来说,就像刀刃对于刀身;从没听说过刀身都没了刀刃还存在,那么怎么可能允许肉体死亡了而灵魂还在呢?

    “引用”之于对象,就好比刀刃之于刀身,对象还没有创建,又怎么存在对象的“引用”呢?

    如果 zhangsan 和 lisi 此时不能被称为“引用”,那么他们是什么呢?答案很简单,就是变量啊!(鄙人理解)

    ②、误解:zhangsan 和 lisi 此时的默认值为 null

    应该说 zhangsan 和 lisi 此时的值为 undefined——借用 JavaScript 的关键字;也就是未定义;或者应该是一个新的关键字 uninitialized——未初始化。但不管是 undefined 还是 uninitialized,都与 null 不同。

    既然没有初始化,zhangsan 和 lisi 此时就不能被使用。假如强行使用的话,编译器就会报错,提醒 zhangsan 和 lisi 还没有出生(初始化);见下图。

    如果把 zhangsan 和 lisi 初始化为 null,编译器是认可的(见下图);由此可见,zhangsan 和 lisi 此时的默认值不为 null

    再来看第二行代码:zhangsan = new String("我是对象张三");——创建“我是对象张三"的 String 类对象,并将其赋值给 zhangsan 这个变量。

    此时,zhangsan 就是"我是对象张三"的引用;“=”操作符赋予了 zhangsan 这样神圣的权利。

    第三行代码 lisi = new String("我是对象李四");和第二行代码 zhangsan = new String("我是对象张三");同理。

    现在,我可以下这样一个结论了——对象是通过 new 关键字创建的;引用是依赖于对象的;= 操作符把对象赋值给了引用

    我们再来看这样一段代码:

    String zhangsan, lisi;
    zhangsan = new String("我是对象张三");
    lisi = new String("我是对象李四");
    zhangsan = lisi;
    

    zhangsan = lisi; 执行过后,zhangsan 就不再是"我是对象张三"的引用了;zhangsan 和 lisi 指向了同一个对象(“我是对象李四”);因此,你知道 System.out.println(zhangsan == lisi); 打印的是 false 还是 true 了吗?

    二、堆、栈、堆栈

    谁来告诉我,为什么有很多地方(书、博客等等)把栈叫做堆栈,把堆栈叫做栈?搞得我都头晕目眩了——绕着门柱估计转了 80 圈,不晕才怪!

    我查了一下金山词霸,结果如下:

    我的天呐,更晕了,有没有!怎么才能不晕呢?我这里有几招武功秘籍,你们尽管拿去一睹为快:

    1)以后再看到堆、栈、堆栈三个在一起打牌的时候,直接把“堆栈”踢出去;这仨人不适合在一起玩,因为堆和栈才是老相好;你“堆栈”来这插一脚算怎么回事;这世界上只存在“堆、栈”或者“堆栈”(标点符号很重要哦)。

    2)堆是在程序运行时在内存中申请的空间(可理解为动态的过程);切记,不是在编译时;因此,Java 中的对象就放在这里,这样做的好处就是:

    当需要一个对象时,只需要通过 new 关键字写一行代码即可,当执行这行代码时,会自动在内存的“堆”区分配空间——这样就很灵活。

    另外,需要记住,堆遵循“先进后出”的规则(此处有雷)。就好像,一个和尚去挑了一担水,然后把一担水装缸里面,等到他口渴的时候他再用瓢舀出来喝。请放肆地打开你的脑洞脑补一下这个流程:缸底的水是先进去的,但后出来的。所以,我建议这位和尚在缸上贴个标签——保质期 90 天,过期饮用,后果自负!

    还是记不住,看下图:

    (不好意思,这是鼎,不是缸,将就一下哈)

    3)栈,又名堆栈(简直了,完全不符合程序员的思维啊,我们程序员习惯说一就是一,说二就是二嘛),能够和处理器(CPU,也就是脑子)直接关联,因此访问速度更快;举个十分不恰当的例子哈——眼睛相对嘴巴是离脑子近的一方,因此,你可以一目十行,但绝对做不到一开口就读十行字,哪怕十个字也做不到

    既然访问速度快,要好好利用啊!Java 就把对象的引用放在栈里。为什么呢?因为引用的使用频率高吗?

    不是的,因为 Java 在编译程序时,必须明确的知道存储在栈里的东西的生命周期,否则就没法释放旧的内存来开辟新的内存空间存放引用——空间就那么大,前浪要把后浪拍死在沙滩上啊。

    现在清楚堆、栈和堆栈了吧?

    三、基本数据类型

    先来看《Java 编程思想》中的一段话:

    在程序设计中经常用到一系列类型,他们需要特殊对待。之所以特殊对待,是因为 new 将对象存储于“堆”中,故用 new 创建一个对象──特别小、简单的变量,往往不是很有效。因此,不用new来创建这类变量,而是创建一个并非是引用的变量,这个变量直接存储值,并置于栈中,因此更加高效。

    在 Java 中,这些基本类型有:boolean、char、byte、short、int、long、float、double 和 void;还有与之对应的包装器:Boolean、Character、Byte、Short、Integer、Long、Float、Double 和 Void;它们之间涉及到装箱和拆箱,点击链接。

    看两行简单的代码:

     int a = 3;
     int b = 3;
    

    这两行代码在编译的时候是什么样子呢?

    编译器当然是先处理 int a = 3;,不然还能跳过吗?编译器在处理 int a = 3; 时在栈中创建了一个变量为 a 的内存空间,然后查找有没有字面值为 3 的地址,没找到,就开辟一个存放 3 这个字面值的地址,然后将 a 指向 3 的地址。

    编译器忙完了 int a = 3;,就来接着处理 int b = 3;;在创建完 b 的变量后,由于栈中已经有 3 这个字面值,就将 b 直接指向 3 的地址;就不需要再开辟新的空间了。

    依据上面的概述,我们假设在定义完 a 与 b 的值后,再令 a=4,此时 b 是等于 3 呢,还是 4 呢?

    思考一下,再看答案哈。

    答案揭晓:当编译器遇到 a = 4;时,它会重新搜索栈中是否有 4 的字面值,如果没有,重新开辟地址存放 4 的值;如果已经有了,则直接将 a 指向 4 这个地址;因此 a 值的改变不会影响到 b 的值哦。

    最后,留个作业吧,下面这段代码在运行时会输出什么呢?

    public class Test1 {
        public static void main(String args[]) {
            int a = 1;
            int b = 1;
    
            a = 2;
    
            System.out.println(a);
            System.out.println(b);
    
            TT t = new TT("T");
            TT t1 = t;
            t.setName("TT");
    
    
            System.out.println(t.getName());
            System.out.println(t1.getName());
        }
    }
    
    class TT{
        private String name;
    
        public TT (String name) {
            this.name = name;
        }
    
        public String getName() {
            return this.name;
        }
    
        public void setName(String name1) {
            this.name = name1;
        }
    }
    

    上一篇:如何理解 Java 中的继承?

    下一篇:Java 的操作符——“=”号

    微信搜索「沉默王二」公众号,关注后回复「免费视频」获取 500G Java 高质量教学视频(已分门别类)。

    展开全文
  • 1对象 世界上所有的事物都可以称为对象对象可以是有形的如一台电视机等也可以是无形的如帐户一项记录等对象具有静态特征和动态特征 对象是封装了数据结构及可以施加在这些数据结构上的操作的封装体这个封装体有可以...
  • 第一部分基础篇;从程序设计方法的角度看面向对象是一种新的程序设计范型...对象是现实世界中某个实际存在的事物它可以是有形的比如一辆汽车也可以是无形的比如一项计划对象是构成世界的一个独立单位它具有自己的静态特
  • 我有一个Json对象,但是在实际操作中,会无形中少了一些子对象,但是又知道是为啥 希望各位大大帮我解惑一下 比如下面这个Json对象 解析出来的时候 就只有两个子对象,少了两个子对象 var JsonObj= { 008: { name: ...
  • 作为一名PM,你也许花了许多时间在学习如何提升产品设计,需求处理和战略规划的能力上,最后却发现在这些高大上的工作最后都回归到了沟通。以上情景可能是许多PM都经历过...如果说PM常感觉会被一只无形的手控制甚至干预
  • 一个 Java 对象到底有多大?

    千次阅读 2021-02-12 14:30:52
    阅读本文大概需要 2.8 分钟...但是殊不知,在我们不经意间,大量的内存被无形地浪费了。一个 Java 对象到底有多大?想要精确计算一个 Java 对象占用的内存,首先要了解 Java 对象的结构表示。Java 对象结构一个 Java...

    阅读本文大概需要 2.8 分钟。

    出处:http://u6.gg/swLPg

    编写 Java 代码的时候,大多数情况下,我们很少关注一个 Java 对象究竟有多大(占据多少内存),更多的是关注业务与逻辑。

    但是殊不知,在我们不经意间,大量的内存被无形地浪费了。

    一个 Java 对象到底有多大?

    想要精确计算一个 Java 对象占用的内存,首先要了解 Java 对象的结构表示。

    Java 对象结构

    一个 Java 对象在 Heap 的表示,可以分为三部分:

    Object Header

    Class Pointer

    Fields

    每个普通 Java 对象在堆(heap)中都有一个头信息(object header),头信息是必不可少的,记录着对象的状态。

    e3cee1a2f60dc535f5bd27d6c805c9fa.png

    32 位与 64 位占用空间不同,在 32 位中:

    hash(25)+age(4)+lock(3)=32bit

    64 位中:

    unused(25+1)+hash(31)+age(4)+lock(3)=64bit

    我们知道,在 Java 中,一切皆对象;每个类都有一个父类, ClassPointer 就是当前对象父类的一个指针。

    在 32 位系统中,这个指针为 4byte;

    在 64 位系统中,如果开启指针压缩(-XX:+UseCompressedOops)或者 JVM 堆的最大值小于 32G,这个指针也是 4byte,否则是 8byte。

    关于字段(Fields),这里指的是类的实例字段;也就是说不包括静态字段,因为这个字段是共享内存的,只会存在一份。

    下面以 32 位系统为例子,计算一下 java.lang.Integer 到底占用多大内存:

    ObjectHeader 和 Pointer 都是固定的,4+4=8byte 。

    再看看字段,只有这一个,表示数值:

    /** * The value of the Integer. * * @serial */private final int value;

    一个 int 在 java 中占据 4byte,所以 Integer 的大小为 4+4+4=12byte。

    这个结果对吗?

    不对!

    还有一点没有说: 在 java,对象占用的 heap 大小是 8 位对齐的,上面的 12byte 没有对齐,所以需要补位 4byte。结果是 16byte!

    另外,在 Java中 还有一种特殊的对象, 数组!

    没错,这个对象有点特殊,它比其他对象多了一个属性:长度(length)。

    所以我们计算数组长度的时候,需要额外加上一个长度的字段,即一个 int 的大小。

    例如:int[] arr = new int[10];

    arr 的占用 heap 大小为:

    4(object header)+4(pointer)+4(length)+4*10(10个int大小)=52byte 由于需要 8 位对齐,所以最终大小为 56byte。

    节约内存原则

    在了解了对象的内存使用情况后,我们可以简单算一笔帐。

    一个 java.lang.Integer 占用 16byte,而一个 int 占用 4byte,4:1 的比例。

    也就是说整数的类类型是基本类型内存的 4 倍!

    由此我们得出第一个节约内存的原则:

    (1) 尽量使用基本类型,而不是包装类型。

    数据库建表的时候字段类型需要仔细推敲,同样 JavaBean 中的属性字段类型也需要仔细斟酌。

    不要吝啬使用 short,byte,boolean,如果短类型能放下数据,尽量不要使用更长的类型。

    一个 long 比一个 int 才多 4byte,但是你要想,如果内存中有 100W 个 long,那就白白浪费了约 4MB 空间,不要小看这一点点的空间浪费,因为随便一个跑着在线应用的 JVM 中,对象都能达到上千万!

    内存是节省出来的。

    (2) 斟酌字段类型,在满足容量前提下,尽量用小字段。

    你知道一个 ArrayList 集合,如果里面放了 10 个数字,占用多少内存吗?

    让我们算算:

    ArrayList 中有两个字段:

    /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. */private transient Object[] elementData;/** * The size of the ArrayList (the number of elements it contains). * * @serial */private int size;

    Object Header 占 4byte,Pointer 占 4byte,一个 int 字段(size)占 4byte,elementData 数组本身占 12(4+4+4),数组中 10 个 Integer 对象占 10×16。

    所以整个集合空间大小为 4+4+4+12+160=184byte。

    如果我们用 int[] 代替集合呢,12+4×10=52byte,对其后 56byte。

    集合跟数组的比例是 184:56,超过 3:1 了!

    (3) 如果可能,尽量用数组,少用集合。

    数组中是可以使用基本类型的,但是集合中只能放包装类型!

    如果实在需要使用集合,推荐一个比较节约内存的集合工具, fastutil。

    这里面包含了 JKD 集合中绝大部分的实现,而且比较省内存。

    小技巧

    在上面的三个原则基础上,提供两个小技巧。

    时间用 long/int 表示,不用 Date 或者 String。

    短字符串如果能穷举或者转换成 ascii 表示,可以用 long 或者 int 表示。

    注意:小技巧跟具体的场景数据有关系,可以根据实际情况进行激进优化节省内存。

    总结

    性能和可读性向来就有些矛盾,在这里也是,为了节约内存,不得不进行取舍,代码丑陋了一些,可读性差了一些,还好能省下一些内存。

    上面的原则在确实需要节约内存的时候 ,不妨可以试试!

    ·END·

    程序员的成长之路

    路虽远,行则必至

    本文原发于 同名微信公众号「程序员的成长之路」,回复「1024」你懂得,给个赞呗。

    回复 [ 520 ] 领取程序员最佳学习方式

    回复 [ 256 ] 查看 Java 程序员成长规划

    往期精彩回顾

    展开全文
  • 领域对象

    千次阅读 2020-08-29 21:49:04
    DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,...
  • 大象无形ue4基础知识

    2021-11-15 09:46:06
    序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件等的过程。 如果类继承自UObject,没继承自Actor,那么需要用newUObject()来产出对象 如果类继承自AActor,那么需要用spawnActor
  • 面向对象测试

    千次阅读 2020-04-01 17:03:52
    一、面向对象影响测试  传统的测试软件是从“小型测试”开始,逐步过渡到“大型测试”,即从单元测试开始,逐步进入集成测试,最后进行确认测试和系统测试。对于传统的软件系统来说,单元测试集中测试最小的可编译...
  • 早期方法的不足: 早期的方法只使用一种系统的视角作为构造块,而没有容纳其他视角。 1、结构化分析和设计方法集中于将功能作为系统的构造块...为了克服传统开发方法的不足,面向对象方法解决问题的思路 是从现实世...
  • 一、对象销毁 纯C++类销毁 尽量不要使用new、delete方案,可以使用智能指针。智能指针会使用引用计数来完成自动的内存释放。 使用MakeShareable函数可以来转化普通指针为智能指针。 TSharedPtr<YourClass&...
  • 什么是面向对象

    万次阅读 多人点赞 2019-06-01 23:02:26
    面向对象说到底就是一种思想,任何事物都可以看作是一个对象。在有些面试题目中也称之为OOP(Object Oriented Programming)。分开来解读就是: Object:对象、 Oriented: 面向的 Programming:程序设计...
  • C++习题03_类和对象

    千次阅读 2021-01-26 12:23:36
    C++习题03_类和对象 习题03(01)计算器类 题目描述 下面是一个计算器类的定义,请完成该类成员函数的实现,并编写main()。 class Counter { public: Counter(int num); void increament(); //给原值增1 void ...
  • 面向对象的软件开发方法

    千次阅读 2020-03-04 13:04:09
    一、了解什么是面向对象的软件开发方法 答:1、OOSD是一种把面向对象的思想应用于软件开发过程,是一种当今成熟的、普遍流行的软件开发方法 2、面向对象方法的解决思路是从现实世界中的客观对象入手,尽量运用人类...
  • Java面向对象(基础总结)

    千次阅读 多人点赞 2020-08-26 22:05:36
    Java面向对象(基础总结) 面向对象是一种编程思想。 面向对象的三大基本特征: 封装 继承 多态 面向对象的编程思想就是把事物看作一个整体,从事物的特征(属性)和行为(方法)两个方面进行描述。 面向对象的...
  • 面向过程的编程思想 面向过程是一种编程思想。如:递归思想,冒泡思想,二分查找等...面向过程的优点,执行速度快,适合大项目 例如 :上传一个产品 前段页面(upload.html),就是上传产品的表单,如:产...
  • 面向对象程序设计方法概述

    千次阅读 2019-09-21 16:55:11
    (1)面向过程与面向对象的比较 面向过程程序设计方法(C语言) 分析出要解决所需要的步骤,然后用函数把各步骤逐个实现,运行时依次调用各个函数即可。  程序 = 算法 + 数据结构 面向对象程序设计方法...
  • 从安全性来说,因为每次http请求都会携带cookie信息,这样无形中浪费了带宽,所以cookie应该尽可能少的使用,另外cookie还需要指定作用域,不可以跨域调用,限制比较多。但是用来识别用户登录来说,cookie还是比...
  • 建德若偷,质真若渝。大方无隅,大器晚成。  大音希声,大象无形。夫唯道善贷且成。  ——老子,《道德经》   ------...
  • ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。作为Java开发者,对这种写法会一见如故,但是它又跟Java的面向对象编程语法有所...
  • UE4大象无形命名规则

    2021-11-18 09:37:08
    如果前缀为F开头(纯C++类型),可以用new来产生新对象 前缀为U:可以用NewObject函数来产生对象 前缀为A:可以用SpawnActor函数来产生对象对象的获取:借助Actor迭代器,如下: for(TActorIterator<AActor...
  • java面向对象学习心得体会

    千次阅读 2019-11-25 21:55:29
    java中所有属性和方法都在类中,一个程序可以包含一个主类,和若干类 主类public class的名称只能与文件名相同。 java的类中包括属性和方法,一般由主类进行对象实例化,new一个对象的时候,系统统一开辟了一个堆...
  • 关于python类说法错误的是( )

    千次阅读 2021-02-03 14:47:07
    关于python类说法错误的是( )答:类的实例方法必须创建对象前才可以调用声表面波滤波器稳定性差,需要调整。( )答:√扁平骨盆是指( )答:骨盆入口前后径小于正常下列哪些因素可影响胚泡植入( )答:置入避孕环 子宫...
  • 前言:今天第一次上C++课程。根据老师的所讲内容进度,记录C++知识!... 面向对象程序设计的基本元素是对象,面向对象程序的主要结构特点是: 1. 程序一般由类的定义和类的使用两部分组成; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,549
精华内容 10,219
关键字:

对象不可以是无形的