Java 面向对象

面向对象三大特征

1.封装

隐藏对象的属性和实现细节,仅对外提供公共访问方式。隐藏代码的实现细节,提高安全性。

2.继承

体现在代码开发中,让代码具有层次结构。继承的主要特点是父类与子类的关系,子类可以继承父类的一些特性,如方法和变量。

3.多态

主要体现在 Java 的重载与重写上。

访问控制权限

修饰词 本类 同一个包的类 子类 任何地方
private × × ×
default (默认) × ×
protected ×
public

重写

在父类中方法无法满足子类需求时,子类可以将父类的方法进行重写来满足需求。

方法重写条件:

  • 两个类必须是继承关系。
  • 必须具有相同的方法名,相同的返回值类型,相同的参数列表。
  • 子类的访问权限必须大于等于父类方法。
  • 子类方法的返回类型必须是父类方法返回类型或为其子类型。

私有方法、静态方法、构造方法不能被重写。

super

当前子类父类型的特征。

  • 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。
  • 访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。

抽象类

抽象类和抽象方法都使用 abstract 关键字进行声明,且不能被 final 修饰。抽象类一般会包含抽象方法,抽象方法一定位于抽象类中。抽象类中的子类可以是抽象类,如果不是抽象类的话必须对抽象类中的方法进行重写。

接口

接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。

从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类。

一个类如果实现了接口,那么这个类需要重写接口中所有的抽象方法,如果不重写则这个类需要声明为抽象类。

接口可以使项目分层,都面向接口开发,提高开发效率,同时也降低了代码之间的耦合度,提高了代码的可插拔性。

接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。

接口的字段默认都是 static 和 final 的。

内部类

内部类可以直接访问外部类的成员,包括 private 修饰的变量和方法。

  • 静态内部类
  • 匿名内部类
  • 成员内部类
  • 局部内部类

Object

1. toString()

用来被子类重写的,该方法将返回此对象的字符串表示,开发自己的类如果没有特殊要求都应该重写 toString 方法。

2. equals()

让继承 Object 的类重写,以满足比较不同类型对象是否等价的要求。String 已经对 equals 方法进行了重写。

public boolean equals(Object obj){
  return (this == obj);
}
重写规则

Ⅰ 自反性

x.equals(x); // true

Ⅱ 对称性

x.equals(y) == y.equals(x); // true

Ⅲ 传递性

if (x.equals(y) && y.equals(z))
    x.equals(z); // true;

Ⅳ 一致性

多次调用 equals() 方法结果不变

x.equals(y) == x.equals(y); // true

Ⅴ 与 null 的比较

对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false

x.equals(null); // false;
实现
  • 检查是否为同一个对象的引用,如果是直接返回 true
  • 检查是否是同一个类型,如果不是,直接返回 false
  • 将 Object 对象进行转型
  • 判断每个关键域是否相等
public class EqualExample {

    private int x;
    private int y;
    private int z;

    public EqualExample(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EqualExample that = (EqualExample) o;

        if (x != that.x) return false;
        if (y != that.y) return false;
        return z == that.z;
    }
}

3. hashCode()

hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。

在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。

4. finalize()

垃圾回收之前,自动调用此方法。

关键字

static

1. 静态变量

程序运行时静态变量存放在方法区里面,因此,静态变量在类加载阶段赋值,并且只赋值一次。

2. 静态方法

不用创建对象就能直接方法该方法,即使用「类名.静态方法名」的方式。静态方法不能访问非静态的数据。

3. 静态语句块

静态语句块在类加载阶段执行,只执行一次,按照自上而下的顺序执行,在构造方法之前执行。

4. 静态内部类

非静态内部类依赖于外部类的实例,而静态内部类不需要。

final

final 修饰的基本数据类型,值不能改变;final 修饰的引用数据类型,指向地址不能改变,但是对象里面的值是可以改变的。

  • — 无法被继承。
  • 方法 — 无法被重写。
  • 局部变量 — 一旦赋值,不可再改变。
  • 成员变量 — 必须初始化值。