1.Java面向对象和面试过程的区别?
面向过程
是将一个问题拆解成几个步骤,依次实现每一个步骤,比如实现一个冒泡排序的算法,是为了解决某个非常具体的问题。
而面向对象
也是将一个问题拆解成几个步骤,但是先不去实现,而是根据这些步骤抽象出若干个类,每个类都有属性和方法,咱配合着把问题解决。比如把大象装进冰箱,得有一个冰箱类和大象类,还有一个执行者类。执行者类拥有一个放入的方法,传入两个参数:大象 和 冰箱。
2.面向对象的三大特性怎么理解?
1.封装
把客观的事物抽象成一个类就是封装,实际开发中,这个事物往往是一个业务对象,比如贷款,公积金,房产等。
2.继承
编程界的继承就是子类继承父类,从而可以复用父类的属性和方法,目的就是少写代码。
3.多态
子类继承父类后,虽然继承了父类的属性和方法,但是业务上往往需要子类拥有不同的行为,所以在一个继承链中同一个方法很有可能出现不同实现(方法重写/重载),这就是多态的一个体现。
多态还体现在方法传参的时候,比如一个eat方法,参数列表是Food类型,那么所有继承自Food类的实例都可以传进去。目的是提高程序的灵活性。
3.继承和实现有什么区别?
一个类用 extends
关键字继承父类,用 implements
关键字实现接口,不管是继承还是实现,这个类都可以视为父类/接口类的子类。
继承和实现都是为了实现多态,Java支持多实现,单继承。
4.为什么Java不支持多继承
需要多继承的场景很少,而且多继承会带来菱形问题,C++为了解决菱形问题引入了虚继承,过于复杂,没必要。
PS:所谓菱形问题就是B类和C类都继承了A类,D类同时继承B类和C类,那么A类中的方法会在D类里面获取两次,这时D类如果调用A类的方法,会有歧义。
5. 面向对象的无法基本原则?
单一职责原则 (SRP):
这个原则指的是一个类最好只做一件事。这有助于降低类的复杂性,提高代码的可读性和可维护性。例如,一个汽车类可以有一个方法叫做move()
,而这个方法里面包含了所有关于移动汽车的行为,加速、减速、转弯等等。这就不符合单一职责原则,因为move()
方法做了太多的事情。更好的做法是将加速、减速、转弯等行为放在各自的方法中,使得每个方法都只做一件事情。
开放封闭原则 (OCP):
这个原则是指对扩展开放,对修改封闭。也就是说,在设计一个系统的时候,应该使得它可以通过添加新的代码来进行扩展,而不是通过修改已有的代码。例如,如果我们有一个处理VIP用户的类,我们可以为这个类添加一个新的方法来处理新类型的VIP用户,而不是修改已有的方法来处理新的VIP用户。
里氏替换原则 (LSP):
这个原则是指子类必须能够替换其父类。也就是说,如果一个类B继承自一个类A,那么在使用A的地方应该可以使用B。这个原则可以帮助我们确保继承的正确使用,避免向下替换的问题。
简单来说,就是任何你用到父类的地方,就算换成子类,程序也不会报错。
所有子类的行为功能必须和使用者对其父类的期望保持一致,如果子类达不到这一点,那么必然违反里氏替换原则。
如果违反了,我们就要反思,是不是我们的继承用错了。比如鸟类实现了飞翔的接口,鸵鸟能继承鸟类嘛?显然不行,因为鸟类希望所有的继承者都会飞,而鸵鸟显然不能飞,强行继承的话,在鸟飞调用fly方法的时候,鸵鸟就报错了。
依赖倒置原则 (DIP):
这个原则是指程序要依赖于抽象接口,而不是具体的实现。也就是说,我们在编程的时候应该依赖于接口或者抽象类,而不是具体的实现类。
简单来说就是定义对象的时候,用接口或者抽象类,而不是一个具体的实现类。
这样可以使得我们的代码更加灵活,可以方便地更换实现。例如,我们有一个接口叫做Printer
,有很多实现这个接口的类(如PrinterA, PrinterB等等)。在我们的代码中,我们不应该直接使用PrinterA
或PrinterB
,而应该使用Printer
接口。这样如果以后我们想更换成其他的打印机,只需要添加一个新的实现类就可以了。
接口隔离原则 (ISP):
这个原则是指使用多个小的专门的接口,而不要使用一个大的总接口。
简单来说就是接口方法尽量少,避免一个类因为实现了接口,要去实现一大堆自己用不到的方法。