Stay Curious, Stay Naive.
首页 归档 标签 关于

java 中面向对象的概念

关于java比较全面的面向对象概念

构造代码块有什么用?

如果所有的构造方法在最开始的时候有相同的一部分代码,不妨将这个公共的代码提取到构造代码块当中,这样代码可以得到复用

public class Student {
    {
        for(int = 0; i< 10; i++);
        System.out.println("i = " + i);
    }
    
    public Student() {
        System.out.println("Student类的无参构造方法执行了")
    }
    
    
}
public class ConstructorTest {
    public static void main(String[] args) {
        new Student();
        new Student("张三");
    }
}

初识 this

this 本质上是一个引用,this 中保存的也是对象的内存地址

this 中保存的也是对象的内存地址

this 中保存的是当前对象的内存地址

this.是可以省略的. 默认访问的就是当前对象的name

this 存储在: 栈帧的局部变量表的第0个槽位上.

this 大部分情况下可以省略,用于区分局部变量和实例变量时不能省略.

this 不能出现在静态方法中.

​ - this 代表的是当前对象,static的方法中没有当前对象,所以static的方法中不能使用this

this(实参) 语法:

​ 1.只能出现在构造方法的第一行

​ 2.通过当前构造方法去调用本类中其他的构造方法.

​ 3.作用: 代码复用

	实例变量
    局部变量
    静态变量
    
    静态代码块 :特殊时间点(类加载时刻)
    初始化代码块

static 关键字

  1. static 修饰的变量:静态变量

  2. static 修饰的方法:静态方法

  3. 所有static修饰的,访问的时候,直接采用 "类名",不需要 new 对象

  4. 什么情况下把成员变量定义为静态成员变量?

    • 当一个属性是对象级别的,这个属性通常定义为实例变量. (实例变量是一个对象一份,100个对象就应该有 100 个空间).
    • 当一个属性是类级别的 (所有属性都有这个属性,并且这个属性的值是一样的),建议将其定义为静态变量,在内存空间上只有一份. 节省内存开销. 这种类级别的属性,不需要 new 对象,直接通过类名访问.
  5. 静态变量存储在哪里? 静态变量什么时候初始化? (= 什么时候开辟空间?)

    ​ 答: JDK8之后: 静态变量存储在堆空间中. 类加载时初始化.

  6. 静态变量可以采用引用访问,(但不建议,会给程序员造成困惑,程序员会认为 country 是一个实例变量).

  7. 静态方法中不能使用 this 关键字,因此无法直接访问实例变量和调用实例方法.

  8. 静态代码块在类加载时执行,一个类中可以编写多个静态代码块,遵循自上而下的顺序依次执行.

  9. 静态代码块代表了类加载时刻,如何你有代码需要在此刻执行,可以将该代码放到静态代码块中.

  10. 使用引用.访问静态相关的即使引用为null,也不会出现空指针异常.

image-20240926151021563

在同一个类中,类名. 是可以省略的.

成员方法只能通过 实例变量和实例方法才可以调用

静态代码块: 为程序员预留的特殊的时间点:类加载时刻

如果你需要在类加载时刻执行一段程序的话,这段代码就可以写到静态代码块当中

例如: 有这样一个需求,请在类加载时,记录日志.那么记录日志的代码就可以编写到静态代码块当中.

继承

继承作用:

  • 基本作用: 代码复用
  • 重要作用: 有了继承,才有了方法覆盖和多态机制

extends 翻译为 扩展, 表示子类继承父类后,子类是对父类的扩展

继承相关的术语:

  • 父类 --- > superclass
  • 子类 --- > subclass

java只支持单继承,一个类只能继承一个类.

java不支持多继承,但支持多层继承, 子类继承父类,除私有的,构造方法不支持继承,其他的全部会继承.

一个类没有显示继承任何类,默认会继承 java.lang.Object类

方法覆盖/ 重写 /

  1. 什么情况下考虑使用 方法覆盖?
    1. 当从父类中继承过来的方法无法满足当前子类的业务需求时.
  2. 发生方法覆盖的条件?
    1. 具有继承关系的父子类之间
    2. 相同的返回值类型,相同的方法名,相同的形式参数列表
    3. 访问权限不能变低,可以变高
    4. 抛出异常不能变多,可以变少
    5. 返回值类型可以是父类方法返回值类型的子类
  3. 方法覆盖的小细节
    1. @override注解标注会在编译阶段检查该方法是否重写了父类的方法.
    2. 私有方法不能继承,所以不能覆盖.
    3. 构造方法不能继承,所以不能覆盖.
    4. 静态方法不存在方法覆盖,方法覆盖针对的是实例方法.
    5. 方法覆盖说的实例方法,和实例变量无关. 因为 方法覆盖和多态才有意义.
// 方法覆盖说的实例方法,和实例变量无关.
// 实例变量不存在覆盖这一说, a.name 编译阶段绑定的是 A类的 name属性,运行的时候也会输出A类的name属性值

public class Test2 {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.name);
    }
}

class A {
    // 实例变量
    String name = "张三";
}

class B extends A {
    // 实例变量
    String name = "李四";
}

多态

  1. 什么是向上转型和向下转型?

    1. java允许具有继承关系的父子类型之间的类型转换

    2. 向上转型: 子 ---> 父

      • 子类型的对象可以赋值给一个父类型的引用
    3. 向下转型: 父 ---> 子

      • 父类型的引用可以转换为子类型的引用.但是需要加强制类型转换符.
    4. 无论是向上转型还是向下转型?

      ​ 前提条件是: 两种类型之间必须存在继承关系. 这样编译器才能通过.

    image-20240926224531760
  2. 什么是多态?

    1. 父类型引用指向子类对象:

      Animal a = new Cat(); a.move()

    2. 程序分为编译阶段和运行阶段:

      1. 编译阶段: 编译器只知道a 是 Animal 类型,因此去 Animal 类中找 move() 方法,找到之后,绑定成功.编译通过,这个过程称为 静态绑定.
      2. 运行阶段: 运行时和 jvm 堆内存中的真实 java 对象有关, 所以运行时会自动调用真实对象的move() 方法. 这个过程通常被称为动态绑定.
    3. 多态指的是: 多种形态, 编译阶段 一种形态, 运行阶段 一种形态, 因此称为多态.

  3. 向下转型我们需要注意什么?

    1. 向下转型时,使用不当,容易发生类型转换异常: ClassCastException
    2. 在向下转型时,一般建议使用 instanceof 运算符进行判断来避免 ClassCaseException 的发生.
  4. instanceof 运算符的使用

    1. 语法格式: (引用 instanceof 类型)
    2. 执行结果为 true或者 false
    3. 例如 (a instanceof cat)
      1. 如果结果为 true 表示 a 引用指向的对象是 Cat 类型
      2. 如果结果为 false 表示 a 引用指向的对象不是 Cat 类型

抽象类

创建一个名为 Person 的类,在其中定义方法 greet(),用于问候对方. 在此基础上,创建一个名为 EnglishPerson的子类和名为 ChinesePeron的子类
分别复写 greet() 方法, 分别使用英文和中文问候对方. 在main方法中 创建一个名为person的数组,添加一个 EnglishPerson对象和一个 ChinesePerson对象
使用greet() 方法问候对方.
public abstract class Person {

    public Person() {
    }

    private String name;

    public Person(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void greet(); // 抽象方法
}
class ChinesePerson extends Person{
    @Override
    public void greet() {
        System.out.println("你好呀,我的名字是 " + this.getName() + " 我很好!");
    }
}

public class EnglishPerson extends Person{
    @Override
    public void greet() {
        System.out.println("Hello, My name is " + this.getName() + " How are you ?");
    }
}

public class Test {
    public static void main(String[] args) {

        Person englishPerson = new EnglishPerson();
        englishPerson.setName("Frank");
        englishPerson.greet();

        System.out.println("---------------------");

        Person chinesePerson = new ChinesePerson();
        chinesePerson.setName("吴彦祖");
        chinesePerson.greet();
        
    }
}

Super 关键字

  1. super 关键字 和 this 关键字 对比来学习. this代表的是当前对象, super 代表的当前对象中的父类型特征.
  2. super 不能使用在静态上下文中.
  3. super 大部分情况下是可以省略的. 什么时候不能省略?
    1. 当父类和子类中定义了相同的属性 (实例变量) 或者 (实例方法)时, 如果需要在子类中访问父类的属性或方法时, super不能省略.
  4. this 可以单独输出, super 不能单独输出.
  5. super(实参);通过子类的构造方法调用父类的构造方法,目的是为了完成父类型特征的初始化.
  6. 当一个构造方法第一行没有显示的调用 super(实参), 也没有显示的调用 this(实参),系统会自动调用 super(). 因此一个类中的无参构造方法建议使用显示的定义出来.
image-20240929184018775