前言

面向对象编程是一种程序设计思想,简称 OOP。它把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

OOP:Object Oriented Programming

面向对象的三大特征

  • 封装:将对象的属性隐藏在对象内部,不允许外部直接访问,只提供一些可访问的方法操作某些属性。
  • 继承:
    • 子类拥有父类的属性和方法(包括私有)。但是子类无法访问私有属性和方法,仅仅是拥有。
    • 子类可以对父类进行扩展。
    • 子类可以用自己的方式实现父类的方法。
  • 多态:多态具体表现为父类引用指向子类实例。
1
2
3
4
/** 
* 多态
*/
List<Integer> list = new ArrayList<>();

多态的实现

本质上分为编译时多态(静态多态)和运行时多态(动态多态),重载就是动态多态的一个例子。

Java 实现多态需要满足 3 个条件:继承、重写和向上转型:

  • 继承:多态中必须存在有继承关系的子类和父类。
  • 重写:子类对父类中的某个方法进行重新定义,在调用这些方法时就会调用子类的方法。
  • 向上转型:在多态中需要将子类对象赋给父类引用,这样该引用才既能可以调用父类的方法,又能调用子类的方法。

多态的特点:

  • 多态不能调用“只在子类存在但是父类不存在”的方法。
  • 对象类型和引用类型之间具有继承(类)/ 实现(接口)的关系。
  • 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定。
  • 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,否则执行的是父类的方法。

面向对象和面向过程的区别

面向过程:

  • 优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源。
  • 缺点:不容易维护、易复用、易扩展。

面向对象:

  • 优点:易维护、易复用、易扩展。面向对象有封装、继承、多态性三个特性,所以可以降低系统的耦合性,使系统更加灵活和维护。
  • 缺点:由于对象需要实例化,所以性能较面向过程很低。

Java 创建对象的方式

Java 中包含 4 种创建对象的方式:

  • new 创建新对象;
  • 反射机制;
  • clone 机制;
  • 序列化机制;

其中,前两者都需要显式调用构造方法,clone 机制需要注意浅拷贝和深拷贝的区别,序列化一般通过 Externalizable 或者 Serializable 来实现。

成员变量和局部变量的区别

  • 语法形式:
    • 成员变量属于类,局部变量属于代码块或方法。
    • 成员变量可以被publicprivatestatic等修饰符修饰,局部变量不可以。但是二者都可以被final修饰。
  • 存储方式:成员变量根据是否被static修饰判断是属于类还是实例。对象存在堆内存,局部变量存在栈内存。
  • 生存时间:成员变量随着对象的创建而存在,局部变量随着方法的调用自动生成,随着调用结束而消亡。
  • 默认值:成员变量会自动以类型的默认值赋值,而局部变量不会自动赋值。如果被final修饰,则都必须显式赋值。

对象引用和对象实体

  • 对象实体:使用new关键字创建,存放在堆内存中。
  • 对象引用:存放在栈内存中,指向对象实体。

一个对象引用可以指向 0 或 1 个对象;一个对象实体可以有 n 个引用指向它。

1
2
3
4
5
6
// 一个对象实体可以有多个引用指向它
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = list1;

// true
System.out.println(list1 == list2);

对象相等和引用相等

  • 对象相等:比较内存中存放的内容是否相等。
  • 引用相等:比较他们指向的内存地址是否相等。

不可变对象

不可变对象指对象一旦被创建,状态就不能再改变,任何修改都会创建一个新的对象,如 String、Integer及其它包装类。不可变对象最大优点是线程安全。可以创建一个包含可变对象的不可变对象,但是需要注意不能共享可变对象的引用,而是在数据变化时返回原对象的一个拷贝。

接口和抽象类的共同点和区别

共同点:

  • 不能被实例化;
  • 可以包含抽象方法;
  • 可以有默认实现的方法,Java8 可以使用default关键字在接口中定义默认方法;

区别:

  • 一个类只能继承一个类,但是可以实现多个接口;
  • 接口强调约束类的行为,抽象类强调所属关系;
  • 接口中的成员变量只能为publicstaticfinal类型,不能被修改且必须有初始值。抽象类的成员变量默认default,可以在子类中重新定义或重新赋值。

参考

  1. Java的向上转型和向下转型