Java-Day-6(类与对象)

发布时间 2023-04-08 00:16:54作者: 朱呀朱~

Java-Day-6

类与对象

Java 最大特点:面向对象 ( OOP )

  • 类是抽象的、概念的,代表一类事物,即是种数据类型

    对象是具体的,实际的,代表一个具体事物,即是实例

  • 类是对象的模板 ( class XX { ... } )

    对象是类的一个个体,对应一个实例 ( XX xx = new XX() )

  • 创建对象

    • 直接创建

    • 先声明再创建 ( 声明时在栈里指向为 null 的空值的空间,直到 new 后再于堆里开出一个地址空间,把地址填回栈后指向堆里开出的地址空间 )

      • 只声明的话输出会报错

      • 创建一个对象 = 实例化一个对象 = 把类实例化

      • 若是 Person p2 = p1 则同数组一样是指向了同地址,一改全改

  • 在 jvm 的内存里 ( 主要:栈,堆,方法区 ),对象的存在形式

    • class Person{
          int 属性1;
          String 属性2;
      }
      
      //main 里
      //类模板 对象名 = new 类模板() —— 完成对象的创建
      Person p1 = new Person();
      // p1 —— 对象名,也叫对象引用
      // new Person() —— 创建出对象空间,才是真正的对象
      // 注:运行时是先右后赋回左
      
    • 在 new 创建一个对象时,会先把类的信息加载到方法区里 ( 相当于模板,只会加载一次 ),内含属性信息和行为 ( 方法信息 )

    • 因为new了,在堆里面就有一个地址空间,空间会根据类的内含属性分配应有大小 ( 真正的对象空间 ),若未赋值就是默认初始化

    • 对象和数组都是引用类型,所以自定义的对象名在栈里是一个地址,此地址是堆赋给的一个指向着堆对象的地址

    • 根据实际情况进行指定初始化

    • 若是定义的属性是 String ( 引用类型 ),则在堆里的一个空间里存放的仍是一个地址,此地址指向方法区的常量池里,在常量池被指向的地址里存放 String 型的具体数值

  • 类里面的属性

    • 也叫做成员变量,也有叫做 field ( 字段 ),其是类的一个组成部分

    • 属性可以是基本数据类型,也可以是引用类型 ( 另一对象或数组 )

    • 属性定义:访问修饰符 属性类型 属性名

    • 访问修饰符 ( 学包的时候再具体介绍 )是控制属性的访问范围:public,protected,默认,private

    • 属性如果不赋值,默认值规则同数组一致

  • 类里面的方法

    • public 返回数据类型 方法名 ( 形参列表... )
    class Person{
         
    // public:方法公开,void:该方法无返回值,speak:方法名,():形参列表,{}:方法体,写要执行的代码
        public void speak(){
            System.out.print("类中的一个方法")
        }
    }
    
    • 在 jvm 的内存中,类的方法的调用机制

      • 在栈里创建一个小的main栈,在其中 Person p1 = new Person()开辟堆空间
      • 调用p1的方法时,会在栈里再开一个新栈,一个独立空间,若是方法的形参列表里有数据,就要把数复制到独立空间里,变量与值一一对应,在其内完成方法的运行
      • 方法非 void 的话,就会 return 返回给 p1 的方法被调用的地方,完成赋值,继续执行后面的代码,主方法 main 栈执行完成后,main 栈退出,整个程序退出
    • 提高了代码的复用性

      可以将实现细节进行封装,便于他人调用

    • 一个方法只能有一个返回值,若想返回多个结果就借用数组存多个数据进行返回

      public int[] getperson(...){ int[] resArr = new int[要返回的个数]; ...... }
      
    • 返回类型可以为任意类型,包含基本类型或引用类型 ( 数组,对象 )

    • 如果要求有返回值,则返回值类型必须和 return 的值类型一致或兼容

    • 若是 void,则方法体中没有 return 或只写 “ return ;”,不带值

    • 方法体里写完成功能的具体语句,不能再定义方法,即方法不能嵌套定义。

    • 方法的调用

      • 同一个类的方法可以相互直接调用

        class A{
            public void printaa(...){ ... }
            public void printbb(){ printaa(...); ... }
        }
        
      • 跨类的方法想调用得通过对象名来调用

        //另一个class里:
        A a = new A();
        a.printaa(...);
        
      • 跨类的方法调用还与后面学到的包的修饰符也是有关联的

  • 易错:

    • 若是设定一个方法交换 a、b 值,则是把 main 里的 a、b 值拷贝到了开辟的独立空间的栈里进行了交换,main 函数里的 a 和 b 没有变化

      • ——> 基本数据类型,传递的是值 ( 值拷贝 ),形参的任何改变不影响实参
    • 但若是传递数组 ( 或对象 ),则在开辟的独立空间栈里的数组也是指向着堆里的 main 数组地址,改变的是地址里的值,会影响到 main

      • ——> 引用类型传递的是地址,所以可以通过形参影响实参
    • 若是传递一个对象,在方法里把该对象再赋为 null ( 或是再 new ),就是从指向堆的地址变成空 ( 指向新的堆里的地址 ),并不会改变原 main 对象