
- 词 义
- 目标
- 拼 音
- duì xìang
- 出 自
- 《套不住的手》
- 中文名
- 对象
-
面向对象与面向过程的本质的区别
2018-01-10 20:19:04前言: 如果你很想搞明白面向对象是什么,面向过程是什么,或者说二者之间的区别是什么,那么就花费一点...面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个前言:
如果你很想搞明白面向对象是什么,面向过程是什么,或者说二者之间的区别是什么,那么就花费一点时间来研读一下这篇博客,你一定会有很大的收获的!
一、面向对象与面向过程的区别
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
可以拿生活中的实例来理解面向过程与面向对象,例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。
如果是面向对象的设计思想来解决问题。面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了多个步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
上述的内容是从网上查到的,觉得这个例子非常的生动形象,我就写了下来,现在就应该理解了他俩的区别了吧,其实就是两句话,面向对象就是高度实物抽象化、面向过程就是自顶向下的编程!
二、面向对象的特点
在了解其特点之前,咱们先谈谈对象,对象就是现实世界存在的任何事务都可以称之为对象,有着自己独特的个性
属性用来描述具体某个对象的特征。比如小志身高180M,体重70KG,这里身高、体重都是属性。
面向对象的思想就是把一切都看成对象,而对象一般都由属性+方法组成!属性属于对象静态的一面,用来形容对象的一些特性,方法属于对象动态的一面,咱们举一个例子,小明会跑,会说话,跑、说话这些行为就是对象的方法!所以为动态的一面, 我们把属性和方法称为这个对象的成员!
类:具有同种属性的对象称为类,是个抽象的概念。比如“人”就是一类,期中有一些人名,比如小明、小红、小玲等等这些都是对象,类就相当于一个模具,他定义了它所包含的全体对象的公共特征和功能,对象就是类的一个实例化,小明就是人的一个实例化!我们在做程序的时候,经常要将一个变量实例化,就是这个原理!我们一般在做程序的时候一般都不用类名的,比如我们在叫小明的时候,不会喊“人,你干嘛呢!”而是说的是“小明,你在干嘛呢!”
面向对象有三大特性,分别是封装性、继承性和多态性,这里小编不给予太多的解释,因为在后边的博客会专门总结的!
三、面向过程与面向对象的优缺点
很多资料上全都是一群很难理解的理论知识,整的小编头都大了,后来发现了一个比较好的文章,写的真是太棒了,通俗易懂,想要不明白都难!
用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。所谓盖浇饭,北京叫盖饭,东北叫烩饭,广东叫碟头饭,就是在一碗白米饭上面浇上一份盖菜,你喜欢什么菜,你就浇上什么菜。我觉得这个比喻还是比较贴切的。
蛋炒饭制作的细节,我不太清楚,因为我没当过厨师,也不会做饭,但最后的一道工序肯定是把米饭和鸡蛋混在一起炒匀。盖浇饭呢,则是把米饭和盖菜分别做好,你如果要一份红烧肉盖饭呢,就给你浇一份红烧肉;如果要一份青椒土豆盖浇饭,就给浇一份青椒土豆丝。
蛋炒饭的好处就是入味均匀,吃起来香。如果恰巧你不爱吃鸡蛋,只爱吃青菜的话,那么唯一的办法就是全部倒掉,重新做一份青菜炒饭了。盖浇饭就没这么多麻烦,你只需要把上面的盖菜拨掉,更换一份盖菜就可以了。盖浇饭的缺点是入味不均,可能没有蛋炒饭那么香。
到底是蛋炒饭好还是盖浇饭好呢?其实这类问题都很难回答,非要比个上下高低的话,就必须设定一个场景,否则只能说是各有所长。如果大家都不是美食家,没那么多讲究,那么从饭馆角度来讲的话,做盖浇饭显然比蛋炒饭更有优势,他可以组合出来任意多的组合,而且不会浪费。
盖浇饭的好处就是"菜"“饭"分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是"可维护性"比较好,“饭” 和"菜"的耦合度比较低。蛋炒饭将"蛋”“饭"搅和在一起,想换"蛋”"饭"中任何一种都很困难,耦合度很高,以至于"可维护性"比较差。软件工程追求的目标之一就是可维护性,可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的好处之一就是显著的改善了软件系统的可维护性。
看了这篇文章,简单的总结一下!面向过程
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:性能比面向过程低 -
解惑真小白的苦恼 | 类的对象,对象引用,对象实例,引用变量
2019-11-04 09:54:35对于刚接触不久面向对象的真小白童鞋来说,类的对象,对象的实例,对象的引用,引用变量的问题以及莫过于没得对象虽然博主也没得对象,本文将逐个逐个讲解! 1.何谓对象? 在Java中有一句比较流行的话,叫做“万物皆...对于刚接触不久面向对象的真小白童鞋来说,类的对象,对象的实例,对象的引用,引用变量的问题以及莫过于没得对象虽然博主也没得对象,本文将逐个逐个讲解!
1.何谓对象?
在Java中有一句比较流行的话,叫做“万物皆对象”,这是Java语言设计之初的理念之一。要理解什么是对象,需要跟类一起结合起来理解。下面这段话引自《Java编程思想》中的一段原话:
“按照通俗的说法,每个对象都是某个类(class)的一个实例(instance),这里,‘类’就是‘类型’的同义词。”
从这一句话就可以理解到对象的本质,简而言之,它就是类的实例,比如所有的人统称为“人类”,这里的“人类”就是一个类(物种的一种类型),而具体到每个人,比如张三这个人,它就是对象,就是“人类”的实例。
2.何谓对象引用?
我们先看一段话,这段话同样来自于《Java编程思想》:
“每种编程语言都有自己的数据处理方式。有些时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C/C++里的指针)来操作对象。所有这些在
Java
里都得到了简化,一切都被视为对象。因此,我们可采用一种统一的语法。尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“引用”(reference)。”很显然,从这段话可以看出对象和对象引用不是一回事,是两个完全不同的概念。举个例子,我们通常会用下面这一行代码来创建一个对象:
Person per = new Person("张三");
有小白童鞋会说,这里的
per
是一个对象,是Person
类的一个实例。也有小白童鞋会说,这里的per
并不是真正的对象,而是指向所创建的对象的引用。到底哪种说法是对的?我们先不急着纠结哪种说法是对的,再看两行代码:Person person; person = new Person("张三");
这两行代码实现的功能和上面的一行代码是完全一样的。大家都知道,在Java中
new
是用来在堆上创建对象用的,如果per
是一个对象的话,那么第二行为何还要通过new
来创建对象呢?由此可见,
per
并不是所创建的对象,是什么?上面的一段话说的很清楚,“操纵的标识符实际是指向一个对象的引用”,也就是说per
是一个引用,是指向一个可以指向Person
类的对象的引用。真正创建对象的语句是右边的new Person("张三")
;因此这里的per
是一个引用,是指向一个可以指向Person
类的对象的引用。简单来说,对象的引用意思是“定义一个变量,这个变量指向的是一个对象“
Object obj=new Object(); //Object:类 //obj:对象的引用 //new Object():对象
3.何谓对象实例?
首先,没有“对象的实例”这一说法,只有类的实例,而类的实例,指的就是类的对象,说白了就是对象。
但是还是有很多人这样叫,那怎么理解对象实例呢?比如说人类中有个叫宜春的程序员,宜春就是人类的一个实例String s = new String("YiChun");
s
就是String
类中的一个实例关于对象实例官方没有给其概念,其实有很多概念官方都没有给的,什么父类声明指向子类对象、方法签名等概念都是没有的 ,只是人们经常这么用这么说就习惯了。因此关于实例对象大体可以理解为对象引用的意思…
4.何谓引用变量?
引用变量就是用引用类型声明的变量,这种变量叫引用类型变量。如:
People people; //其中people就是引用变量,People是一个类属于引用类型
5、对象与对象引用碰撞火花
从对象引用出发:
一个对象引用可以指向零个或一个对象
从对象出发:
一个对象可以被一个或多个对象引用
怎么理解捏?小白童鞋脑壳逐渐变大…
5、1. 从对象引用出发:一个对象引用可以指向零个或一个对象
首先先来理解第一句话:从对象引用出发:一个对象引用可以指向零个或一个对象
public static void main(String[] args) { Two t; //一个对象引用可以指向零个对象 t=new Two();//一个对象引用可以指向一个对象 t=new String();//一个对象引用不可以指向 >1个对象 }
试想一下这样的代码会出现啥情况?是的,它会编译失败
看完上面这个例子就能说明了么?我们接着看下面这个代码:public static void main(String[] args) { String str; str=new String("string1"); str=new String("string2"); }
我们知道,凡是
new
都能创建出一个对象,我们发现上面代码String
对象引用str
一个new
了两次,而且上面代码编译也不报错,的的确确是创建了两个对象,那这怎么说?小白童鞋还没说完,把博主按在马桶盖盖上…别急,我们再看看上面代码输出啥
public static void main(String[] args) { String str; str=new String("string1"); str=new String("string2"); System.out.println(str); } 运行结果: string2
这说明啥?说明现在str是下一个对象的引用。上一个对象被垃圾回收了,因为上一个对象(也就是
string1
)不能被再次使用了。因此上面这个程序可以这样理解:public static void main(String[] args) { String str;//一个对象引用str指向零个对象 str=new String("string1");//一个对象引用str指向一个对象string1 str=new String("string2");//注意:这里对象引用str并不是指向第二个对象string2,而是将之前指向第一个对象string1的引用重新指向了另一个对象string2 }
对象引用str并不是指向第二个对象string2,而是将之前指向第一个对象string1的引用重新指向了另一个对象string2,因此从对象引用出发:一个对象引用可以指向零个或一个对象!
这个时候,小白童鞋渐渐松开了把博主按在马桶盖盖上的双手…
5、2. 从对象出发:一个对象可以被一个或多个对象引用
我们再来理解一下第二句话:从对象出发,一个对象可以被一个或多个对象引用
小白童鞋同样不解,于是又用双手把博主按在马桶盖盖上…
看下面这个程序:
Demo demo1,demo2,demo3; demo1=new Demo(); demo2=demo1; demo3=demo2;
怎么理解?看的有点晕?会不会感觉后面两句代码就是对象引用=对象引用…
其实要弄清除这个,首先你得弄清楚java虚拟机内存,弄清楚变量(对象引用)和对象是如何存储的,对象引用是存储在栈内存中,而对象是存储在堆内存中。分析如下:
Demo demo1,demo2,demo3;//创建多个对象引用,都存储在栈中 demo1=new Demo();//创建一个Demo对象,存储在堆中,并将demo1指向这个对象,相当于加了一个链 demo2=demo1;//demo2与demo1一样,都指向堆中Demo对象 demo3=demo2;//demo3与demo2一样,都指向堆中Demo对象
首先,每个对象只有一个地址值,
new Demo()
是创建了一个对象,demo1
是这个对象的地址值,用来找到这个对象,demo2=demo1
是把new Demo()
这个对象的地址值由demo1
改为了demo2
,后面的demo3=demo2
也是只改变了对象的地址值,对象本身的空间大小都没有变化,变的,是这个对象的地址值,也就是c里面所谓的指针。这个时候,小白童鞋渐渐松开了把博主按在马桶盖盖上的双手…
最后,我们再看看一个网上关于对象与对象引用很流行的程序与分析,代码如下:
UserType ut = new UserType(); // ut是引用,实际的对象在内存里。 ut = new UserType(); /*现在ut是另一个对象的引用,先前的对象被垃圾回收了(因为先前的对象不能被再次使用了)。*/ UserType ut2; // 定义了一个引用ut2,他不引用任何对象,不能使用。。。。 ut2 = new UserType(); // 然ut2成为一个对象的引用。 UserType ut3 = new UserType(); UserType ut4 = new UserType(); ut3 = ut4; // 现在ut3引用ut4的对象,这里不是赋值。。。 int a = 5; int b = 4; a = b; // 这里是赋值。 a b 依然引用不同的对象
6、最后要相信的真理
对于面向对象语言,如java,首先,请小白童鞋相信一句话:一切皆为对象。然后相信另一句话:变量只是一个零时的储存地点。引用类型的变量只是一个普通变量,储存了引用类型的地址。对象的创建是直接在内存中分配一个内存。
最后再梳理一下
引用类型变量 就 相当于 电脑上的快捷方式; 对象就相当于 你 磁盘里面 安装的游戏,它 实实在在 占用你的空间内存; 而变量 只是快捷方式
说白了基本数据类型变量就像是直接放在柜子里的东西,而引用数据类型变量就是这个柜子对应编码的钥匙。钥匙号和柜子对应。
到这里文章就结束了喔,小白童鞋,你何识着咩啊~
最后,若有不足或者不正之处,欢迎指正批评,感激不尽!
欢迎各位关注我的公众号,一起探讨技术,向往技术,追求技术…
小白童鞋关注了我的公众号之后,又用双手把博主按在马桶盖盖上… -
java对象结构以及对象大小计算示例(通俗易懂)
2020-05-17 10:34:51在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。 具体如下图 java 普通对象结构 java 数组对象结构 对象结构组成 对象头 ...概念
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
具体如下图
java 普通对象结构
java 数组对象结构
对象结构组成
对象头
HotSpot虚拟机的对象头包括两部分信息:
- Mark Word
第一部分Mark Word,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit - 类型指针
对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例. - 数组长度(只有数组对象有)
如果对象是一个数组, 那在对象头中还必须有一块数据用于记录数组长度.
实例数据
实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes。
原生类型(primitive type)的内存占用如下:
Primitive Type Memory Required(bytes) byte, boolean 1 byte short, char 2 bytes int, float 4 bytes long, double 8 bytes 包装类型
包装类(Boolean/Byte/Short/Character/Integer/Long/Double/Float)占用内存的大小等于对象头大小加上底层基础数据类型的大小。
包装类型的对象内存占用情况如下:
Numberic Wrappers +useCompressedOops -useCompressedOops Byte, Boolean 16 bytes 24 bytes Short, Character 16 bytes 24 bytes Integer, Float 16 bytes 24 bytes Long, Double 24 bytes 24 bytes 对齐填充
第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。
HotSpot的对齐方式为8字节对齐:
(对象头 + 实例数据 + padding) % 8=0且0 <= padding < 8
jvm相关参数
上面用到的useCompressedOops这个参数,我们可以看看在命令行输入:java -XX:+PrintCommandLineFlags -version 查看jvm默认参数如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pKMke0p9-1589680207000)(E:\技术帖子\笔记\基础\图\java对象结构\jvm参数.png)]
分别是 -XX:+UseCompressedOops 和 -XX:+UseCompressedClassPointers
这2个参数都是默认开启(+代表开启,-代表关闭)UseCompressedOops:普通对象指针压缩(oop是ordinary object pointer的缩写),
UseCompressedClassPointers:类型指针压缩。例如:
Object o = new Object();
o指向new Object()的引用就是“普通对象指针”,
new Object()自身还需要指向Object类型的引用,也就是"类型指针"。这2个压缩参数可以有4种组合(++, --, + -, -+),但有1种组合是会抛出警告的:
-XX:+UseCompressedClassPointers -XX:-UseCompressedOops,不要使用这种参数组合,用这种参数启动jvm时会抛出警告。
Java HotSpot(TM) 64-Bit Server TIM warning: UseCompressedClassPointers requires UseCompressOops
原因是jvm层面的hotspot源码对jvm的参数组合做了限制,一看就懂:
// UseCompressedOops must be on for UseCompressedClassPointers to be on. if (!UseCompressedOops){ if (UseCompressedClassPointers){ warning("UseCompressedClassPointers requires UseCompressOops"); } FLAG_SET_DEFAULT(UseCompressedClassPointers , false); }
HotSpot对象模型
HotSpot中采用了OOP-Klass模型,它是描述Java对象实例的模型,它分为两部分:
-
类被加载到内存时,就被封装成了klass,klass包含类的元数据信息,像类的方法、常量池这些信息都是存在klass里的,你可以认为它是java里面的java.lang.Class对象,记录了类的全部信息;
-
OOP(Ordinary Object Pointer)指的是普通对象指针,它包含MarkWord 和元数据指针,MarkWord用来存储当前指针指向的对象运行时的一些状态数据;元数据指针则指向klass,用来告诉你当前指针指向的对象是什么类型,也就是使用哪个类来创建出来的;
那么为何要设计这样一个一分为二的对象模型呢?这是因为HotSopt JVM的设计者不想让每个对象中都含有一个vtable(虚函数表),所以就把对象模型拆成klass和oop,其中oop中不含有任何虚函数,而klass就含有虚函数表,可以进行method dispatch。
HotSpot中,OOP-Klass实现的代码都在/hotspot/src/share/vm/oops/路径下,oop的实现为instanceOop 和 arrayOop,他们来描述对象头,其中arrayOop对象用于描述数组类型。
以下就是oop.hhp文件中oopDesc的源码,可以看到两个变量_mark就是MarkWord,_metadata就是元数据指针,指向klass对象,这个指针压缩的是32位,未压缩的是64位;
volatile markOop _mark; //标识运行时数据 union _metadata { Klass* _klass; narrowKlass _compressed_klass; } _metadata; //klass指针
一个Java对象在内存中的布局可以连续分成两部分:instanceOop(继承自oop.hpp)和实例数据;
如图:
通过栈帧中的对象引用reference找到Java堆中的对象,再通过对象的instanceOop中的元数据指针klass来找到方法区中的instanceKlass,从而确定该对象的类型。
对象大小的计算
有以下几点:
1.在32位系统下,存放Class指针的空间大小是4字节,MarkWord是4字节,对象头为8字节。
2.在64位系统下,存放Class指针的空间大小是8字节,MarkWord是8字节,对象头为16字节。
3.64位开启指针压缩的情况下,存放Class指针的空间大小是4字节,MarkWord是8字节,对象头为12字节。
4.数组长度4字节+数组对象头8字节(对象引用4字节(未开启指针压缩的64位为8字节)+数组markword为4字节(64位未开启指针压缩的为8字节))+对齐4=16字节。
5.静态属性不算在对象大小内。
贴网上的一个比较实用的工具类:
import java.lang.instrument.Instrumentation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashSet; import java.util.Set; /** *对象占用字节大小工具类 **/ public class SizeOfObject { static Instrumentation inst; public static void premain(String args, Instrumentation instP) { inst = instP; } /** * 直接计算当前对象占用空间大小,包括当前类及超类的基本类型实例字段大小、<br></br> *引用类型实例字段引用大小、实例基本类型数组总占用空间、实例引用类型数组引用本身占用空间大小;<br></br> *但是不包括超类继承下来的和当前类声明的实例引用字段的对象本身的大小、实例引用数组引用的对象本身的大小 <br></br> * *@param obj *@return */ public static long sizeOf(Object obj) { return inst.getObjectSize(obj); } /** *递归计算当前对象占用空间总大小,包括当前类和超类的实例字段大小以及实例字段引用对象大小 * *@param objP *@return *@throws IllegalAccessException */ public static long fullSizeOf(Object objP) throws IllegalAccessException { Set<Object> visited = new HashSet<Object>(); Deque<Object> toBeQueue = new ArrayDeque<Object>(); toBeQueue.add(objP); long size = 0L; while (toBeQueue.size() > 0) { Object obj = toBeQueue.poll(); //sizeOf的时候已经计基本类型和引用的长度,包括数组 size += skipObject(visited, obj) ? 0L : sizeOf(obj); Class<?> tmpObjClass = obj.getClass(); if (tmpObjClass.isArray()) { //[I , [F 基本类型名字长度是2 if (tmpObjClass.getName().length() > 2) { for (int i = 0, len = Array.getLength(obj); i < len; i++) { Object tmp = Array.get(obj, i); if (tmp != null) { //非基本类型需要深度遍历其对象 toBeQueue.add(Array.get(obj, i)); } } } } else { while (tmpObjClass != null) { Field[] fields = tmpObjClass.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers()) //静态不计 || field.getType().isPrimitive()) { //基本类型不重复计 continue; } field.setAccessible(true); Object fieldValue = field.get(obj); if (fieldValue == null) { continue; } toBeQueue.add(fieldValue); } tmpObjClass = tmpObjClass.getSuperclass(); } } } return size; } /** * String.intern的对象不计;计算过的不计,也避免死循环 * *@param visited *@param obj *@return */ static boolean skipObject(Set<Object> visited, Object obj) { if (obj instanceof String && obj == ((String) obj).intern()) { return true; } return visited.contains(obj); } }
最后举三个例子:
首先需要创建一个mavean项目,引入包
<dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency>
1.需要补齐的对象
代码
public class User { long sex; Long mobile; String name; public static void main(String[] args) { System.out.println(ClassLayout.parseInstance(new User()).toPrintable()); } }
输出如图
2.不需要padding补齐的对象代码:
public class User { String name; Long mobile; int sex; public static void main(String[] args) { System.out.println(ClassLayout.parseInstance(new User()).toPrintable()); } }
输出如图
3.空对象,所占字节数代码:
public class User { public static void main(String[] args) { System.out.println(ClassLayout.parseInstance(new User()).toPrintable()); } }
输出如图
4.数组对象结构代码:
public class ArrayTest { public static void main(String[] args) { System.out.println(ClassLayout.parseInstance(new Integer[7]).toPrintable()); System.out.println(ClassLayout.parseInstance(new Integer[8]).toPrintable()); System.out.println(ClassLayout.parseInstance(new int[7]).toPrintable()); } }
输出如图
如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想! - Mark Word
-
java基础知识点04_面向对象
2020-08-16 23:24:11对象是具体的,类是对对象的抽象,描述对象的共同特征,是对象创建的模板,对象是类的一个具体实例,类实例化得到对象,每个类都有默认的无参构造方法,类实例化得到对象就是通过构造方法完成的,一旦定义了有参构造...java基础知识点04_面向对象
面向对象编程OOP 的本质就是:以类的方式组织代码,以对象的形式封装数据
面向对象三大特性:封装、继承、多态
对象是具体的,类是对对象的抽象,描述对象的共同特征,是对象创建的模板,对象是类的一个具体实例,类实例化得到对象,每个类都有默认的无参构造方法,类实例化得到对象就是通过构造方法完成的,一旦定义了有参构造,无参构造就必须显示定义
- 对象(具体):小明、小红、李华
- 类(抽象):学生
定义静态方法: public class Student { public static void say() { System.out.println("speaking...."); } } 调用静态方法: public class demo01 { public static void main(String[] args) { Student.say(); } } 定义非静态方法: public class Student { public void say() { System.out.println("speaking...."); } } 调用非静态方法: public class demo01 { public static void main(String[] args) { Student student = new Student(); student.say(); } } 类的静态方法是和类一起加载的,而类的非静态方法是类实例化之后才存在的 所以调用非静态方法必须先实例化类,通过实例化的对象来调用方法!
值传递和引用传递:
- 值传递
public class demo01 { public static void main(String[] args) { int a = 1; System.out.println(a); demo01.change(a); System.out.println(a); } public static void change(int a) { a = 10; } } 结果a的值并没有改变!
- 引用传递
public class demo01 { public static void main(String[] args) { Person person = new Person(); System.out.println(person.name); demo01.change(person); System.out.println(person.name); } public static void change(Person person) { person.name="BLU"; } } class Person{ String name; } 结果Person.name的值改变了!
创建对象时的内存分析:
public class Pet { public String name; public int age; public void bark(){ System.out.println("barking...."); } } public class demo { public static void main(String[] args) { Pet dog = new Pet(); dog.name = "格洛米"; dog.age = 3; dog.bark(); System.out.println(dog.name); System.out.println("dog.age"); Pet cat = new Pet(); cat.bark(); } }
对象初始化时属性的默认值:数字类型:0 或 0.0
字符类型:u0000
boolean:false
引用类型:null
面向对象三大特性 —— 封装
将属性私有化,通过 get/set 方法操作属性
好处:保护数据,提高安全性。隐藏代码的实现细节示例:
public class Student{ private String name; private int age; public String getName(){ return this.name; } public void setName(String name){ this.name = name; } } public class demo { public static void main(String[] args) { Student s1 = new Student(); s1.setName("BLU"); System.out.println(s1.getName();); } }
面向对象三大特性 —— 继承
类是对对象的抽象,继承是对类的抽象
人类 —> 学生类、老师类
使用 extends 关键字继承
public class Student extends Person{ }
子类会继承父类的全部的 public 方法和属性
所有的类都直接或间接继承 Object 类
只能有一个父类
super 代表父类
this 代表本类
super() 调用父类的构造
this() 调用本类的构造子类的构造器会首先调用父类的构造器
面向对象三大特性 —— 多态
静态方法和非静态方法的区别:
public class B { public static void test() { System.out.println("B....test"); } } public class A extends B{ public static void test() { System.out.println("A....test"); } } public class test { public static void main(String[] args) { A a = new A(); a.test(); B b = new A(); b.test(); } } 结果: A....test B....test 如果将A和B的test方法去掉static修饰,结果将变为: A....test A....test
静态方法与静态成员变量一样,属于类,在类装载的时候被装载到内存,一直存在,直到JVM关闭。
实例化方法,属于实例对象,实例化后才会分配内存,必须通过类的实例来引用。不会常驻内存,当实例对象被JVM 回收之后,也跟着消失。instance of 判断对象类型
Object object = new Student(); object instanceof Student true object instanceof Person true object instanceof Object true object instanceof Teacher false object instanceof String false
父子类类型转换:
//子转父,子类的特有方法丢失 Person person = new Student(); //父转子,需要强制转换 Student student = (Student) new Person();
抽象类:
使用 abstract 修饰的类叫 抽象类
在抽象类中用 abstract 修饰的方法叫 抽象方法
抽象方法只有方法名,没有 方法体
继承抽象类的子类,如果不是抽象类,则 必须实现 父类的所有抽象方法
子类只能继承一个抽象类
抽象类 不能实例化
抽象类中可以有普通方法
接口:
比抽象类更抽象的抽象,相当于没有普通方法的抽象类
使用 implements 实现接口,可实现多个接口
实现类必须实现接口的方法
jdk8新特性:接口也可以提供具体方法,但需要 default 修饰:
public interface demo { public default void test() { System.out.println("test..."); } }
final
final 修饰的类无法被继承
final 修饰的方法,子类无法重写
final 修饰的基本类型变量只有一次赋值机会
final 修饰的引用只有一次指向的机会
Object类
Object类是所有类的父类
toString() public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } getClass().getName()代表返回对象所属类的包名.类名 Integer.toHexString(hashCode())代表将对象的哈希值用16进制表示
finalize() 当一个对象没有任何引用指向的时候,它就满足垃圾回收的条件 当它被垃圾回收的时候,它的finalize() 方法就会被调用 finalize() 不是开发人员主动调用的方法,而是由虚拟机JVM调用的
equals() Object.class: public boolean equals(Object obj) { return (this == obj); } String.class: public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } equals和==的区别: 对于基本数据类型,==判断的是两个值是否相等 对于引用类型而言,==判断的是两个引用是否指向同一个对象 equals在Object类中本质上就是==, 而在String、Integer这些类中,equals方法被重写为值比较 String s1="apple"; String s2="apple"; String s3 = new String("apple"); String s4 = new String("apple"); System.out.println(s1==s2); System.out.println(s1.equals(s2)); System.out.println(s3==s4); System.out.println(s3.equals(s4)); System.out.println(s1.equals(s3));
hashCode() public native int hashCode(); hashCode方法返回一个对象的哈希值
线程同步相关方法: wait() notify() notifyAll()
getClass() public final native Class<?> getClass(); 返回一个对象的类对象
-
Python对象和类序列化到MySQL
2020-01-07 23:21:49pickle序列化对象和类到数据库,需修改mysql数据库表结构,字段类型设为二进制,如blob类型,参考: https://www.cnblogs.com/wangchunlan1299/p/7725062.html | test | CREATE TABLE `test` ( `id` int(10) unsigned ... -
-
js 对象转json,json转对象
2020-05-27 22:17:55将对象转成json类型:JSON.stringify(persion) 将json转换成对象类型:JSON.parse('{"name":"你大爷","age":108}') 简介: 对象转json:查看对象中存储的数据 json转对象:value=object.key (只有对象才可以... -
JS的对象与内置对象详细介绍
2019-07-06 23:53:50JS的对象就是Object,还有独立于宿主环境的ECMAScript实现提供的内置对象:Array,String,Date,Math。。。 首先我们来学习一下JS的对象: Object: JS里有一句话叫万物皆对象(除了基本数据类型)。但是new String(’... -
吃人的那些 Java 名词:对象、引用、堆、栈
2019-09-05 15:57:09作为一个有着 8 年 Java 编程经验的 IT 老兵,说起来很惭愧,我被 Java 当中的四五个名词一直困扰着:**对象、引用、堆、栈、堆栈**(栈可同堆栈,因此是四个名词,也是五个名词)。每次我看到这几个名词,都隐隐... -
什么是面向对象
2019-09-09 16:54:50面向对象(OOP)概述 从我们开始接触Java这门语言后,就有人告诉我们这是一门面向对象的语言。说的最多的是new个对象,其实并不知道什么是对象。以为对象就是一个class(类),并不觉得有什么特殊。直到很久之后,... -
几种服务分层架构及其对象命名规范
2020-03-04 20:48:501、经典的三层架构 (这不合理,太复杂的分层会导致混乱,《阿里巴巴手册》还是很... DTO( Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。 BO( Business Object):业务对象。 由Serv... -
java对象数组 创建对象数组,初始化对象数组
2019-07-30 16:34:15对象数组的概念: 如果一个数组中的元素是对象类型,则称该数组为对象数组。 当需要一个类的多个对象时,应该用该类的对象数组来表示,通过改变下标值就可以访问到不同的对象。 对象数组的定义和使用: 对象数组的... -
Java类和对象 详解(一)
2016-10-06 20:48:02一、面向对象简述面向对象是一种现在最为流行的程序设计方法,几乎现在的所有应用都以面向对象为主了,最早的面向对象的概念实际上是由IBM提出的,在70年代的Smaltalk语言之中进行了应用,后来根据面向对象的设计... -
JSON对象转成formData对象,formData对象转成JSON对象
2019-02-14 15:53:16在向后端请求时,如果上传的数据里存在file文件对象,需要用到表单提交,这时候我们需要将JSON对象,转成formData对象,具体见代码 Object.keys(params).forEach((key) =&amp;amp;gt; { formData.append... -
Vue项目JSON格式字符串和对象之间的互转
2018-10-18 15:12:151、将对象转换为JSON格式字符串 JSON.stringify(object) 2、将JSON字符串转换为对象 JSON.parse(jsonString); 更多技术请关注QQ群:636212586 -
游离对象 临时对象 持久化对象
2018-04-25 18:49:52临时对象是指new出的对象,没有对ID赋值;游离状态时候指对临时状态赋值ID的状态;持久化对象是指该对象已经插入数据库中; -
java对象引用及对象赋值-java对象克隆
2018-08-09 09:54:08一、Java对象及其引用 &amp;amp;amp;amp;nbsp; &amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;nbsp; 初学Java,总是会自觉或不... -
浅析new一个对象的过程
2020-05-07 23:52:02在进行Java编程时,我们通常需要通过new创建一个对象的实例。 Object obj = new Object(); 做了三件事 (1)为对象创建了对象空间; (2)调用类的构造方法; (3)将生成对象的地址返回。 具体步骤 1,首先到常量池... -
javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法
2017-02-08 19:12:05javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法前言在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并... -
js 将多个对象合并成一个对象 assign方法。ES6新特性有哪些
2018-09-06 21:57:371.作用:将多个对象{} 合并成一个独立对象。 2.使用方式: Object.assign(合并的对象,传入合并中的对象....) let user = {name:'无敌人',age:19}; let page = {pageSize:10,currentPage:1}; let newObj = {};.... -
JVM笔记 垃圾对象判断
2020-07-18 20:55:13垃圾对象 垃圾对象,我们可以认为是"死掉的对象",即不能被任何途径使用的对象 引用计数算法 在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为... -
JSP九大内置对象
2019-02-28 15:52:26JSP提供了由容器实现和管理的内置对象,也可以称之为隐含对象,由于JSP使用Java作为脚本语言,所以JSP将具有强大的对象处理能力,并且可以动态创建Web页面内容。但Java语法在使用一个对象前,需要先实例化这个对象,... -
深入理解Java类型信息(Class对象)与反射机制
2017-05-01 23:19:19【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ...深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解 -
java对象与对象引用变量
2018-07-12 14:47:54Java对象及其引用 先搞清楚什么是堆,什么是栈。 Java开辟了两类存储区域,对比二者的特点 存储区域 存储内容 优点 缺点 回收 栈 基本类型的变量和对象的引用变量 存取速度比堆要快,仅次于... -
对象和对象的引用
2018-06-02 01:41:28最近初学java对于对象和对象的引用以及实例化有诸多迷惑,查了很多博客和API,现整理自己的理解如下:Java是一种面向对象的语言,采用类和对象的概念。Java中每个对象都有一种类型,即对象所属的类。类有两个主要... -
java对象转js对象
2017-05-04 20:51:04在js中直接使用 EL表达式表达java对象时,输出是对象的类名。没有达到我们要使用该对象的目的。比如var user= ${user};在页面上查询代码为var user=com.test.domain.user;这时候想要获取user的属性值: user.name是会... -
Kubernetes对象模型
2018-10-13 20:44:20Kubernetes对象 在之前的文章已经讲到了很多Kubernets对象,包括pod,service,deployment等等。Kubernets对象是一种持久化,表示集群状态的实体。它是一种声明式的意图的记录,一般使用yaml文件描述对象,它使用... -
往数组里面添加对象,往对象里面添加元素
2018-09-13 11:40:48当后台传过来一个数组的时候,我们发现,需要往里面添加个属性,用起来更方便,这时候,我们就要往数组里面添加一个对象,再使用这个新的数组就可以了 var cardNumArr = this.data.cardNumArr; //定义一个空的数组... -
面向对象
2018-05-19 16:59:57Java语言的面向对象技术包括了面向对象和面向过程的基本概念,面向对象的特征,Java语言的类,对象,修饰符,抽象类等一系列的知识点首先让我们来了解一下什么是对象? 没错!面向对象我们肯定需要先知道对象到底是... -
Java的对象头和对象组成详解
2018-07-20 10:46:47一,对象头 1,Mark Word 2,指向类的指针 3,数组长度 二,实例数据 三,对齐填充字节 Java对象保存在内存中时,由以下三部分组成: 1,对象头 2,实例数据 3,对齐填充字节 一,对象头 java的对象头...
-
全新PHP运动步数卡密版
-
为您的Linux应用开发加油提速(二)
-
MySQL Router 实现高可用、负载均衡、读写分离
-
System.InvalidOperationException:“调用线程无法访问此对象,因为另一个线程拥有该对象。”
-
java文档Java上课的文档PPT.zip
-
taobao_seckill-master.zip
-
matlab车型识别源程序
-
2021年N1叉车司机考试题库及N1叉车司机考试报名
-
02 预定义类(LocalDate,).md
-
心音信号处理分析(含matlab代码)
-
NODE-VUE-MODA-源码
-
数据结构串讲笔记.docx
-
深究字符编码的奥秘,与乱码说再见
-
扒站仿站网站源码
-
C语言
-
2021-02-27
-
单点登录 (2).vpd
-
EJB核心技术及其应用
-
【Python-随到随学】 FLask第一周
-
L - Arena