精华内容
下载资源
问答
  • 对象的复制和赋值什么区别?各自的应用场景是怎么样的?
    千次阅读
    2019-04-15 17:01:31

    部分引用:https://blog.csdn.net/liitdar/article/details/81874541

    对象赋值

    如同基本类型的赋值语句一样,同一个类的对象之间也是可以进行赋值操作的,即将一个对象的值赋给另一个对象。

    对于类对象的赋值,只会对类中的数据成员进行赋值,而不对成员函数赋值。

    给对象赋值和调用拷贝构造函数初始化另一个对象行为是类似的,但是有所区别,下面会讲到(实际上调用的是拷贝构造函数)

    拷贝构造函数和赋值

    拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象;但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而***赋值运算符是将对象的值复制给一个已经存在的实例。***这种区别从两者的名字也可以很轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。
    调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生。如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。
    以下代码用于辨析何时使用了拷贝构造、何时使用了赋值运算符

    复制

    使用拷贝构造函数操作对象的方式,称为“对象的复制”。

    int main()
    {
        Person p;
        Person p1 = p;    // 1
        Person p2;
        p2 = p;           // 2
        f(p2);            // 3
    
        p2 = f1();        // 4
    
        Person p3 = f1(); // 5
    
        getchar();
        return 0;
    }
    

    1、使用对象 p创建了一个新的对象p1,毫无疑问使用的是拷贝构造函数
    2、p2这个对象已经提前声明好了,执行的仅仅只是将p的值复制给p2
    3、这个就是拷贝构造函数 调用时机 之一“对象以值传递的方式传入函数参数”
    4、这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2
    5、直接调用拷贝构造函数使用f1()返回值创建了对象p3

    特别要说的是

    1. 对象进行赋值时,两个对象必须属于同一个类;
    2. s2 = s1; 只会使得学生2和学生1的各项数据相同,但是学生还是两个独立的个体;
    3. 对象赋值是通过赋值运算函数实现的\
    4. 在对象声明之后,进行的对象赋值运算,才属于“真正的”对象赋值运算,即使用了赋值运算符“=”;而在对象初始化时,针对对象进行的赋值操作,其实是属于对象的复制。
    //就是说  通过一个对象创建了另一个对象 调用的是拷贝构造函数(strcpy函数),执行的是复制操作
    	Person p;
        Person p1 = p;    // 1
        
    //对象全部创建好之后,执行的"="  才算是赋值操作
        ClassA obj1;
        ClassA obj2;
        obj2 = obj1; // 此语句为对象的赋值
    
    

    赋值操作中内存变化

    int main()
    {
        ClassA obj1(1, "liitdar");
        ClassA obj2;
     
        return 0;
    }
    

    上述中,声明了对象obj1和obj2之后,系统将会为其分配相应大小的内存空间(由于obj1初始化了,所以空间中存放的是liitdar 但是obj2并没初始化,所以存的是随机值)
    注:图片来源https://blog.csdn.net/liitdar/article/details/81874541

    执行赋值操作后 obj2 = obj2; 会将对象中的所有位于 stack 中的域进行相应的复制操作;

    目前就到这个程度,望指正。

    更多相关内容
  • 一个对象在内存中究竟是怎样进行布局的,如何依据代码去确定对象占据的大小,本文将进行粗略地探讨。 对象在内存中的布局,主要3个组成部分,包括对象头,实例数据与对齐填充。确定对象的大小,也是从这3个组成...

    一个对象在内存中究竟是怎样进行布局的,如何依据代码去确定对象占据的大小,本文将进行粗略地探讨。

    对象在内存中的布局,主要有3个组成部分,包括对象头,实例数据与对齐填充。确定对象的大小,也是从这3个组成部分的入手。


    对象头

    其中对象头中又包括Mark Word与Klass Word。当该对象是一个数组时,对象头还会增加一块区域,用来保存数组的长度。以64位系统为例,对象头存储内容如下图所示:

    |---------------------------------------------------------------------------------------------------------------|
    |                                              Object Header (128 bits)                                         |
    |---------------------------------------------------------------------------------------------------------------|
    |                        Mark Word (64 bits)                                     |      Klass Word (64 bits)    |       
    |---------------------------------------------------------------------------------------------------------------|
    |  unused:25 | identity_hashcode:31 | unused:1 | age:4 | biased_lock:0 | lock:01 |     OOP to metadata object   |  无锁
    |----------------------------------------------------------------------|---------|------------------------------|
    |  thread:54 |         epoch:2      | unused:1 | age:4 | biased_lock:1 | lock:01 |     OOP to metadata object   |  偏向锁
    |----------------------------------------------------------------------|---------|------------------------------|
    |                     ptr_to_lock_record:62                            | lock:00 |     OOP to metadata object   |  轻量锁
    |----------------------------------------------------------------------|---------|------------------------------|
    |                     ptr_to_heavyweight_monitor:62                    | lock:10 |     OOP to metadata object   |  重量锁
    |----------------------------------------------------------------------|---------|------------------------------|
    |                                                                      | lock:11 |     OOP to metadata object   |    GC
    |---------------------------------------------------------------------------------------------------------------|

    Mark Word

    该区域主要存储hashcode、gc年龄、锁标志等。在32位系统上,Mark Word为32位,在64位系统上,为64位,即8个字节。Mark Word在不同的锁标志(lock)下,结构也不尽相同。当然,lock相同时,比如lock=01,这时候需要借助偏向锁标记(biased_lock)来具体确定对象是否存在偏向锁。

    关于结合Mark Word讲锁的升级,可能要另外篇幅。不过,可以先看我的另外一篇文章Synchronized的优化,大致了解一下锁的优化。

    Klass Word

    该区域存储对象的类型指针,该指正指向对象类元数据(类元数据都在方法区中,对方法区不熟悉的同学,可以先参考我的另外一篇文章灵性一问——为什么用元空间替换永久代?),虚拟机能够通过这个指针,来确定该对象到底是哪个类的实例。在32位系统上,该区域占用32位,在64位系统上,占用64位,但是!当64位机器设置最大堆内存为32G以下时,将会默认开启指针压缩,将8字节的指针压缩为4字节。当然也可以使用+UseCompressedOops直接开启指针压缩。

    Array Length

    前面说过,如果对象是一个数组,那么对象头会增加一个额外的区域,用来记录数组的长度。在32位系统上,该区域占用32位,在64位系统上,占用64位,同样的,如果开启指针压缩,则会压缩到32位。

    可以看得出来,一个非数组的对象的对象头占用12个字节,即Mark Word(8)+Klass Word(4)。


    实例数据

    基本数据类型占用的长度如下:

    类型

    占用字节长度

    byte

    1

    short

    2

    int

    4

    long

    8

    float

    4

    double

    8

    char

    2

    boolean

    1

    对于引用变量占用的长度,同样视系统位数而定。32位系统占用4字节,64位系统8字节,开启指针压缩那就占用4字节。

    实例数据部分只会存放对象的实例数据,并不会存放静态数据。此外,子对象的实例数据部分会继承父类所有实例数据,包括私有类型,这里可以理解为子类拥有父类所有类型的成员变量,但在子类中无法直接访问这些私有实例变量。


    对齐填充

    这里的对齐填充有两方面:

    (1)HotSpot虚拟机规定对象的起始地址必须是8的整数倍,也就是要求对象的大小必须是8的整数倍。因此如果一个对象的对象头+实例数据占用的总内存没有达到8的倍数时,会进行对齐填充,将总大小填充到最近的8的倍数上。

    (2)字段与字段之前也需要对齐,字段对齐的最小单位是4个字节。

    可以这样理解,虚拟机每次会为字段发放一个最近的4倍数的一个盒子。比如,有个类的字段有一个boolean和一个int,这时候先为boolean发放第一个大小为4字节的盒子,将boolean放入其中,占用1个字节,浪费3个字节,因为int占用4个字节,根本放不下,需要虚拟机再分配一个大小为4的盒子。

    虚拟机不会按照字段声明的顺序去给字段分配盒子,而是会进行重排序,使得物尽其用。比如一个类有以下变量:char、int、boolean、byte。如果按照声明顺序去分配盒子的话,则需要为char分配一个盒子,浪费2个字节。再为int分配一个盒子,这个盒子正好满了,没有浪费。接着为boolean分配一个盒子,浪费3个字节。最后为byte分配一个盒子,又浪费3个字节。

    在进行重排序后,此时可以按照int(4)、char(2)+boolean(1)+byte(1)的顺序,虚拟机可以只分配2个盒子,大大减少内存浪费。但是引用类型的字段必定在最后才分配。


    例子

    例子位于64位机器上,其都开启指针压缩。

    (1)实例化一个没有任何属性的空对象,那么这个空对象占用的内存大小为多少呢?

    很简单,对象头占用12字节,还会利用4字节进行填充,一共占用16字节。

    (2)实例一个具有四个不同属性的对象

    class Test {
        public char charP;
        public int intP;
        public boolean booleanP;
        public byte byteP;
    }

    这就是对齐填充部分举的例子,对象头占用12字节,实例数据占用8字节,此时一共20字节,则对象填充需要占用4字节,一共占用24字节。

    我们使用一个jol(Java Object Layout)工具来分析Test对象占据的内存大小。只要在maven项目中引入这个依赖就好:

            <dependency>
                <groupId>org.openjdk.jol</groupId>
                <artifactId>jol-core</artifactId>
                <version>0.8</version>
            </dependency>

    然后在代码中这样调用:

    package com.yang;
    
    import org.openjdk.jol.info.ClassLayout;
    
    public class Main {
        public static void main(String[] args) {
            Test test = new Test();
            System.out.println(ClassLayout.parseInstance(test).toPrintable());
        }
    }
    

    输出如下:

    看的出来,总大小确实为24字节。

    (3)实例化一个具有父类的子类

    class Father {
        public boolean publicFlag;
        private boolean privateFlag;
        public static boolean staticFlag;
    }
    
    public class Test extends Father {
        public boolean publicFlag;
        private int b;
        protected double c;
        Long d;
    }

    猜猜看,实例化一个Test对象后,这个对象占据的内存大小是多少呢?

    这里可能会有几个问题:

    【1】子类的实例数据部分会排除掉父类的私有实例属性privateFlag吗?

    【2】子类的实例数据部分会覆盖掉父类的同名实例属性吗?

    带着这些疑问,我们直接使用jol查看对象内存大小:

    可以看到,子类对象中包含了父类所有的实例变量,且首先分配父类实例变量,再分配子类实例变量。对象头还是占用12字节,父类实例变量占用4字节(包括2个字节的字段填充),子类实例变量占用20字节,对象填充占用4字节,一共占用40字节。

    展开全文
  • 看到PHP设计模式中值对象模式中的例题,对于结果总感到有点疑惑。回头看了下PHP5的对象赋值真正清楚。
  • 要看的懂对象的创建过程,首先你得对Java虚拟机和Java基础以及JUC很是熟悉,比如类的加载过程,CAS、多线程、JVM的GC等等 首先好看一个图,我大概会根据图中的内容来分享这六个步骤(其实几个步骤不重要,只要包括...


    要看的懂对象的创建过程,首先你得有对Java虚拟机和Java基础以及JUC很是熟悉,
    比如类的加载过程、CAS、多线程、JVM的GC等等

    首先来看一个图,我大概会根据图中的内容来分享这六个步骤(其实几个步骤不重要,只要包括的内容都在就行):

    在这里插入图片描述

    一、创建对象的六个步骤:

    1、判断是否能在常量池中能找到类符号引用,并检查是否已被加载、链接、初始化(即判断类元信息是否存在)

    如果没有则在双亲委派模式下,使用当前类加载器以ClassLoader + 包名 + 类名为Key进行查找对应的.class文件以此来完成类的加载进内存。在这个过程中,要是找不到要加载的类JVM就会抛出ClassNotFoundException异常,意思就是找不到该类进行加载。

    2、为对象分配内存空间

    首先计算对象占用空间大小,接着在堆中划分一块内存给新对象,如果实例成员变量是引用变量,仅分配引用变量空间即可,即4个字节。文章结束附有Java八种基本数据类型的所占字节数,分配内存时根据堆中内存是否规整分为:

    内存规整—指针碰撞:如果是规整的,那么虚拟机将采用指针碰撞法来为对象分配内存。

    意思就是所有用过的内存在一边,空闲的内存在另一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那一边挪动一段与对象大小相等的距离,以此来分配内存给对象。如果垃圾收集器选择的是Serial、ParNew这种基于标记 - 压缩算法的,也就是一般使用带有compact(整理)过程的收集器时,就会使用指针碰撞分配方法。

    另外:为什么内存就会是规整的呢?或者为什么内存有不规整的呢?我写了一篇我觉得十分完整的JVM垃圾回收篇

    内存不规整—空闲列表:如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用这种空闲列表法给对象分配内存。

    意思就是虚拟机维护了一个列表,记录上哪些内存块是可用的,再分配的时候从列表找到一块足够大的空间划分给对象实例,这种分配方式就是空闲列表(Free List)。

    3、处理并发问题
    为什么会有这个阶段呢?就是我们都知道堆空间是多个线程共享的,那么多个线程同时去操作堆空间数据时就会存在并发线程安全问题。

    两种方式去解决这种并发安全问题:
    采用CAS失败重试、区域加锁更新的原子性

    CAS算法是这样的:CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包(Java.Util.Concurrent)中的原子类都使用了CAS技术。

    CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。
    CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。

    大白话:假如A线程要把共享变量sum的值从1修改为2,那么这时候A线程会先通过地址去获取一次sum的初始值1作为预期值,在修改之前会把之前获取的预期值与当前sum的值进行一次比较,假如两个值相同,那就将1修改为2,如果在A线程修改之前,B线程进入把sum的值提前修改为0了,那么A线程在用预期值去与当前的sum值0比较,显然两个值不相等,此时的A线程就不会修改,会继续去读取sum的值,直到sum为 1 时才进行修改操作。

    每个线程预先分配一块TLAB区域,可以通过-XX:+ /-UseTLAB参数来设定

    TLAB这一块区域是在堆当中Eden(伊甸园)区中的,大概占整个Eden区的1%左右,很小的一块区域,堆为每一个线程单独分配一块TLAB,以此来保证多线程共享数据时是线程安全的。

    4、初始化分配到的空间(对属性初始化,零值初始化)

    这一过程说白了就是:所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用。基本数据类型默认初始化的值在文章下方表格里。

    5、设置对象的对象头

    将对象的所属类(即类的元数据信息)、对象的HashCode、对象的GC信息、锁信息等数据存储在对象头中。这个过程的具体设置方式取决于JVM实现。

    6、执行init方法进行初始化

    可以简单理解成调用构造函数进行显示的赋值,代码中和构造器中初始化。在Java程序的视角看来,初始化才正式开始,初始化成员变量,显示赋值,执行实例化代码块,调用类的构造器,并把堆内对象的首地址赋值给引用变量。

    一般来说(由字节码中是否跟随有invokspecial 指令所决定), new指令之后会接着就是执行方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全创建出来。

    扩展:还有一个clinit方法,这个方法是加载时对类中static静态修饰的属性和静态代码块进行初始化(此过程是在链接阶段的准备阶段)。这是JVM相关的知识了。

    二、对象头的内部结构

    1、创建了Customer()实例 和 Account()实例
    在这里插入图片描述
    一个对象的内存结构包括:运行时元数据、类型指针、实例数据、对齐填充


    2、对象头里包括(64位机器占96位)运行时元数据(Mark Word)(占64位)、类型指针(Klass Point)(占32位)

    (1) 运行时元数据里又包括:哈希值(HashCode)、GC分代年龄、锁状态标志

    哈希值:31位的对象标识hashCode,采用延迟加载技术。调用方法System.identityHashCode()计算,并会将结果写到该对象头中。它是一个地址,用于栈对堆空间中对象的引用指向,不然栈是无法找到堆中对象的;

    GC分代年龄(占4位):记录幸存者区对象被GC之后的年龄age,一般age为15(阈值为15的原因是因为age只有4位最大就可以将阈值设置15)之后下一次GC就会直接进入老年代,要是还没有等到年龄为15,幸存者区就满了怎么办,那就下一次GC就将大对象或者年龄大者直接进入老年代。

    锁状态标志:记录一些加锁的信息(我们都是使用加锁的话,在底层是锁的对象,而不是锁的代码,锁对象的话,那会改变什么信息来表示这个对象被改变了呢?也就是怎么才算加锁了呢?

    答案就是改变这个对象的对象头的锁信息来标识已经加锁,下一个线程来获取是获取不到的,底层是通过比对当前的线程的那个值与它所期望的值是否相同,这时候一直自旋直到与期望值相同,相同就获取到锁,反之则进入到阻塞队列等待,这个机制叫做CAS,比较并交换。)
    在这里插入图片描述
    那么怎样查看对象的对象头的信息呢 ?

    第一步:导入第三方依赖

        <dependency>
          <groupId>org.openjdk.jol</groupId>
          <artifactId>jol-core</artifactId>
          <version>0.11</version>
        </dependency>
    

    第二步:打印信息

    System.out.println(ClassLayout.parseInstance(o).toPrintable());
    

    打印结果:

    在这里插入图片描述
    其中VALUE分析:
    在这里插入图片描述

    另外:锁的状态有两位数的空间标识,这样就可以实现用较少的空间去存储更多的信息,
    0 表示不可偏向,1 表示可偏向

    标志位锁状态
    01未锁定
    00轻量级
    10重量级(膨胀)
    01可偏向
    11GC标记

    (2)类型指针:是对方法区中类元信息的引用

    3、实例数据:真实记录一个对象包含的数据,比如说一个person对象,里面可能包含年龄、性别、身高等等,其中数据为字符串的,要引用到字符串常量池。

    想知道jdk8字符串常量池到底在那个地方存储的可以看这里。

    4、对齐填充:填充部分仅起到占位符的作用, 原因是HotSpot要求对象起始地址必须是8字节的整数,假如不是,就采用对齐填充的方式将其补齐8字节整数倍,那么为什么是8呢?原因是64位机器能被8整除的效率是最高的。
    在这里插入图片描述
    另外这个过程还会涉及到逃逸分析。我写了一篇逃逸分析的具体作用,感兴趣可以看看。

    基本数据类型所占字节数默认值包装类名称
    byte1(1字节=8位)0Byte
    short20Short
    int40Integer
    long80LLong
    double80.0dDouble
    float40.0fFloat
    char2‘\u0000’Character
    boolean1falseBoolean

    怎样快速记住这些类型的方法,请看这里。

    有用点个关注,手留余香!😐 😐 😐

    展开全文
  • 怎样理解对象

    千次阅读 2018-08-01 11:28:59
    1、对象的英文单词是“Object”,它三个方面的意思: (1)目标,目的,宗旨 (2)物,物体,物件 (3)对象,客体,客观  仔细琢磨下这三个意思。首先它“目标”的意思,也就是说这是个实际的东西,我们可以...

    一、万事万物皆对象--理解对象模型
    对象实际上是看待事物的一种方式。它只是我们从现实世界中抽象出来的一种模型,但是这个模型还是有它的定义和概念的。

     

    1、对象的英文单词是“Object”,它有三个方面的意思:
    (1)目标,目的,宗旨
    (2)物,物体,物件
    (3)对象,客体,客观


        仔细琢磨下这三个意思。首先它有“目标”的意思,也就是说这是个实际的东西,我们可以对它做些操作,它是一些动作的受体。其次就是第二层意思,它是物体、物件,现实世界中的任何实际事物或称为“实体”的东西都可以叫作“Object”.第三层含义是哲学上的一个概念,比前两层含义都要抽象,这也是我们所取的“Object”的意思,它就是指一种客观事物的存在,如桌子、人、狗、鱼,蓝天,白云……

     


        对象是件“东西”,什么“东西”都可以称之为对象;你可以对一个对象施加作用(属性->特性),对象会发生一些事件(变化->方法)

     

    2、现实世界中一些具体的对象

        举个栗子,比如一台笔记本电脑,我们将它视为一个对象无非是为了能够更加抽象地描述它,这在编程的过程中很重要,来看看它有哪些需要抽象出来的特性吧~
        在生活中大家应该很熟悉,当你在买一台新的笔记本电脑时,主要考虑的是什么?———笔记本电脑的屏幕大小、屏幕形状、机身总重量、硬盘空间、CPU频率、操作系统……这些都是“笔记本电脑”这个对象所固有的一些性能或制造的参数,这些可以标识出这台笔记本电脑是否受到顾客的欢迎。
        但是,对于现实世界中的一台洗衣机,要考虑的特性就完全不是上面的那些参数和特性了,更多的是会去关注它的容积、耗电量、噪音大小等。还有,对于一架航天飞机,它要考虑的特性会更多,对于一支钢笔,一把伞,针对它们要考虑的就会相对要少一些……从这些例子来看,世间万物的复杂程度不同,我们对它们的关心方面就不同,相应地从它们这些具体事物中抽象出的对象也会各有差别。

     

    3、由现实世界中的事物抽象为对象


        来看看下面这张图,图中列出了3种类型的电脑,以及我们对3个“对象”所关注的特性。相对而言,对于台式机更注重性能,不会关心它的重量,因为它不是为了方便移动而设计的。而对于平板电脑呢,相比较台式电脑而言,没有那么关心它的性能,而是看它是否方便携带及电池的续航能力。而笔记本电脑,考虑因素就处于这两者之间。
        这个例子,向大家说明了如何将现实世界中的各种事物抽象为一个个对象。做法很简单,只要它是一个独立的事物,找出所关注的那几个方面的特性,把这些特性提取出来,就得到了一个抽象之后的“对象”。

     

     

    4、对象之间的差别--事物的属性
        (1)何为对象的属性?
      只知道什么是对象还不行,世界上有无穷多种事物,它们各有特点,互不相同。必须有个办法将我们抽象出的对象互相区分出来才行,这样才能够真实地对现实世界中的事物进行合理的建模与抽象。这个用于区分各个对象特征的部分就称为属性,不同的对象具有不同的属性,借属性这个概念来使各个对象能够得以区分。


        (2)不同对象的属性值不同
        举个例子,如果发现两个笔记本电脑对象的屏幕尺寸大小不同,则它们必然不是同一个对象。
        


        (3)不同对象具有不同的属性
        举个例子,笔记本电脑和平板电脑,其中屏幕大小是两者都有的一个共同属性。它们也具有不同的属性,笔记本电脑的键盘属性,平板电脑的触摸板的属性,等等。

     

        (4)属性与对象间的关系
        举个例子,三角形与正方形都有一个共同的属性--边长。圆形是不具有边长的,只有名称为“直径”的属性。三角形与正方形虽然都具有“边长”,但边长的值并不相同,另外,我们也知道三角形与正方形,边长对它们的一些其他的特性,如周长、面积等的含义是不同的。这些均代表了不同的对象之间属性的关系,可能具有不同的属性或者不同的属性值。

     


      

     

    5、对象与属性的关系
        对于任何一个属性都具有三个方面:属性所属的对象、属性名称、属性的值。只有这三个方面都是相同的,才能判定这两个属性实际上属于同一个。比如,两台笔记本电脑的屏幕大小都是14寸,这才说明“屏幕大小”这个属性是属于同一个。

     


    二、万物皆有变化——对象的方法
    对象是由现实中的事物抽象而来的。我们知道世界上亘古不变的事物几乎是没有的。世间万物都处在不断变化中,当所要关注的对象发生变化时,就必须要有一种相应的办法来描述并反映对象的这个变化的过程和想象。

     

    1、对象的方法定义
        属性只是固定的、没有变化的对象特征而已。但现实世界中的事物都处在不断发展变化中,必须有某种方式来描述这种变化。所以就有了“方法”,它所描述的是对象可以发起的动作,或者是对象可以做的事情等。
       (1)什么是方法?
        举个例子,将一只猫抽象为一个对象——Cat。对于这个对象,我们现在只关注它所拥有的其中一个属性——体重(Weight)。猫能吃老鼠,这样Cat对象就会有一个方法——EatMouse().用这个方法表示猫吃老鼠这个变化过程,在这个过程的前后猫的体重会有所变化。反映到我们抽象后的对象中,就是这个事实,Cat在执行EatMouse()这个方法之后,属性Weight的值发生了变化,这就是对象的变化——方法。
        事实上,方法的定义是这样说的:它是相应的对象可以做的、但不一定会真正去做的事情。从这个定义上来看,上面的EatMouse()方法是为Cat对象所有的,如果在定义一个对象——狗(Dog),那么它就不可以拥有EatMouse()方法。

     

    2、方法与对象间的关系

        不同的对象所拥有的方法可能不一样,但方法并不是一个对象所专属的事情。

        如下图:

     

     

     

     

     

     

     

    展开全文
  • Java引用对象

    万次阅读 2018-12-11 10:09:03
    简介 在写了15年C/C++之后,我于1999年开始写Java。借助指针切换(pointer handoffs)等编码实践或者Purify等工具,我认为...在我不需要再管理内存后我意识到之前耗费了多少精力。 接着我就遇到了第一个OutOfMemor...
  • 今天看别人的博客,讲到面试相关的问题,其中一个知识点是:synchronized关键字,Java对象头、Markword概念、synchronized底层实现,monitorenter和monitorexit指令,一脸蒙逼,虽然早期把《深入理解Java虚拟机》...
  • JAVA 面向对象对象 封装

    万次阅读 多人点赞 2021-05-06 15:58:57
    面向对象概念 面向对象其实是一种编程思想,通过它可以把生活中复杂的事情变得简单化,从原来的执行者变成了指挥者。 面向对象是基于面向过程而言的。 面向过程强调的是过程,比如: 打开冰箱门 2. 把大象放进去 3. ...
  • 文章目录1、什么是垃圾回收2、如何定义垃圾2.1 引用计数算法2.2 可达性分析算法2.3 Java内存区域3、怎么回收垃圾3.1 标记清除算法3.2 复制算法3.3 标记整理算法3.4 分代收集算法4、内存模型与回收策略5、微信关注...
  • 详解Java的对象创建

    千次阅读 2021-02-26 12:03:30
    1. 前言在《还不清楚怎样面向对象?》和《面向对象再探究》两篇文章中,都介绍了关于面向对象程序设计的概念和特点。其中也涉及到了许多代码,比如:Dog dog = new Dog();这篇文章就主要来谈谈创建对象时的具体操作...
  • 对象可以是一个实体、一个名词、一个可以想象为自己标识的任何东西,可以概括来说:万物皆对象。 什么是类? 类(Class)是Java代码的基本组织模块,使用来描述一组具有共同属性和行为对象的基本原型。是对这组...
  • new一个对象的背后,竟然这么多可以说的

    千次阅读 多人点赞 2021-09-14 21:29:52
    那么GirlFriend对象到底是怎么产生的呢? 一、类加载 当遇到new指令时,jvm首先去常量池寻找该类的符号应用,找不到,则执行类加载。 以下是类加载各个阶段的主要任务,现在记不住也没有什么关系。 1. 装载 ...
  • 哈希值:它是一个地址,用于栈对堆空间中对象的引用指向,不然栈是无法找到堆中对象的 GC分代年龄:记录幸存者区对象被GC之后的年龄age,,一般age为15之后下一次GC就会直接进入老年代 锁状态标志:记录一些加锁的...
  • 什么是对象存储

    千次阅读 2021-01-28 09:59:59
    对象存储概述 什么是对象存储(OSD)? 存储局域网(SAN)和网络附加存储(NAS)是目前两种主流网络存储架构,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备...
  • 对象的哈希值

    千次阅读 2021-02-27 21:33:13
    ## 概述任何对象,都一个哈希值,这个哈希值是对象的一个整数数字表示. 对象的字符串表示是toString()方法.## 如何获取对象的哈希值每一个对象一个方法,hashCode(),这个方法定义在了Object类中,所以每个对象都...
  • 在java中new一个对象的流程是怎样

    千次阅读 2021-04-19 19:46:58
    对象怎么创建,这个太熟悉了,new一下(其实还有很多途径,比如反射、反序列化、clone等,这里拿最简单的new来讲): Dog dog = new Dog(); 我们总是习惯于固定语句的执行,却对于背后的实现过程缺乏认知,而理解这个...
  • 详解Python中的可哈希对象与不可哈希对象(二)

    千次阅读 多人点赞 2019-10-30 16:49:52
    前言:我们经常会听见很多的概念,哈希值,哈希表,可哈希对象,不可哈希对象,散列表,字典,映射,等等,那么这么多的概念后面到底又什么区别和联系,它们的本质又是怎么样的,本此系列文章将针对这些概念进行...
  • 创建对象的方式

    千次阅读 2021-03-12 00:11:28
    获得对象的方式 先定义一个Programmer类: package com.zrt.pojo; public class Programmer { private int id; private String name; private int age = 18; public Programmer(){ } public Programmer...
  • java对象的销毁详解

    千次阅读 2021-03-01 07:52:24
    对象使用完之后需要对其进行清除,下面的文章内容就对这个方面的知识进行了较为详细的介绍,一起来看看这个方面的知识吧。前面讲到了清除,对象的清除指的就是释放对象占用的内存。在创建对象的时候,用户必须使用...
  • 【java】今天你 new “对象”吗

    千次阅读 多人点赞 2022-03-30 22:33:01
    在java中,什么是类‍️?对象又是什么?类和对象有那些不可名状的关系
  • 最近被问到了C++内存池的问题,其中不免涉及到在指定内存地址调用对象构造函数以及显示调用对象析构函数的情况。</p> C++中new的用法 new是C++中用于动态内存分配的运算符,在C语言中一般使用malloc函数。 ...
  • Java DataSource对象

    千次阅读 2020-11-29 09:41:34
    连接数据源对象 本节介绍DataSource对象,这是获得与数据源的连接的首选方法。除了它们的其他优点(将在后面解释)之外,DataSource对象还可以提供连接池和分布式事务。此功能对于企业数据库计算至关重要。特别是...
  • java面向对象简介

    千次阅读 多人点赞 2021-11-06 13:59:14
    Java 中的每个类都构造方法,用来初始化该类的一个对象。 构造方法具有和类名相同的名称,而且不返回任何数据类型。 重载经常用于构造方法。 构造方法只能由new运算符调用 5、注释 Java中的注释就是解释说明你的...
  • 早期方法的不足: 早期的方法只使用一种系统的视角作为构造块,而没有容纳其他视角。 1、结构化分析和设计方法集中于将功能作为系统的构造块...为了克服传统开发方法的不足,面向对象方法解决问题的思路 是从现实世...
  • C++对象计数

    千次阅读 2019-01-26 12:25:33
    例如,你一个Widget类,你想知道一共在运行时一共创建了多少个Widget对象。一个简单可行的方法是在Widget内部创建一个static counter,当对象创建时增加计数器的值,当对象销毁时减少计数器的值。同时,也要创建一...
  • object如何强转为对象

    千次阅读 2021-04-17 05:07:43
    如何将一个object 对象转换为他原来的类型生命中许多你不想做却不能不做的事,这就是责任;...反射没用过,现在已经能获取对象类型和属性了,分享教该怎么还原为原来的类型呢。java 可以将Object 转...
  • 面向对象思想————不看后悔!... 前言: 整理这份资料的目的是为了帮助朋友们能够...但其中不免许多漏洞及错误,也还请前辈提出宝贵的更改意见,毕竟交流会让我们不断的进步。 技术是日新月异的,他不会等待你的成长。
  • 判断对象为垃圾对象的方法为:引用计数法和可达性分析法。 Object object = new Object(); // 不是垃圾对象 object = null; // 此时为垃圾对象 System.gc(); // 提示给gc进行回收垃圾,只是提示而已,不代表立即...
  • JVM成神之路-Java对象模型

    千次阅读 2018-07-23 15:01:17
    在jvm的内存结构中,对象保存在堆中,而我们在对对象进行操作时,其实操作的是对象的引用。 Java对象包含三个部分 一个Java对象可以分为三部分存储在内存中,分别是:对象头(Header)、实例数据(Instance Data)和...
  • 面向对象程序设计

    千次阅读 2020-12-09 15:37:28
    之前复习面向对象的时候整理的,丢出来一起分享一下。因为复习得很赶,只是大致的整理,且大部分图片来自老师的ppt,可能不是很准确。如果要详细了解其中的某个知识点请另外搜索。 但是老师不讲武德啊,明明提纲给了...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 363,813
精华内容 145,525
关键字:

怎样才有对象