Java的面向对象知识点梳理
1. 面向对象和面向过程
面向过程:
面向过程就是把一个问题按照从左到右,从上到下的解决方案分解成N个小步骤然后挨个去执行,自顶向下,逐步细化
面向对象:
面向对象和面向过程思想完全不同,它是需要根据问题先抽象一个模型(即我们通常说的类),然后把这个模型实例化(也就是我们通常说的对象)来使用,其中在模型中我们封装了解决问题需要的一些属性和方法,通过将该模型实例化成对象,然后调用模型中的方法来解决.
面向对象和面向过程的比较
面向过程简单直接,易于入门理解,模块化程度较低。
面向对象相对于面向过程较为复杂,不易理解,模块化程度较高。
可总结为下面三点:
- 1.都可以实现代码重用和模块化编程,但是面对对象的模块化更深,数据更封闭,也更安全!因为面向对象的封装性更强!
- 2.面对对象的思维方式更加贴近于现实生活,更容易解决大型的复杂的业务逻辑
- 3.从前期开发角度上来看,面对对象远比面向过程要复杂,但是从维护和扩展功能的角度上来看,面对对象远比面向过程要简单!
2. 类的概念
类是构建对象的模板和蓝图,由类构造对象的过程叫做创建类的实例
类就是一类事物的总称,如果将某个事物抽象为对象,那么类就是这个对象的总称
类是封装对象的属性和行为的载体,对象则是类的实例
3. 面向对象的第一大特性------封装(安全性)
java核心技术对封装的描述:
封装也可以称为数据隐藏,即是将数据和行为组合到一个包中,并对对象的使用者隐藏了数据的实现方式。
封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域,程序仅仅通过对象的方法与对象数据进行交互。
封装给对象赋予了"黑盒"的特征,提高了重用性和可靠性
面经描述:
封装性是面向对象编程的核心思想。指的就是将描述某种实体的数据和基于这些数的操作集合到一起,形成一个封装体。封装的思想保证了类内部数据结构的完整性,使用户无法轻易直接操作类的内部数据,这样降低了对内部数据的影响,提高了程序的安全性和可维护性。
封装的好处
- 1.只能通过规定的方法来访问数据
- 2.隐藏了类中的方法的实现细节
- 3.方法修改实现
- 4.方便加入控制语句
封装的使用:
1)修改属性的可见性 ——> 设为private
2)创建共有的 getter / setter方法 ——> 用于属性的读写
3)在getter / setter方法中加入属性控制语句 ——> 对属性值的合法性进行判断
4. 类之间的关系
依赖关系:即如果一个类A的方法操纵另一个类B的对象,就说类A依赖于一个类B
聚合关系:即一个类A的对象包含类B的对象
继承关系:类A继承父类B,子类就拥有了父类的属性和方法,而同时子类又能够去定义自己特有的属性和方法
5. 对象和对象变量
1.局部变量不能自动初始化为null,而必须通过调用new或者将他们设置为null进行初始化
2.构造器域其他的方法不同:构造器总是伴随着new操作符的执行而被调用的,而不能对一个已经存在的对象调用构造器来达到重新设置实例域的目的
3.this关键字表示隐式参数
4.静态方法不存在this关键字
5.使用静态方法的场景:
-
一个方法不需要访问对象状态,其所需参数都是通过显式参数来提供
-
一个方法只需要访问类的静态域
6. java类的执行次序
若类还未被加载
-
先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关。
-
执行子类的静态代码块和静态变量初始化。
-
执行父类的实例变量初始化
-
执行父类的构造函数
-
执行子类的实例变量初始化
-
执行子类的构造函数
若类已经加载
则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法
- 即:静态代码块和静态变量只在第一次加载类的时候进行初始化
7. 方法参数
参数传递给方法的方式分为:1.按值调用 2.引用调用
java中总是按值调用:
- 1.java方法不能修改一个基本数据类型的参数(即数值类型或者布尔类型)
- 2.java方法可以改变一个对象参数的状态
- 3.java方法不能让对象参数引用一个新的对象
8. java的域,静态域,实例域
域:即是我们常说的字段,或者说是属性。 比如类的字段(属性),局部的属性,全局的属性等等。
域包括实例域和静态域
9. 方法的重载
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载
java允许重载任何方法,不只是构造方法
方法重载和方法重写的区别:
方法的重载指的是在同一个类中,同一个方法名,但是方法的参数列表不同:参数的个数,参数的类型,参数的顺序不同称为重载
方法的重写指的是子类继承父类,在子类中编写和父类一样的方法(要求子类重写父类方法的时候,其权限必须要大于父类该方法的权限)
10. 面向对象的第二大特性-----继承
继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或类从父类继承方法,使得子类具有父类相同的行为
继承的特点:
1.继承鼓励类的重用
2.继承可以多层继承
3.一个类只能继承一个父类,即只允许单继承
4.父类中private修饰的不能被继承
5.构造方法不能被继承
继承的细节点:
1.java中所有的继承都是公有继承,没有C++中的私有继承和保护继承
2.如果子类的构造器没有显式的调用超类(父类)的构造器,则将自动地调用超类(父类)(没有参数)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其他构造器,则java编译器就会报告错误。
3.关键字this有两个用途:
一是引用隐式参数,二是调用该类的其他的构造器。
4.关键字super也有两个用途:
一是调用超类的方法,二是调用超类的构造器。
5.在子类覆盖父类的一个方法的时候,其可见性要高于父类,即如果父类方法时public,子类方法一定要声明为public。
6.不允许扩展的类被称为final类
7.final域在构造对象以后,就不允许改变他们的值了,但是,如果将一个类声明为final,只有其中的方法自动成为fina,而不包括域。
7.将一个子类的引用赋给一个超类变量,编译器是允许的(多态,向上转型),但是将一个超类的引用赋给一个子类变量,就必须进行类型转换,这样才能通过运行时的检查(向下转型),但是向下转型时很容易出现类型转换异常,可以在将超类转换成子类之前,应该使用instanceof来判断某一对象是否属于一个类
11. 动态绑定和静态绑定
动态绑定:默认的处理方式:方法不是private,static或者final类型
调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定。动态绑定的过程分为以下几个环节:
(1)编译器查看对象的声明类型和方法名;
(2)编译器查看调用方法时提供的参数类型。例如x.f(“hello”),编译器将会挑选f(String),而不是f(int),由于存在类型转换(int转换为double),所以可能会更复杂。如果编译器没找到参数类型匹配的方法,或者发现有多个方法与之匹配,就会报告一个错误。
至此,编译器获得了需要调用的方法名字和参数类型。
(3)采用动态绑定调用方法的时候,一定调用与所引用对象的实际类型最合适的类的方法。如果x的实际类型是D,它是C类的子类,如果D定义了一个方法f(String),就直接调用它,否则将在D类的超类中寻找f(String),以此类推。
(4 ) 每次调用方法都要进行搜索,时间开销太大,所以虚拟机预先为每个类创建一个方法表(method table),其中列出了所有方法的签名和实际调用的方法。这样在调用方法的时候,只需要查找这个表即可
静态绑定
private:不能被继承,则不能通过子类对象调用,而只能通过类本身的对象进行调用,所以可以说private方法和方法所属的类绑定;
final:final方法虽然可以被继承,但是不能被重写(覆盖),虽然子类对象可以调用,但是调用的都是父类中的final方法(因此可以看出当类中的方法声明为final的时候,一是为了防止方法被覆盖,而是为了有效关闭java的动态绑定);
static:static方法可以被子类继承,但是不能被子类重写(覆盖),但是可以被子类隐藏。(这里意思是说如果父类里有一个static方法,它的子类里如果没有对应的方法,那么当子类对象调用这个方法时就会使用父类中的方法。而如果子类中定义了相同的方法,则会调用子类的中定义的方法。唯一的不同就是,当子类对象上转型为父类对象时,不论子类中有没有定义这个静态方法,该对象都会使用父类中的静态方法。因此这里说静态方法可以被隐藏而不能被覆盖。这与子类隐藏父类中的成员变量是一样的。隐藏和覆盖的区别在于,子类对象转换成父类对象后,能够访问父类被隐藏的变量和方法,而不能访问父类被覆盖的方法。
12. java的4个访问修饰符
1.private-----仅对本类可见
2.public-----对所有类可见
3.protected-----对本包和所有子类可见
4.默认(没有修饰符)------对本包可见
13. 自动装箱
1.自动装箱规范要求boolean,byte,char<=127,介于-128~127之间的short和int被包装到固定的对象中
2.由于包装器类引用可以为null,所以自动装箱有可能会抛出NullPointException
3.装箱和拆箱是编译器许可的,而不是虚拟机.编译器在生成类的字节码时,插入必要的方法调用.虚拟机只是执行字节码文件.
14. 抽象类
拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明
java规定抽象类不能创建对象,并且天生就是作为父类使用
抽象方法:即一个方法,只有声明,没有实现,就称为抽象方法
细节点:
1.java语法规定只有一个类用abstract修饰,那么这个类就是抽象类
2.抽象类一定是父类。因为抽象类就是不断地抽取共性需求而生成的
3.抽象类中也可以不定义抽象方法,此时仅仅是不让该类创建对象
15. 面向对象的第3大特性-----多态
一个对象变量可以指示多种数据类型的现象称为多态,是同一个行为具有不同的表现现象的能力
在运行时能自动地选择调用哪个方法的现象称为动态绑定
详细解答版本:
多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性.
多态表现的三大特性:
1.必须存在子父类关系(即存在继承关系)
2.子类重写父类的方法
3.父类引用指向子类对象
多态的优缺点:
优点:
1.消除类型之间的耦合关系
2.可替换性
3.可扩充性
4.接口性
5.灵活性
6.简化性
缺点:
无法直接访问子类的特有成员属性
简单总结多态的特点:
指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用).
1.成员变量
编译看左边(父类),运行看左边(父类)
2.成员方法
编译看左边(父类),运行看右边(子类)。动态绑定
3.静态方法
编译看左边(父类),运行看左边(父类)。静态和类相关,算不上重写,所以,访问还是左边的。只有非静态的成员方法,编译看左边,运行看右边
16. final关键字
1.final可以修饰类,成员变量,成员方法.局部变量(基本类型,引用类型)
2.final修饰类:不能被继承,但是可以作为其他类的子类
3.final修饰成员变量:
-
被final修饰的成员变量,必须在创建对象之前进行值的初始化(即有确定的值)
-
被final修饰的成员变量只能被赋值一次
4.final修饰成员方法:不能被子类重写,子类调用该方法时,调用的即是父类的方法
5.final修饰局部变量:只能赋值一次