Java 面向对象知识点拆分(一)
Java 面向对象的编程思想是极其重要的,可以说是 Java 的核心,这块内容比较细,比较多,花了两周时间,整理出来 47 条知识点,帮助大家稳固基础,早日实现年薪百万,哈哈~
1、面向对象
初学者接触最多的一句话就是 Java 是一门面向对象的编程语言,然而能理解的并不多,其实很多问题如果使用面向对象的思想去解答,会特别的合理,还能把很难的问题简单化,但实际开发中很少能做到这一点。下面是几个例子,结合万事万物皆对象的理念多想想,慢慢就会有感觉。
举例 1:将大象装进冰箱
举例 2:叫人买电脑
举例 3:软件公司招技术人才
举例 4:到饭店叫服务员点菜
2、类和对象的关系
类:就是对现实生活中事物的描述。
对象:就是这类事物,实实在在存在的个体。
3、封装
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
将变化隔离;
便于使用;
提高重用性;
提高安全性。
原则:
将不需要对外提供的内容都隐藏起来;把属性都隐藏起来,提供公共方式对其访问。
4、构造函数
作用:可以用于给对象进行初始化。
注意:①当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。②当在类中定义了构造函数后,默认的构造函数就没有了。③一个对象建立,构造函数只运行一次;而一般的方法可以被该对象调用多次。
构造函数和一般函数在写法上有不同:
在运行上也有不同:
构造函数是在对象一建立就运行,给对象初始化。而一般方法是在对象调用才执行,给对象添加具备的功能。
5、构造代码块
作用:给对象进行初始化。
对象一旦建立就运行,而且优先于构造函数执行。
和构造函数的区别:
构造代码块是给所有对象进行统一初始化;而构造函数是给对应的对象初始化。
构造代码块中定义的是不同对象共性的初始化内容。
6、关键字—static
用法:
是一个修饰符,用于修饰成员(成员变量,成员函数);当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用。类名.静态成员。
特点:
①随着类的加载而加载(随着类的消失而消失
最长)②优先于对象存在(静态先存在,对象后存在)③被所有对象所共享④可以直接被类名所调用。
实例变量和类变量的区别:
①存放位置:类变量随着类的加载而存在于方法区中;实例变量随着对象的建立而存在于堆内存中。②生命周期:类变量生命周期最长,随着类的消失而消失;实例变量生命周期随着对象的消失而消失。
静态使用注意事项:
①静态方法只能访问静态成员;非静态方法既能访问静态也可以访问非静态②静态方法中不可以定义 this,super 关键字。因为静态优先于对象存在。所以静态方法中不可以出现 this。
静态利弊:
利处:对对相对共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。
弊端:生命周期过长;访问出现局限性(静态虽好,只能访问静态)。
7、解析 java 程序主方法 main()
主函数可以被 jvm 加载调用
主函数的定义:
public:代表着该函数访问权限是最大的。
static: 代表主函数随着类的加载就已经存在了。
void: 主函数没有具体的返回值
main: 不是关键字,但是是一个特殊的单词,可以被 jvm 识别。
(String[] str): 参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组。
jvm 在调用主函数时,传入的是 new String[]
8、什么时候使用静态
1)什么时候定义静态变量(类变量)?
当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态存在于堆内存中。
2)什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据)时。
9、静态代码块
格式:
特点:
随着类的加载而执行,只执行一次,用于给类进行初始化的。
10、对象的初始化过程
①因为 new 用到了 Person.class.所以会先找到 Person.class 文件并加载到内存中。②执行该类的 static 代码块,如果有的话,给 Person.class 类进行初始化。③在堆内存中开辟空间,分配内存地址。④在堆内存中建立对象的特有属性。并进行默认初始化。⑤对属性进行显示初始化。⑥对对象进行构造代码块初始化。⑦对对象进行对应的构造函数初始化。将内存地址付给栈内存中的 p 变量。
11、单例设计模式
解决一个类在内存中只存在一个对象。
保证对象唯一及实现方法:
①为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。【将构造函数私有化】②还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。【在类中创建一个本类对象】③为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。【提供一个方法可以获取到该对象】
定义单例模式时,建议使用饿汉式;因为懒汉式存在安全问题,效率不高。
12、继承
好处:
①提高了代码的复用性;
②让类与类之间产生了关系;正因为有了这个关系,才有了多态的特性。
特性:
java 语言只支持单继承,不支持多继承。因为多继承容易带来安全隐患:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。但是 java 保留了这种机制,并用另一种体现形式来完成表示。多实现。
java 支持多层继承,也就是一个继承体系。
如何使用一个继承体系中的功能呢?
要想使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的基本功能。那么这个体系已经可以基本使用了。
那么在具体调用时要创建最子类的对象,为什么呢?
①因为有可能父类不能创建对象;②创建子类对象可以使用更多的功能,包括基本的也包括特有的。
总之,查阅父类功能,创建子类对象使用功能。
子父类中变量的特点:
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用 this;子类要访问父类中的同名变量,用 super。
super 的使用和 this 的使用几乎一致。this 代表的是本类对象的引用。super 代表的是父类对象的引用。
子父类中函数的特点:
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。
覆盖:
①子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。②静态只能覆盖静态。
子父类中的构造函数:
在对子类对象进行构造初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐士的语句 super();super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是 super()。
为什么子类一定要访问父类中的构造函数?
因为父类中的数据子类都可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义 super 语句的方式来指定。
子类的实例化过程:
结论:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式 super();当父类中没有空参数的构造函数时,子类必须手动通过 super 语句形式来指定要访问父类中的构造函数。当然,子类的构造函数第一行也可以手动指定 this 语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
注意:
不要为了减少代码量而继承;必须是类与类之间有所关系才可以继承。
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。(父类中声明为 private 的方法,子类无法实现重写)
super 语句一定定义在子类构造函数的第一行。
方法的重写:
重写方法必须和被重写方法具有相同的方法名、参数列表和返回值类型。
重写方法不能使用比被重写方法更严格的访问权限。
重写和被重写的方法须同时为 static 的,或同时为非 static 的。
子类方法抛出的异常不能大于父类被重写方法的异常。
13、final 关键字
①final 作为一个修饰符,可以修饰类、变量、函数;②被 final 修饰的类不可以被继承;为了避免被继承,被子类复写功能,就将类的修饰符选为 final;③被 final 修饰的方法不可以被复写;④被 final 修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,也可以修饰局部变量;⑤内部内定义在类中的局部位置上时,只能访问该局部被 final 修饰的局部变量。
注意:
当在描述事务时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字,方便于阅读。而这个值不需要改变,所以加上 final 修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过下划线(_)连接。
14、抽象类
定义抽象类:
当多个类中出现相同功能,但是功能主题不同,这时可以进行向上抽取,只抽取功能定义,而不抽取功能主体。
抽象类的特点:
①抽象方法一定在抽象类中;②抽象方法和抽象类都必须被 abstract 关键字修饰;③抽象类不可以实例化对象,因为调用抽象方法没有意义;④抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法,建立子类对象调用;如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
抽象类和一般类没有太大的不同
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西,这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体,通过抽象方法来表示。
抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法。抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是为了不让该类建立对象。
15、模板方法设计模式
定义:在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去。由该类的子类完成.
16、接口
不可以创建对象,因为有抽象方法;需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类。
接口可以被类多实现,也是对多继承不支持的转换形式,java 支持多实现。
接口特点:
接口是对外暴露的规则;
接口是程序的功能扩展;
接口可以用来多实现;
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口;
接口与接口之间可以有继承关系。
17、多态
可以理解为事物存在的多种体现形态。
多态的 2 种体现:
方法的重载和重写。
对象的多态性——可以直接应用在抽象类和接口上。
父类的引用指向了自己的子类对象;
父类的引用也可以接受自己的子类对象。
多态的前提
必须是类与类之间有关系。要么继承,要么实现;
通常还有一个前提:存在覆盖。
多态的好处
多态的出现大大的提高了程序的扩展性。
多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
多态的应用
在多态中成员函数的特点:
①在编译时期:参阅引用型所属的类中是否有调用的方法。如果有,编译通过;如果没有编译失败。②在运行时期:参阅对象所属的类中是否有调用的方法。
总结:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
18、内部类
内部类的定义规则:
当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。
内部类的访问规则:
①内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式为:外部类名.this。②外部类要访问内部类,必须建立内部类对象。
访问格式:
①当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象。格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;例如:Outer.Inner in = new Outer().new Inner();②当内部类在成员位置上,就可以被成员修饰符修饰。比如,private:将内部类在外部类中进行封装。static:内部类就具备 static 的特性。当内部类被 static 修饰后,只能直接访问外部类中的 static 成员。出现了访问局限。
在外部其他类中,如何直接访问 static 内部类的非静态成员呢?
在外部其他类中,如何直接访问 static 内部类的静态成员呢?
内部类定义在局部时:
①不可以被成员修饰符修饰;②可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被 final 修饰的局部变量。
注意:当内部类中定义了静态成员,该内部类必须是 static 的。当外部类中的静态方法访问内部类时,内部类也必须是 static 的。
匿名内部类:
①匿名内部类其实就是内部类的简写格式;②定义匿名内部类的前提:内部类必须是继承一个类或者实现接口;③匿名内部类的格式:new 父类或者接口(){定义子类的内容};④其实匿名内部类就是一个匿名子类的对象。可以理解为带内容的对象。
19、关键字—this
this:代表本类对象,哪个对象调用 this 所在函数,this 就代表哪个对象。
以上这部分内容是面向对象这块的核心内容,我们都知道,封装、继承和多态是 Java 面向对象的三大块内容,如果你已经学习了一遍基础知识,那么这个总结是最适合你来温故知新的,也可以用来查缺补漏。下节内容将会介绍 JavaSE 的核心 API 知识,包括集合框架、文件操作、常用类和方法等。
版权声明: 本文为 InfoQ 作者【逆锋起笔】的原创文章。
原文链接:【http://xie.infoq.cn/article/9044cb22a1af5d69687ee5a58】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论