面向对象编程
概述
java是一门面向对象编程的语言,其它几种我们常见的编程语言如:C++,Python也是面向对象编程的。与面向对象相对,还有一种是面向过程编程,我们学习编程刚开始接触的C语言就是一门面向过程编程的语言。
面向过程编程
概念
面向过程是一个具体化的,流程化的。要想解决一个问题,需要一步一步的分析,一步一步的实现。举个咱们最常见到的例子,就是将大象装进冰箱,面向过程中把对象装进冰箱要经过三个步骤。
- 打开冰箱门;
- 把大象放进冰箱里面;
- 关闭冰箱门。
由此我们可以看出,面向对象强调的是过程。
优点
性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点
没有面向对象易维护、易复用、易扩展。
面向对象编程
概念
面向对象是模型化的,我们只需要抽象出一个类,这是一个封闭的盒子,里面拥有数据也有解决问题的方法。需要什么功能直接使用就可以了,不必一步一步的去实现。至于这个功能是如何实现的,我们不需要知道,只要会用就可以了。同样,我们使用把大象装进冰箱这个例子。打开,储存,关闭等行为都是对于冰箱的操作,是冰箱的行为。冰箱就是一个对象,所以我们只需要操作冰箱所具备的功能。当我们需要把大象放进冰箱的时候,只需要对冰箱说“嗨,冰箱,把大象放进去”,至于冰箱具体是怎么把大象放进去的,我们不需要知道,我们只要会使用冰箱即可。
优点
易维护、易复用、易扩展。由于面向对象具有封装、继承、多态的特性,可以设计出低耦合的系统,使得系统更加灵活、更加容易维护。
缺点
性能没有面向过程高。
面向对象的三大特性
面向对象编程主要有三个重要特性
- 封装
- 继承
- 多态
封装
所谓封装,就是将一个对象的属性私有化,同时提供给外界一些可以访问其属性的方法。如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也就没有什么意义了。
封装提高了代码的复用性和安全性。
继承
继承是使用已存在的类的定义为基础建立新的类的技术。新类的定义可以增加新的数据或者新的功能,也可以使用父类的功能,但是不能选择性的继承父类。通过使用继承,我们能够非常方便的复用之前的代码,继承为多态提供了前提。
特点
- java中只存在单个继承而不可以多继承,即一个类只能有一个父类。C++中可以多继承。
- java中虽然不能多继承,但是可以多层继承。
- 子类拥有父类所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问的,只是拥有。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
如果将name前面的修饰符public改为private,那么此时子类就不能再访问了
protected关键字
如果将字段设置为private,那么子类就不能访问了,设置为public又违背了封装的初衷,两全其美的办法就是protected关键字。
♥ 对于类的调用者来说,protected修饰的字段和方法是不能访问的。
♥ 对于类的子类和同一个包中的其它类来说,protected修饰的字段和方法又是可以访问的。
java中对于字段和方法有四种访问权限
- private:类内部能访问,类外部不能访问;
- default(默认):类内部能访问,同一个包中的类可以访问,其它类不能访问;
- protected:类内部能访问,子类和同一个包中的类可以访问,其它类不能访问;
- public:类内部和类的调用者都能访问。
多态
所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在程序编程期间并不确定,而是在运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能确定。
因为在程序运行期间才确定具体的类,这样,不用修改源程序,就可以让引用变量绑定到不同的类的实现上,从而导致该引用所调用的方法随之改变,既不用修改源代码就可以改变程序所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
多态又分为编译时多态和运行时多态
编译时多态
编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编译之后会变成两个不同的函数,在运行时谈不上多态。
运行时多态
运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
在java中有两种方式实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中的同一方法)
java实现多态有三个必要条件:动态绑定、向上转型、方法重写
重载和重写
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时期的多态性,而后者实现的是运行时的多态性。
重载:发生在同一个类中,方法名相同,参数列表不同(参数类型,参数个数,参数顺序),与方法返回值和访问修饰符无关。即重载的方法不能根据返回值进行区分。
重写:发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
重载的规则
- 方法名相同
- 参数列表不同(参数个数、参数类型、参数顺序)
- 返回值不做要求
重写的规则
- 一般用于子类重写父类的方法
- 方法名称必须相同
- 参数列表必须相同
- 返回值类型也必须相同
- 子类的访问权限必须高于父类被重写的方法的访问权限
- 抛出的异常范围小于等于父类
- 声明为final和static的方法不能被重写
- 构造方法不能被重写
抽象类与接口
抽象类的规则
- 抽象类没有方法体(只声明,不实现,具体的实现由继承它的子类来完成)
- 抽象类不能被实例化
- 抽象方法不能是private的,因为就不能被继承了。
- 抽象类中可以包含其它非抽象方法,也可以包含字段,这个非抽象方法和普通方法是一样的,可以被重写,也可以被子类直接调用。
接口的规则
- 接口时抽象类的更进一步,抽象类中还可以包含非抽象方法和字段,但是接口中只有抽象方法,字段只能是静态常量(final和static)。
- 一个类通过继承接口的方式,从而继承接口中的抽象方法。
- 使用interface定义一个接口,使用implement实现一个接口。
- 接口中的方法一定时public的。
- 接口不能被单独实例化
- java中一个类不能多继承,但是可以同时实现多个接口。
- 接口可以继承自另一个接口,使用extends关键字,达到复用效果。
抽象类和接口的对比
相同点
- 接口和抽象类都不能被实例化。
- 都位于继承的顶端,用于被其它实现或者继承。
- 都包含抽象方法,其子类必须重写这些抽象方法。
不同点
普通类和抽象类有哪些区别?
- 普通类中不能有抽象方法,抽象类中可以包含普通方法。
- 抽象类不能直接实例化,普通类可以直接实例化。
抽象类能被final修饰吗?
不能,因为被final所修饰的类不能被继承,而定义抽象类就是为了被继承,这样就会彼此产生矛盾,所以final不能修饰抽象类。
这里既然说到final了,咱们就来具体说一下
final是一个关键字,可以用来修饰类,方法和变量。
- 修饰类时,表示该类不能被继承;
- 修饰方法时,表示该方法不能被重写;
- 修饰变量时,表示变量只能一次赋值以后值不能被修改(常量)。
static的独特之处
static存在的主要意义是在于创建独立于具体对象的变量或者方法。即使没有创建对象,也能使用属性和调用方法。
static关键字还有一个比较关键的作用就是用来形成静态代码块来优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。因此,很多时候都是将一些只需要进行一次初始化的操作放在static块中。
1.修饰属性
java静态属性和类相关,和具体的实例无关,同一个类的不同实例共用同一个静态属性。
执行结果
上述代码中,count被static所修饰,所有类共享,且不属于对象,访问方式为:类名.属性名。
再java中,类创建的对象存储在堆上,其引用存放在虚拟机栈上,而其中被static修饰的变量存放在方法区中,类共享。
2.修饰方法
在任何方法上用static修饰,该方法就为静态方法。
- 静态方法属于类,而不属于类的对象;
- 可以直接调用静态方法,无需创建类的实例对象;
- 静态方法可以访问静态数据成员,并且可以更改静态数据成员的值。
注意事项:
1.静态方法不能直接使用非静态数据成员或者非静态方法(这两个都与实例有关)
2.this和super两个关键字不能在静态上下文中使用(this是当前实例的引用,super是当前父类实例的引用,也都与当前实例有关)
总结
以上内容便是我对面向对象编程的知识点的整理和小结,如能对各位博友有所帮助我将感到不胜荣幸,文章中也可能存在不足之处,敬请各位博友斧正!