Java 面向对象

前言

  • 面向对象的基本概念。

1、类和对象

1.1 final

  • final:修饰 类、方法、基本类型变量、引用 的时候分别有不同的意思。
修饰类型 说明
该类不能够被继承
方法 该方法不能够被重写
基本类型变量 该变量只有一次赋值机会
引用 该引用只有 1 次指向对象的机会
常量 常量指的是可以公开,直接访问,不会变化的值

1.2 this

  • this:代表当前对象。

1.3 super

  • super:父类。

  • 实例化子类,父类的构造方法一定会被调用,并且是父类构造方法先调用,子类构造方法会默认调用父类的无参的构造方法。

    1
    2
    3
    4
    public ADHero(String name) {
    super(name); // 子类显式调用父类带参构造方法
    System.out.println("AD Hero 的构造方法");
    }
  • 调用父类属性。

  • 调用父类方法。

1.4 Object 类

  • Object 类:是所有类的父类。声明一个类的时候,默认是继承了 Object
关键字 说明
toString 返回当前对象的字符串表达
finalize 垃圾回收的时候调用,是由虚拟机 JVM 调用的,一旦一个对象被回收,它的 finalize() 方法就会被调用
equals 判断两个对象的内容是否相同
== 判断两个对象是否相同,更准确的讲,用于判断两个引用,是否指向了同一个对象
hashCode 返回一个对象的哈希值
getClass 返回一个对象的类对象
wait、notify、notifyAll 线程同步相关方法

1.5 抽象类

  • 抽象类:在类中声明一个方法,这个方法没有实现体,是一个 “空” 方法,这样的方法就叫抽象方法,使用修饰符 abstract,当一个类有抽象方法的时候,该类必须被声明为抽象类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package charactor;

    public abstract class Hero {

    String name;
    float hp;
    float armor;
    int moveSpeed;

    public abstract void attack(); // 抽象方法 attack,Hero 的子类会被要求实现 attack 方法
    }
  • 抽象类可以没有抽象方法,一旦一个类被声明为抽象类,就不能够被直接实例化。

  • 抽象类和接口的区别与相同

    • 区别 1:

      • 子类只能继承一个抽象类,不能继承多个
      • 子类可以实现多个接口
    • 区别 2:

      • 抽象类可以定义
        • public, protected, package, private
        • 静态和非静态属性
        • final 和非 final 属性
      • 但是接口中声明的属性,只能是
        • public
        • 静态
        • final 的
      • 即便没有显式的声明
    • 相同:

      • 抽象类和接口都可以有实体方法。

1.6 内部类

  • 内部类

    • 非静态内部类:可以直接在一个类里面定义,只有一个外部类对象存在的时候,才有意义。可以直接访问外部类的实例属性和方法。new 外部类().new 内部类();
    • 静态内部类:在一个类里面声明一个静态内部类,不需要一个外部类的实例为基础,可以直接实例化。不可以访问外部类的实例属性和方法。new 外部类.静态内部类();
    • 匿名类:指的是在声明一个类的同时实例化它,既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。这样的类,叫做匿名类。
    • 本地类:可以理解为有名字的匿名类。内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
  • 在匿名类中使用外部的局部变量,外部的局部变量必须修饰为 final。在 jdk8 中,已经不需要强制修饰成 final 了,如果没有写 final,不会报错,因为编译器偷偷的帮你加上了看不见的 final

1.7 对象转型

  • 对象转型:指当引用类型和对象类型不一致的时候,才需要进行类型转换。类型转换有时候会成功,有时候会失败。

  • 通常情况下,引用类型和对象类型是一样的。

    • 引用类型
    • 对象类型
  • 转换方式

    • 子类转父类 (向上转型) :所有的子类转换为父类,都是说得通的。说得通,就可以转。
    • 父类转子类 (向下转型) :有的时候行,有的时候不行,所以必须进行强制转换。
    • 没有继承关系的两个类,互相转换 :一定会失败。
    • 实现类转换成接口 (向上转型) :转换是能成功的。
    • 接口转换成实现类 (向下转型) :转换会失败。
  • instanceof:判断一个引用所指向的对象。

    1
    2
    // 判断引用 h1 指向的对象,是否是 ADHero 类型
    System.out.println(h1 instanceof ADHero);

1.8 UML 图

  • UML 图:Unified Module Language,统一建模语言,可以很方便的用于描述类的属性,方法,以及类和类之间的关系。

2、属性

  • Java 类的属性

    • 类属性:当一个属性被 static 修饰的时候,就叫做类属性,又叫做静态属性。当一个属性被声明成类属性,那么所有的对象,都共享一个值。
    • 对象属性:又叫实例属性,非静态属性。不同对象的 对象属性 的值都可能不一样。

2.1 属性初始化

  • 属性初始化

  • 对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)> 构造器。

3、方法

  • Java 类的方法

    • 类方法:又叫做静态方法。被 static 修饰的方法。
    • 对象方法:又叫实例方法,非静态方法。

3.1 构造方法

  • 构造方法:方法名和类名一样(包括大小写),没有返回类型,实例化一个对象的时候,必然调用构造方法。

  • 无参的构造方法,如果不写,就会默认提供一个。

  • 一旦提供了一个有参的构造方法,同时又没有显式的提供一个无参的构造方法,默认的无参的构造方法就失效了。

3.2 方法重载

  • 方法重载:指的是方法名一样,但是参数不一样。

  • 可变数量的参数

    1
    2
    3
    4
    5
    6
    // 可变数量的参数
    public void attack(Hero... heros) {
    for (int i = 0; i < heros.length; i++) {
    System.out.println(name + " 攻击了 " + heros[i].name);
    }
    }

3.3 方法重写(覆盖)

  • 方法重写:子类可以继承父类的 对象方法,在继承后,重复提供该方法,就叫做方法的重写,又叫覆盖 override

3.4 方法隐藏

  • 方法隐藏:与重写类似,就是子类覆盖父类的 类方法。

3.5 传参

  • 传参

  • 基本类型传参:赋值,在方法内,无法修改方法外的基本类型参数。

  • 类类型传参:引用,类类型又叫引用。

4、引用

  • 引用:如果一个变量的类型是 类类型,而非基本类型,那么该变量又叫做引用。

  • 一个引用,同一时间,只能指向一个对象。

5、继承

  • 继承

    1
    2
    3
    4
    // Weapon 继承自 Item
    public class Weapon extends Item {

    }

6、多态

  • 多态:同一个类型,调用同一个方法,却能呈现不同的状态。

  • 操作符的多态:同一个操作符在不同情境下,具备不同的作用。

    • + 可以作为算数运算,也可以作为字符串连接。
  • 类的多态 条件

    • 父类(接口)引用指向子类对象。
    • 调用的方法有重写。

7、访问修饰符

修饰符 说明
private 私有的
package/friendly/default 不写,没有修饰符即代表 package/friendly/default
protected 受保护的
public 公共的
  • 作用域
修饰符 自身 同包子类 不同包子类 同包类 其他类
private 访问 不能继承 不能继承 不能访问 不能访问
package 访问 继承 不能继承 访问 不能访问
protected 访问 继承 继承 访问 不能访问
public 访问 继承 继承 访问 访问
  • 修饰符的使用

    • 属性通常使用 private 封装起来。
    • 方法一般使用 public 用于被调用。
    • 会被子类继承的方法,通常使用 protected
    • package 用的不多,一般新手会用 package,因为还不知道有修饰符这个东西。
  • 作用范围最小原则

    • 简单说,能用 private 就用 private,不行就放大一级,用 package,再不行就用 protected,最后用 public。 这样就能把数据尽量的封装起来,没有必要露出来的,就不用露出来了。

8、包

  • :package,把比较接近的类,规划在同一个包下。

  • 使用同一个包下的其他类,直接使用即可。但是要使用其他包下的类,必须 import 包名.类名

  • 在最开始的地方声明该类所处于的包名。

    1
    2
    3
    4
    5
    6
    package charactor;          // 在最开始的地方声明该类所处于的包名

    import property.Weapon; // Weapon 类在其他包里,使用必须进行 import

    public class Hero {
    }

9、接口

  • 接口:接口就像是一种约定。

  • 定义接口

    1
    2
    3
    4
    5
    6
    package charactor;

    public interface AD {

    public void physicAttack(); // 声明一个方法,但是没有方法体,是一个 “空” 方法
    }
  • 实现接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package charactor;

    public class ADHero extends Hero implements AD { // 实现在语法上使用关键字 implements

    @Override // 实现某个接口,就相当于承诺了某种约定
    public void physicAttack() { // 实现了 AD 这个接口,就必须提供 AD 接口中声明的方法
    System.out.println("进行物理攻击");
    }

    }

9.1 默认方法

  • 默认方法:JDK8 新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法,这个方法有实现体,并且被声明为了 default

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package charactor;

    public interface Mortal {
    public void die();

    default public void revive() {
    System.out.println("本英雄复活了");
    }
    }

10、单例模式

  • 单例模式:又叫做 Singleton 模式,指的是一个类,在一个 JVM(Java 虚拟机)里,只有一个实例存在。

  • 三元素

    • 构造方法私有化。
    • 静态属性指向实例。
    • public staticgetInstance 方法,返回第二步的静态属性。

10.1 饿汉式单例模式

  • 通过私有化其构造方法,使得外部无法通过 new 得到新的实例。提供了一个 public staticgetInstance 方法,外部调用者通过该方法获取定义的对象,而且每一次都是获取同一个对象。从而达到单例的目的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package charactor;

    public class GiantDragon {

    private GiantDragon() { // 私有化构造方法使得该类无法在外部通过 new 进行实例化
    }

    private static GiantDragon instance = new GiantDragon(); // 准备一个类属性,指向一个实例化对象。因为是类属性,所以只有一个

    public static GiantDragon getInstance() { // public static 方法,提供给调用者获取定义的对象
    return instance;
    }
    }
    1
    GiantDragon g1 = GiantDragon.getInstance();

10.2 懒汉式单例模式

  • 懒汉式 单例模式与 饿汉式 单例模式不同,只有在调用 getInstance 的时候,才会创建实例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package charactor;

    public class GiantDragon {

    private GiantDragon() { // 私有化构造方法使得该类无法在外部通过 new 进行实例化
    }

    private static GiantDragon instance; // 准备一个类属性,用于指向一个实例化对象,但是暂时指向 null

    public static GiantDragon getInstance() { // public static 方法,返回实例对象
    if (null == instance) { // 第一次访问的时候,发现 instance 没有指向任何对象,这时实例化一个对象
    instance = new GiantDragon();
    }
    return instance; // 返回 instance 指向的对象
    }
    }
    1
    GiantDragon g1 = GiantDragon.getInstance();

10.3 使用方式

  • 饿汉式 是立即加载的方式,无论是否会用到这个对象,都会加载。如果在构造方法里写了性能消耗较大,占时较久的代码,比如建立与数据库的连接,那么就会在启动的时候感觉稍微有些卡顿。

  • 懒汉式 是延迟加载的方式,只有使用的时候才会加载。 并且有线程安全的考量。使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。

  • 看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式

文章目录
  1. 1. 前言
  2. 2. 1、类和对象
    1. 2.1. 1.1 final
    2. 2.2. 1.2 this
    3. 2.3. 1.3 super
    4. 2.4. 1.4 Object 类
    5. 2.5. 1.5 抽象类
    6. 2.6. 1.6 内部类
    7. 2.7. 1.7 对象转型
    8. 2.8. 1.8 UML 图
  3. 3. 2、属性
    1. 3.1. 2.1 属性初始化
  4. 4. 3、方法
    1. 4.1. 3.1 构造方法
    2. 4.2. 3.2 方法重载
    3. 4.3. 3.3 方法重写(覆盖)
    4. 4.4. 3.4 方法隐藏
    5. 4.5. 3.5 传参
  5. 5. 4、引用
  6. 6. 5、继承
  7. 7. 6、多态
  8. 8. 7、访问修饰符
  9. 9. 8、包
  10. 10. 9、接口
    1. 10.1. 9.1 默认方法
  11. 11. 10、单例模式
    1. 11.1. 10.1 饿汉式单例模式
    2. 11.2. 10.2 懒汉式单例模式
    3. 11.3. 10.3 使用方式
隐藏目录