前期准备01-2.1

 

一、程序的流程控制语句

①判断结构(if)

格式:

❶if(条件表达式)

→{条件表达式为true,执行此语句;}

❷if(条件表达式)

→{条件表达式为true,执行此语句;}

→else

→{条件表达式为false,执行此语句;}

❸if中嵌套if或者else中嵌套if

❹if-else结构,有时可以简写为三元运算符,如:变量 = 三元运算符;好处是,可以简化代码;局限性是,运算必须要有结果。

②选择结构(switch)

格式:

switch(表达式)

{

→case 取值1:

→→→→执行语句;

→→→→break;

→case 取值2:

→→→→执行语句;

→→→→break;

→default:

→→→→执行语句;

→→→→break;

}

❶switch语句中的表达式的值只能是四种类型:byte,short,int,char。

当表达式的值满足了某个case的取值时,将在此处一直向下执行,直至遇到break或者switch语句结束。

❷多个case可以共同执行一条语句,如判断季节;case之间也可以没有顺序,可以任意排列,只是先执行第一个。

❸default语句后加了break,就可以放在switch语句的任意位置;如果default语句后没有加break,当它后面还有属于switch语句的代码时,执行到它之后,还会继续向下执行,一直到switch语句结束或者遇到break为止。

❹if的使用范围更广,switch适合判断具体数值不多,且数值属于byte,short,int,char四种类型的情况,效率更高一些,代码更直观。

③循环结构(while,do-while,for)

❶while语句

格式:

while(循环条件表达式)

{循环体(参与循环的语句);}

注意:while()后没有分号,否则while一旦被执行就会进入无限循环。

❷do-while语句

格式:

do

{循环体(参与循环的语句);}

while(循环条件表达式);

注意:while()后有分号。

其特点是:无论条件是否满足,循环体至少被执行一次。也可以在循环体中,再加上条件判断(可以使用if语句),来控制循环体的执行。

❸for语句

格式:

for(初始化表达式;循环条件表达式;循环后要操作的表达式)

{循环体(参与循环的语句);}

当初始化表达式中有多个表达式时,用逗号隔开;循环后要操作的表达式中有多个表达式时,用逗号隔开。

for语句中各表达式的执行顺序:初始表达式只执行一次,然后判断循环条件,为true就执行循环体,然后再执行循环后要操作的表达式,接着继续判断循环条件,一直重复这个过程,直到条件不满足为止,结束循环。

while与for可以互换,区别在于for为了循环而定义的变量在for循环结束后,就在内存中释放了,而while循环使用的变量在循环结束后还可以继续使用。如果参与循环的变量不被外部使用,用for更合适。

最简单无限循环格式:while(ture){},for(;;){}

for的嵌套循环可以控制有规律的二维空间。

④关键字break(跳出)

break可以跳出选择语句(switch),循环语句(while、do-while、for)。

⑤关键字continue(继续)

continue应用于循环语句中(while、do-while、for)。表示只结束本次循环,继续执行下一次循环。

注意:break和continue离开了应用范围,其存在是没有意义的。当这两个语句单独存在时,其下面的语句将执行不到。标号(标记名:)可以让这两个语句能够作用于标号所指定的范围。

 

二、函数(即方法)

①函数的定义

❶函数就是定义在类中的具有特定功能的一段小程序。

❷函数的格式:

修饰符 返回值类型 函数名(参数类型 形式参数1,...)

{

→执行语句;

→return 返回值;

}

修饰符:限定函数的访问权限;标明函数的状态。

返回值类型:函数运行后所得结果的数据类型,函数可以没有返回值,用void修饰。

参数类型:是形式参数的数据类型。

形式参数:是一个变量,用于存储函数调用者传递给函数的实际参数。函数可以是空参数函数。参数是有顺序的,应用于函数的重载。

实际参数:传递给形式参数的具体数值或引用,参与函数功能的实现。

return:用于结束函数,若需要则传递返回值给该函数的调用者。

返回值:该值会返回给函数的调用者。用void修饰的函数没有返回值。

②函数的特点

❶可以将功能代码进行封装

❷方便功能的复用

❸只有在被调用时才被执行

❹函数的出现提高了代码的复用性

❺对于函数没有具体返回值的情况,返回值类型用void表示,这时该函数的return语句如果是在最后一行,就可以省略不写。

注意:函数只能调用函数,不可以在函数内部再定义函数。

③函数的应用

程序中实现应用功能的最小单元即为函数,函数的功能就是对实际应用的一种抽象和提取,它可以使得对实际应用的操作更加高效。

④函数的重载

在同一个类或子父类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型或者参数的排列顺序不同即可(函数同名,参数不同)。

❶重载的特点:

与返回值类型无关,只看参数列表。参数是有顺序的。

❷重载的好处:

方便于阅读,优化了程序设计。

 

三、数组

①数组的定义

数组就是一个集合或者容器,用于存放同一种类型的数据。

❶数组的好处:可以自动给数组中的元素从0开始编号,方便对数组中各个元素的操作。数组中的第i个元素为:数组名[i-1]。

❷数组中的元素可以是基本数据类型,也可以是引用数据类型。

②数组的格式:

数据类型[] 数组名 = new 数据类型[元素个数(即数组长度)];

数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};

对于数组的两种显式初始化方式,定义了数组的长度就不能再罗列数组中的元素,反之亦然。

❶数组名作为一个变量存在于栈内存中,离开其使用范围即被自动释放。

❷数组中的元素,存在于堆内存中,当其不被引用时,只能依靠垃圾回收机制才能被释放掉。

❸数组名的取值,是数组元素在堆内存中存放的首地址,数组名只是一个引用变量,当其离开作用范围或者通过对其赋值null,可以让它结束引用,使得其之前的引用数据变为垃圾(只是在堆中数据被单引用时生效)。

③数组的操作

获取数组中的各个元素的值,要使用遍历,通过循环语句实现。

❶选择排序

从数组的第一个元素开始,将当前位置上的值,同其之后的每一个值进行比较,将符合条件的值换位到当前位置,然后从第二个元素开始再次循环操作,直至数组的最后一个值,完成对数组中各个元素的排序。

对于选择排序,数组中的第一个位置上的值,最先完成排序动作。

❷冒泡排序

从数组的第一个元素开始,将当前位置上的值,同后面的第二个元素的值相比较,符合条件即换位,然后将第二个元素的值同其后面的值相比较,符合条件再次换位,以此类推,一直比到数组的最后一个元素;然后从数组的第一个元素开始,再次循环操作。每次循环都比前一次少比较一个元素的值,即经过前一次比较之后的最后一个元素,直至操作到只剩第一个元素为止。

对于冒泡排序,数组中的最后一个位置上的值,最先完成排序动作。

❸排序相关知识点

排序中都会涉及到换位操作,可以将此操作封装成一个函数。

数组排序:

java.util.Arrays.sort(object[] a)

(['dʒa:və][ju'til][ə'reiz][sɔ:t]['ɔbdʒikt])

根据元素的自然顺序,对指定的对象数组中的元素,按升序进行排序。要保证数组中的所有元素都是可相互比较的。

❹折半查找

通过移动数组中最小角标和最大角标的位置,来判断数组中不断变化的中间角标位的值,是否与所查找的元素相等,从而实现查找的功能。

折半查找返回角标值为-1时,表示数组中没有此元素,因为数组的角标最小是0。

折半查找可以提高效率,但是要求数组必须是有序的。

④二维数组

数组中的元素依然是数组。

格式:

❶元素类型[][] 数组名 = new 元素类型[m][n];

此数组中有m个一维数组元素,每个一维数组中有n个值。

❷元素类型[][] 数组名 = new 元素类型[m][];

此数组中有m个一维数组元素,每个一维数组默认初始化为null。可以分别给每个一维数组进行显式初始化,如:a[i]=new int[j]。

⑤定义数组时需要注意的地方:

一维数组:int[] x;int x[]

二维数组:int[][] x;int x[][];int[]x[]

 

四、面向对象

面向对象是相对于面向过程而言的。面向过程强调的是功能、行为;面向对象将功能封装进对象内部,强调具备了功能的对象。面向对象是基于面向过程的。

①类与对象的关系:

类是一种描述,是一个概念,是抽象的。

对象是一个实际存在的个体,是类的实现,是物质的。

类决定了对象的属性和功能,对象丰富了类的表现形式。

类中的成员变量决定对象的属性,随着对象的创建而实现(静态成员变量在数据区中,非静态成员变量在堆内存中);类中的成员函数决定对象的功能,需要对象的调用才能实现,存在于方法区(共享区、数据区)中。

②创建对象:

一个类,只有创建了对象,才能实现具体功能,才有其存在的意义。

格式:

类名 对象名(标示符) = new 类名();

❶一个类可以创建无限多个对象,每一个对象的生命轨迹,可以自由书写。

❷对象名是一个引用型变量,属于类类型,它指向该类的一个对象,这个对象的属性(非final型)的取值是可以变化的,功能的实现是可以选择的。

❸匿名对象:当对一个对象只是被使用一次时,可以使用匿名对象;匿名对象可以作为实际参数,进行值的传递。

 

五、面向对象的三大特征之一:封装

①封装的定义:

封装是指隐藏对象的属性和实现细节,仅对外提供公共访问的方式。

②封装的好处:

将变化隔离,便于使用,提高复用性,提高安全性。

③封装的原则:

❶将不需要对外提供的内容都隐藏起来。

❷把所有的属性都隐藏起来,只对外提供公有方法对其进行访问。

④封装的实现:

对象是对类的实现,是对类中的成员变量和成员函数的实现。把对象的属性和实现细节隐藏,就是把类中的成员变量和成员函数隐藏。对类中的成员甚至类本身进行隐藏,使用的是可以限制访问权限的修饰符。

❶权限修饰符private:

私有的,用于修饰类的成员(包括成员变量、成员函数和内部类),私有之后的成员,只能被本类中的成员所访问。

私有只是一种表现形式,若是私有成员有必要被外部访问,可以向外部提供能够访问内部私有成员的公有的方法。通过该方法,来判断外部的访问是否合理,合理即允许访问,不合理即不允许访问。公有方法的功能,是可以进行逻辑判断,提高了代码的健壮性。

❷其它权限修饰符:public(公有)、protected(保护)

 

六、构造函数

①构造函数的特点:

函数名与类名相同,不用定义返回值类型,不可以写return语句。

相对于每个不同的对象而言,其自身的构造函数只被执行一次。

②构造函数的作用:

给对象进行初始化,包括对象的属性和对象的功能。对象一被创建,就会调用与之对应的构造函数。

③默认构造函数:

❶若是类中没有定义构造函数,系统会自动添加一个无参数的构造函数,即:类名(){}。

❷若是类中定义了构造函数,则系统就不再自动添加。

❸当类中定义了非空参数的构造函数,一般还要再定义一个空参数的构造函数。因为,当此类被其子类继承时,其子类的所有构造函数中,都会默认包含一个父类的空参数构造函数。

❹默认构造函数的权限和所属类的权限保持一致,其权限随着类权限的变化而变化。当然,可以做显式的修改。

④构造函数的重载:

多个构造函数的存在,是以函数重载的形式完成的。它们决定了不同对象的创建,可以拥有不同的初始化属性。

⑤构造代码块:

❶格式:

{需要执行的代码;}

❷作用:

给对象进行初始化。对象一被创建就会运行,而且优先于构造函数执行。构造代码块中定义的,是不同对象所共性的初始化内容。

❸构造代码块和构造函数的区别:

构造代码块是给所有对象进行统一的初始化,而构造函数是给其所相对应的对象进行初始化;构造代码块的执行顺序在构造函数之前。

⑥构造函数的私有化

❶构造函数是可以被私有化的,当一个类中的所有的构造函数都被私有化后,该类就不能够被外部的程序创建它的对象了。

❷单例设计模式,应用了构造函数的私有化,并在类中自己创建了一个唯一的对象,供外部使用(饿汉式、懒汉式)。

❸工具类中的构造函数都是私有的。工具类中的函数都是静态的,可以由类名直接调用,没有创建对象的必要性。

⑦关键字this:

含义有两个:一是调用当前实例对象;二是调用本类的另一个构造函数。

this的应用:

❶当定义成员函数时,函数内部要用到调用该函数的对象,就用this来代表这个对象。也用于区分同名的成员变量和局部变量。

❷一个类中的成员被使用,都必须要有对象调用才可以。有好多的地方,由于是在本类中的调用,从而省略了this,但它必然存在。尤其是,在多态的应用中,极其重要。

❸在构造函数中调用本类的另一个构造函数时,this一定要放在该构造函数的第一行,被优先执行。

 

七、静态

①关键字static:

用于修饰类的成员(包括成员变量、成员函数和内部类)。

②静态的特点:

❶被static修饰的成员随着类的加载而加载,优先于对象而存在,被该类的所有对象所共享。

❷当类中的成员被静态修饰后,除了可以被本类的对象调用之外,还可以被类名直接调用。

❸静态成员只能访问静态成员。

❹静态方法只能覆盖静态方法。

③类变量和实例变量的区别:

❶存放位置不同

类变量(即静态的成员变量),存储在方法区(共享区、数据区)中,实例变量(即非静态成员变量),随着对象的创建而存在,存储在堆内存中。

❷生命周期不同

类变量的生命周期最长,随着类的消失而消失;实例变量的生命周期,随着对象的消失而消失。

④静态修饰符使用的注意事项:

❶静态方法只能访问静态成员;非静态方法既可以访问静态成员,也可以访问非静态成员。

❷静态方法中不可以使用this、super关键字,因为静态优先于对象而存在。

⑤静态的利弊:

❶好处

将对象的共享数据进行单独存储,节省内存空间;可以被类名直接调用。

❷弊端

对于成员变量,生命周期过长;对于成员函数,其内部只能访问静态成员,访问有局限性。

⑥静态的定义规则:

❶对于类变量,当所有的对象中出现共有数据时,该数据应该被静态修饰,存储于方法区(共享区、数据区)中。而实例变量,是每个对象特有的数据,要定义成非静态,存在于堆内存中。

❷对于成员函数,当功能内部没有访问到非静态数据(对象的特有数据)时,该方法可以定义为静态的。若是访问到了非静态数据,就不可以定义为静态的。

⑦静态代码块:

格式:static{需要执行的语句;}

特点:随着类的加载而执行,只执行一次,并且优先于主函数。

作用:用于给类进行初始化。

⑧静态的应用-工具类:

工具类,即为了完成某些特定的功能,而将这些作用相同的功能进行封装的类。

❶工具类中的方法都是静态的,可以通过类名直接调用。工具类中的构造方法都是私有的,因为用类名就可以实现对象所具有的功能,没有创建对象的意义。

❷将工具类中的构造函数私有化,可以统一工具类的调用方式,更加严谨。

 

八、主函数:

主函数是一个特殊的函数,是静态的。作为程序的入口,被JVM识别并调用。

①主函数的定义:

public:代表着主函数的访问权限是最大的。

static:代表主函数随着类的加载已经存在了。

void:代表主函数没有具体的返回值。

main:不是关键字,但作为一个特殊的单词,可以被JVM识别。

(String[] args):主函数的参数列表,参数的类型是一个字符串类型的数组,该数组中的元素是字符串。

②主函数的识别:

❶主函数的格式,是固定的。

❷JVM只识别固定参数列表的主函数,将其作为程序的入口。

❸拥有不同参数列表的其它同名函数,能够以函数重载的方式与主函数同时存在,但不能被JVM识别。

③主函数的调用:

❶JVM在调用主函时,传入的是一个字符串类型的数组(new String[0])。

❷因为主函数是静态的,可以在程序运行的同时,向主函数中传值。

❸主函数会将收到的数据,封装和存储进其自身的数组中,并以数组角标的形式,为每一个传入的元素进行标号。主函数的数组长度,由所传入的数据决定,其格式为:java 函数名 字符串 字符串 ...

④对象的初始化过程:

当用new关键字创建了一个对象之后,系统会对其进行相应的初始化。

类名 对象名 = new 类名();

❶先在内存中加载其对应的类的字节码文件(类名.class)

❷执行该类的static代码块,给类进行初始化

❸在栈内存中给对象名变量分配空间

❹给栈内存中的对象名进行默认初始化,赋值null

❺在堆内存中开辟空间,分配内存地址

❻在堆内存中建立对象的特有属性,并进行默认初始化

❼给对象的特有属性进行显示初始化

❽执行该类的构造代码块,给对象进行共有属性的初始化

❾给对象进行其所对应的构造函数初始化

❿将对象在堆内存中的首地址,赋值给栈内存中的对象名,实现引用

⑤对象的调用过程:

❶对象调用的过程,是在栈内存中完成的

❷对象调用的实现,是在堆内存中完成的

❸对于静态成员变量,对象在栈内存中的引用,指向对象在堆内存中的实体,堆内存中的实体有相应的引用,指向方法区中的目标数据,从而实现调用。

❹对于非静态成员变量,对象在栈内存中的引用,指向对象在堆内存中的实体,堆内存中的实体直接调用,存在于堆内存中的自身的相应的变量,从而实现调用。

❺对于成员函数,与静态成员变量的调用方式相同。

❻每一个线程都会有一个方法调用栈,用来跟踪该线程运行中的一系列的方法调用过程。栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候,就会向方法栈压入一个新帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。

 

九、Java文档注释的编写:

Java中的注释有三种:

//:单行注释

/*(被注释的信息)*/:多行注释

/**(被注释的信息)*/:Java文档注释专用

注释的特性:多行注释只可以嵌套单行注释,不可以嵌套多行注释。

①Java注释文档的制作前提:

若要制作一个类的注释文档,则该类必须是共有的,才能够向外暴露其内部的功能。

②Java文档注释的作用:

对程序的功能进行说明,方便程序开发者使用该程序的功能。

③Java文档注释的格式:

❶将该程序的所有功能,作者信息,版本信息等放在类的前面。

@author:作者信息

@version:版本信息

❷将该类中各个方法的具体功能,所需要传递的参数列表的形式,返回值类型等放在方法的前面。

@param:各个参数的说明

@return:返回值说明

④注释文档的生成方法:

运行:javadoc -d 指定文件的存放目录 类的源文件全名

❶如果需要生成作者和版本信息,需要在-d后面单独添加-author、-version,各个字段间用空格隔开。

❷如果磁盘中没有指定的目录,则系统会自动新建一个。

⑤注释文档的生成规则:

❶在程序中编写的注释文档,系统只会抽出被public和protected修饰的部分,其它部分不会被抽取。

❷默认构造函数的权限和所属类的权限保持一致,其权限随着类权限的变化而变化。

 

十、单例设计模式

设计模式的意义:解决某一类问题最行之有效的方法。

Java中有23种设计模式。

①单例设计模式:

解决一个类在内存中,只存在一个对象的问题。

②单例设计的规则:

❶将构造函数私有化。

❷在类中创建一个静态的本类对象。

❸提供一个公有并且静态的方法,可以让外部获取到这个对象。

③单例设计的实现方法:

❶饿汉式

该类一被加载,就创建一个对象。

特点:安全,方便。

❷懒汉式

当该类的方法被外部调用时,才创建对象,也叫做对象的延时加载。

特点:在多线程时,为了解决安全问题,要使用双重判断,并且在第二次判断之前,加上同步。效率比较低,因为判断即会消耗资源。

④单例的好处:

❶内存中只有一个对象,节省系统开销。

❷实现了本类对实例化的有效控制。

 

十一、面向对象的三大特征之一:继承

①继承的由来:

对类的描述的不断抽取,可以形成更加抽象的类;反之,对类的描述的不断扩展,可以形成更加具象的类。

②继承的特点:

❶提高了代码的复用性。

❷让类与类之间产生了关系,实现了程序的多态性。

❸不能为了获取其它类的功能,为了简化代码而继承。必须是类与类之间有所属关系,才可以继承。所属关系即is a。

③关键字extends:

继承,表示一个类是另一个类的子类。

❶Java只支持单继承,也支持多实现。

❷Java支持多层继承,也就是一个继承体系。

❸若要使用某个体系,应先查阅父类的描述,因为父类中定义的是该体系中的共性功能。在使用这些功能时,要创建最子类的对象,原因有两个:一是有可能父类不能创建对象;二是创建子类对象可以使用更多的功能,包括共性的功能,也包括特有功能。(即查阅父类功能,创建子类对象使用功能)

④关键字super:

含义有两个:一是表 示父类对象的引用;二是调用父类的构造函数。

❶子类中的所有的构造函数都默认包含一个父类的空参数构造函数,即super()。

❷使用super调用父类的构造函数时,一定要放在子类构造函数的第一行,被优先执行。

❸在子类构造函数中,super与this不能同时存在。

❹若要子类构造函数调用父类的非空参数构造函数,需要显式指定。

⑤函数的覆盖(重写):

子父类中出现了同名函数,子类直接调用自身的方法,父类的方法就被隐藏了起来,如同父类的方法被覆盖(重写)。

❶覆盖的意义:

子类拥有父类的功能,却有与父类不同的实现方式,这时就保留父类功能的定义,重写父类功能的内容。

❷覆盖的应用:

可以用于功能的扩展。

❸覆盖的前提:

子类覆盖父类,必须保证子类权限不小于父类权限;静态只能覆盖静态。

❹覆盖的格式:

子父类函数的定义要一模一样,包括修饰符、函数名、参数列表。

⑥子类的实例化过程:

❶系统在加载子类之前会先加载其父类,并逐级上溯。

❷子类对象在创建时,会先加载父类的内容,再加载自己的内容,包括静态代码块、构造代码块、构造函数。子父类的内容同时存在。

⑦关键字final:

含义是最终,可以修饰变量(包括成员变量和局部变量)、函数和类。表示变量只能被赋值一次,之后以常量的形式存在;表示方法不能被重写;表示类不能有子类。

❶内部类被定义在局部位置上时,只能访问被final修饰的局部变量。

❷final的应用:

当描述事物时,有一些数据的值是固定的,为了增强阅读性,都会给这些值起个名字,然后用final修饰,如:final PI=3.1415926;。

⑧抽象类:

❶关键字abstract:

抽象方法、抽象类的修饰符。抽象的方法没有方法体,直接以分号结尾。只要该类中有一个抽象的方法,则该类必须声明为抽象类。抽象类不能用new创建对象。抽象类中可以没有抽象的方法,只是用来限制该类不能够创建对象。

❷抽象类中功能的实现方式:

抽象类只有被其子类继承,并且将其所有的抽象方法都覆盖之后,通过创建其子类的对象,来调用子类自身的方法,从而实现该抽象类的功能。

❸抽象类的应用:

当在描述事物时,如果出现了有明确的功能,却拥有不确定的实现方式时,就可以通过定义抽象类来进行描述。

抽象类可以强制其子类必须覆盖它的抽象方法,否则无法创建对象。

❹模板设计模式:

当定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而且确定的部分在使用不确定的部分。那么,就可以将不确定的部分以抽象的方式暴露出去,由该类的子类去完成。

⑨接口:

可以理解为,接口是一种特殊的抽象类。接口中的所有方法都是抽象的,同时,接口中只有常量。

❶关键字interface:

用于定义接口,功能同class。接口中的常量(全局常量)和方法都有固定的格式,若是修饰符出现空缺,系统会为其自动补齐。

常量:public static final 数据类型 常量名=常量值;

方法:public abstract 返回值类型 方法名(参数列表);

❷关键字implements:

用于实现接口,功能同extends(is a)类似,可以理解为:like a。

一个类可以多实现,也可以在继承的同时再多实现,多实现时各个接口间以逗号隔开。若是子类中没有将接口中的抽象方法全部覆盖,则此类是一个抽象类。

接口与接口间是继承关系,可以多继承。接口的多继承会有风险,有可能会包含返回值不同的同名函数,此时编译会失败。

❸实现与继承的区别:

继承表示子类必须是父类中的一员,实现表示子类可以拥有接口的功能,不是必须的。继承是一个体系,接口是一种扩展。

❹接口的特点:

接口是对外暴露的规则(降低了耦合性);接口是程序的功能扩展;接口可以被多实现;接口间可以多继承。

 

十二、面向对象的三大特征之一:多态

多态,可以理解为事物的存在拥有多种表现形态。

由于继承的存在,可以让事物从属于一个体系。这个事物本身既是一个特殊的个体,又是其所属体系中的一个成员,从而可以拥有多种表现形态。

①多态的体现:

❶将父类的引用指向子类的对象,或者说父类的引用可以接收子类的对象。

❷函数中也存在多态,函数的重载和重写(覆盖),就是同名函数拥有不同的表现形式,也是一种多态的体现。

②多态的前提:

类与类之间有关系,要么继承,要么实现。

③多态的好处:

提高了程序的扩展性和后期的可维护性。

④多态的弊端:

❶父类的引用只能访问父类的成员。

❷调用时,对于成员变量和静态成员函数,指向的是父类的数据;对于非静态成员函数,调用的是子类的非静态成员函数(存在函数覆盖的就调用子类的成员函数,没有被覆盖的成员函数子父类共享)。

⑤多态中对象的类型转换:

❶当父类引用指向子类对象时,子类对象会被系统自动提升为父类的类型,即向上转型。

❷若想将被提升了类型的子类对象还原成自己的类型,需要进行强制转换,即向下转型。

❸引用数据类型的转换方式,与基本数据类型的转换方式相同。

❹不能够将一个父类对象强制转换成它的子类的类型。

❺不能够将一个非本类类型的对象,转换成本类的类型。

❻对于多态而言,其时自始至终都是子类对象在做类型的转换。

⑥关键字instanceof:

测试一个对象是否是某个类的实例。

❶当判断一个对象是否属于某个类时,若是需要多重判断的话,应将最抽象的类(该体系中最父类的类)写在最后面。

❷instanceof一般应用于两种情况下:一是子类的类型是有限的;二是只使用有限的子类类型。

⑦多态中的非静态成员函数的特点:

❶在编译时期,参阅引用型变量所属的类中,是否有被调用的方法,如果有则编译通过,如果没有则编译失败。

❷在运行时期,执行对象所属的类中,该对象自己的方法。

❸非静态成员函数在多态中调用时,编译看左边,运行看右边。也就是说,编译看父类,运行用子类。

⑧多态中的静态成员函数的特点:

无论编译还是运行,都看左边。因为,静态随着类的加载而加载,只要父类的引用还在,则必指向父类的静态成员函数。

⑨多态中成员变量的特点:

无论编译还是运行,都看左边(引用型变量所属的类,即父类)。

⑩多态的应用:

当接口实现多态时,既可以实现接口自身的功能扩展,又可以实现其调用者的程序扩展。

⑪Object['ɔbdʒikt]类:

Object类是类层次结构的根类。每个类都使用Object作为超类。所有对象(包括数组)都可以实现这个类的方法。

调用Object类中的方法,也是多态应用中的一种。

❶equals['i:kwəlz]方法:

public boolean equals(Object obj)

比较其它某个对象是否与此对象相等,对于引用对象比较的是地址值。

通常一个类会对Object类的equals方法进行覆盖,但是,如果比较中用到了该类中的特有数据,那么就需要进行类型判断以及类型转换(向下转型)才可以继续比较。

❷toString['tu:ˌstriŋ]方法:

public String toString()

返回该对象的字符串表示形式(类名@哈希值)。

其另一表现形式为:

getClass().getName()+’@’+Integer.toHexString(hashCode())

(['getˌkla:s]['getˌneim][æt]['intidʒə]['tu:ˌheks][striŋ]['hæʃˌkəud])

通常一个类会对Object类的toString方法进行覆盖,返回自己定义的表示信息,便于理解。

❸getClass方法:

public final Class<?> getClass()

返回此对象运行时该类的Class对象。该类的Class对象是由表示该类的static synchronized方法锁定的对象,即该类的字节码文件。

返回形式为:Class 类名

Class<T>:T表示由此Class对象建模的类的类型,即类名。

例如:String.class的类型是Class<String>。如果将被建模的类未知,则使用Class<?>。

❹hashCode方法:

public int hashCode()

返回该对象的哈希码值。一般是通过将该对象的内部地址转换成一个整数来实现的。

❺wait方法(只用于同步)

public final void wait()

throw InterruptedException([intə'rʌptid][ik'sepʃn])

当前线程等待,一直持续到到其它线程调用此对象的notify()方法或者notifyAll()方法。

如果当前线程在等待通知之前或者正在等待通知时,任何线程中断了当前线程,抛出中断异常。

当前线程必须拥有此对象监视器(即同步锁)。

❻notify(['nəutifai])方法(只用于同步)

public final void notify()

唤醒在此对象监视器(同步锁)上等待的单个线程。如果所有线程都在此监视器(同步锁)上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。

❼notifyAll方法(只用于同步)

public final void notifyAll()

唤醒在此对象监视器(同步锁)上等待的所有线程。