抽象方法:
抽象方法由来:当多个类中出现功能相同,单功能主体不同时,可以进行向上抽象(抽象至基类),这时只抽取功能定义,而不抽取功能主体。
特点:
1、 抽象方法定义在抽象类中。(若有抽象方法,则该类一定是抽象类,但是抽象类,不一定要有抽象方法。为了不让用该类建立对象,可以把该类申明为抽象类)
2、 抽象方法由abstract进行修饰
3、 偶像类不可以用new创建对象,因为有无意义的抽象方法。
4、 抽象类若要被使用,需要由子类进行复写所有抽象方法,若没有复写完所有抽象方法,则子类依然是抽象类
5、 抽象类和一般类一样。仅仅是说明自己里面有抽象方法;
6、 抽象类中可以不定义抽象方法,这样做仅仅是不让该类创建对象;
继承、抽象练习:
这里,我们定义了员工类。在员工中,存在经理和普通员工。他们共同都有工作这个方法,但是工作的内容不一样。因此将该方法抽象。在写经理类和员工类的时候再更具具体从事的工作的不同,我们复写该方法
模板类方法设计模式:
定义功能时,功能的一部分是确定的,而确定的部分在使用不确定的部分时,那么就需要将不确定的部分暴露出去,由子类去完成。即:去外面建立一个类,等子类去复写。
优点:降低了具体链接和程序的耦合性,提高了功能扩展性,提供了规则。
里面的final防止该函数被复写。
接口:
基本理解:
可以认为是一个特殊的抽象类,其中的方法都是抽象的。总结一下就是,接口就是对外暴露的规则。
特点:
1、 其中的成员有固定的修饰符:
常量为:public static final
方法为:public abstract
2、 接口中的方法要被子类全部实现一遍之后才能使用,否则子类为抽象类
3、 接口可以被多实现(因为无函数主体,则子函数可以随意改变。这也是对单继承的补充)
4、 接口可以实现多继承(因为无函数主体)
多态:(为不确定的子类预留了位置,但所有的子类具有相同的功能)
多态的体现:
父类的引用指向了自己的子类对象,则子类对象可以上转型也可以下转型。父类的引用可以接受子类的对象。
Eg:Animal cat = newCat();
多态的前提
必须是类与类之间有关系(要么继承要么实现)
多态的好处
提高了代码的复用性,通常存在复写,提高了扩展性。
例如:我们在创建动物的类型,动物都有自己吃的方法,但是每种动物吃的内容不一样。在后期扩展动物类型,而想调用他们都有的吃的方法,可以使用多态来完成。
多态的弊端
虽然提高了扩展性,但只能使用父类的引用访问父类的成员。
代码特点
在编译时:参阅引用型变量所属类中是否有调用方法;
在运行时:参阅对象所属类中是否有调用方法
当有静态成员函数时,若父子都有,则查阅父类的方法。
多态调用的总结:
1、 成员函数在编译时看左边,运行时看右边(原因:存在复写问题)
2、 成员变量,无论编译还是运行,都参考左边(原因:无法复写)
3、 静态成员函数,无论编译还是运行,都参考左边(原因:在创建对象时,你能够看到的是由左边类型所申明的类型)
多态应用举例:
在安装电脑主板时,主板在其上预留了显卡,声卡的插槽,虽然显卡、声卡品种很多,但是基本功能却都一致(打开和关闭)。因此我们总结出他们共有的功能,并将这些功能创建为借口。在使用对应的卡时,利用基类借口类,调用打开、关闭方法。
Object类
Object类为所有类的超类。它里面的方法为所有类所共享。只是在实现形式上有些区别(有时需要复写)。
常用方法:
1.
boolean |
对于任何非空引用值x
和y
,当且仅当 x
和 y
引用同一个对象时,此方法才返回true
。
复写其方法:
2.
toString() |
返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@
”和此对象哈希码的无符号十六进制表示组成
3.
int | hashCode() |
针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的)
4.
Class<?> | getClass() |
表示此对象运行时类的Class
对象。
内部类
当描述的事物内部还有事物,则可以用内部类来描述,因为外部类事物用到了内部类事物的内容(变量或函数)。
Eg:将心脏类定义在身体类内部。心脏可以访问身体的成员,但是它不想暴露给别的成员访问。
访问规则:
1. 可以直接访问外部类的成员(包括私有,原因:因为内部类持有了外部类引用 outer.this)
2. 外部类访问内部类需要建立对应的对象。(若内部类非私有)
Outer.Innr in = newOuter().new Inner();
3. 内部类若在外部类成员位置上,则可以被成员修饰符所修饰
1) Private:将内部类在外部类中进行封装
2) Static : 内部类就具备static的特性,(出现访问局限,只能直接访问外部类静态成员)(若内部类中有static 成员,则该内部类一定要是静态的)
4.内部类可以继承外部类
访问方式
1. 外部其他类访问static内部类的非静态成员:
New外部类().内部类().非静态功能();
2. 外部其他类访问static内部类的静态成员:
外部类().内部类().静态功能();
3. 当外部类静态的方法访问内部类时,所访问的内部类需要为静态的。
(因为静态方法先于类而开辟)
局部内部类(即定义在方法中的类)
1. 不可以被成员修饰符修饰;
2. 可以直接访问外部类成员(因为还持有外部类的引用)
3. 不可以访问他所在局部中的变量
4. 只能访问用final修饰的局部变量
注:只有在执行方法的时候才对该类进行加载
匿名内部类
1. 匿名内部类的前提:
内部类必须是继承一个类,或者实现接口。(因为要去复写方法采用匿名内部类)
2. 匿名内部类的格式:
New父类接口()
{
子类内容;
}
3. 匿名内部类就是匿名的子类对象,而且这个对象有点胖——带内容的对象;
4. 匿名内部类定义的方法最好不要超过3。(过多代码臃肿)
注:其局限性:一般用在复写外部类的方法上。(因为在类只有1-2个方法被复写,而且不常用时,我们临时用匿名内部类来创建对象,简化书写)
异常处理
概念:
Java对不正常情况进行描述后的对象体现;可对其进行封装。
对于严重的问题,java用error描述(不使用针对性代码进行处理)。
对于不严重的问题,java用exception描述(使用针对性代码进行处理)。
语法:
常用方法:
1、
toString |
2、
| printStackTrace |
3、
getMessage |
多异常处理
1. 在申明异常时,建议申明更为具体的异常,这样可以具体处理。
2. 申明几个异常,就应该有几个catch块,若多个异常存在继承关系,父异常catch块放在最下边。(不然父类异常把其他异常都处理了,处理过程有点像不加break的switch语句)
3. 建立catch处理时,catch中一定要定义具体的处理方式。不要简单一句e.printStackTrace(),也不要简单地输出一条输出语句。
执行过程:
当程序遇到异常时,便会跳出该程序,去找上一层程序的catch语句。
自定义异常
因为项目中会出现特有的异常问题,并且这些异常问题并未被封装,则可以将特有问题按照自定义进行封装。
当异常由throw抛出,则必须:
1. 在内部try catch处理(只要问题能在内部解决就不用抛出);
2. 或者在函数中继续抛出,让函数的调用者处理。(throws Exception)
3. 因为父类已经把异常信息操作完成,所以再累只要在构造函数,将异常信息传递给父类,父类就可以通过getMessage方法获取。
注意:
1. 当函数内类抛出异常,函数一定要申明
继承Exception原因
异常有一个特点:因为异常和异常对象都被抛出。它们都具备可抛型,这个可抛型是Threable这个体系中独有特点。只有这个体系中的对象才可以被throws和throw操作。
Throw与throws的区别
1. Throws用在函数上,throw用在函数内
2. Throws后跟异常类,可以跟多个。Throw后跟异常对象
Exception中特殊的子类异常RuntimeException
若在函数内抛出,则函数上不需要申明。
若在函数上申明,调用该函数时不需要进行异常处理。
原因:当异常发生,希望程序停止。因为程序中出现了无法继续的情况,希望能被程序员修正。
自定义异常时,若该异常的发生无法继续进行运算,就让自定义异常继承RuntimeException。
Finally代码块
一定会执行到的代码。(除非在其前有System.exit(0),退出虚拟机)
通常用于关闭资源用(只要调用资源就一定要有关闭动作,即使有异常产生,我们依然需要对资源进行关闭)
异常在子类覆盖中的体现
1. 子类在覆盖父类时,若父类抛出异常,那么子类覆盖该方法时,只能抛出父类异常或者该父类的子类异常。
2. 若父类方法抛出多个异常,则子类再覆盖方法时,只能抛出父类异常的子类集
3. 若父类或者接口方法中无异常抛出,那么子类在覆盖方法时也不可以抛出异常。如果发生异常,就必须自己用try catch处理掉而不能抛出。
异常体系:
Throwable:
——Error
——Exception
——RuntimeException
特点:
1. 异常体系中所有类及建立的对象都具有可抛型(即可被throws和throw操作)
2. 当由throw抛出异常,若未进行try处理,就一定要用throws申明抛出。
(RuntimeException除外,其可以不申明)
3. 若申明异常,则调用者可抛可try
异常的分类:
1. 编译时被检测的异常(若无抛,无try则编译错误)
2. 运行时异常(编译时不检测)。当运行时发生该异常,程序停止,需要对代码进行修改。
异常的优点
1. 将异常进行了封装
2. 将正常和异常的代码进行分开处理,方便程序的阅读。
异常的处理总结:
1. Try或者抛
2. 调用到有异常抛出的方法时,抛几个异常,catch几个异常
3. 当有多个catch时,父类catch放最下边
4. Catch中的程序最好定义针对性的处理方式
5. 当捕获到异常,本功能处理不好就继续在catch中抛出。
异常的注意事项
1. 子类抛出的异常必须是父类异常的子集
2. 如果父类或者接口无异常抛出时,子类写方法时,不能抛,只能try
3. 在抛出异常后,他的下一步是直接找catch去执行,而不经过try
异常例子:
1. 可处理异常
其结果为:
在这里申明了可处理的错误,则调用try catch进行处理。程序从出现错误处跳转到catch中,然后继续执行代码。
2. 不可处理异常
结果:
在出现错误后,我们并不打算处理,而是直接抛出给虚拟机处理,并且停止了后续的程序。
注意:
在抛出异常之后不能跟代码,不然编译会报错。