- 子类和父类
- 子类的继承性
- 1.继承的定义
- 2.子类和父类在同一包中的继承性
- 3.子类和父类不在同一包中的继承性
- 子类对象的构造过程
- 成员变量隐藏和方法重写
- 1.成员变量的隐藏
- 2.方法重写
- 3.访问修饰符protected的进一步说明
- 关键字super
- 1.使用super调用父类的构造方法
- 2.使用super操作被隐藏的成员变量和方法
- final类final方法
- 对象的上转型对象
- 继承和多态
- 抽象类
- 面向抽象
- 接口
- 接口的声明和使用
- 接口和多态
- 接口回调
- 1.接口回调
- 2.接口作为参数
- 面向接口
- 抽象类与接口的比较
- 内部类
- 匿名类
- 1.与类有关的匿名类
- 2.与接口有关的匿名类
- 异常类
- 1.try-catch语句
- 2.自定义异常类
- 泛型类
- 1.泛型类声明
- 2.使用泛型类声明对象
- 3.泛型接口
继承是一种根据已有类创建新类的机制,利用继承可以先创建一个共有属性的一般类,根据一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并且根据需要增加自己新的状态和行为。由继承而得到的类称为子类,被继承的称为父类(超类),父类可以是自己编写的类,也可以是Java类库的类。Java不支持多重继承,即子类只能有一个父类。
在类的声明中,使用关键字extends来声明一个类是另一个类的子类格式如下:
class 子类名 extends 父类名{
…
}
如果一个类的声明中没有使用关键字extends,这个类被系统默认是Object的子类。
子类的成员一部分是子类是自己声明定义的,另一部分是从它的父类继承的。子类继承的成员变量作为自己的一个成员变量,可以被子类中自己声明的任何实例方法操作。子类继承父类的方法作为子类的一个方法,就像是在子类中直接声明的,可以被子类中自己声明的任何实例方法调用。
2.子类和父类在同一包中的继承性如果子类和父类在一个包中,那么子类自然的继承了其父亲中不是private的成员变量作为自己的成员变量,也自然的继承了父类中不是private方法作为自己的方法,继承的成员变量以及方法的访问权限保持不变。
例:
如果子类和父类不在同一个包中,那么子类继承了父类的protected、public成员变量作为子类的成员变量,并且继承了父类的protected和public方法,继承的成员或方法的访问权限保持不变,但子类不能继承父类友好变量和友好方法。
子类对象的构造过程当用子类的构造方法创建一个子类的对象时,子类的构造方法总是先调用父类的某个构造方法,如果子类没有明确地指明父类的哪个构造方法,子类就调用父类不带参数的构造方法。
子类创建的对象:1…将子类中声明的成员变量作为子类对象的成员变量 。2.父类的成员变量也都分配内存空间,但只将其中一部分作为子类对象的成员变量。
子类可以隐藏继承的成员变量。在子类中定义的成员变量和父类中的成员变量同名,则子类的成员变量隐藏了继承的成员变量,即子类重新定义了这个成员变量。
注意:尽管子类可以隐藏从父类继承的成员变量,但是子类仍然可以通过使用父类继承的方法操作被隐藏的成员变量。例:
子类可以隐藏已继承的方法,子类可以通过方法重写来隐藏继承的方法。方法重写是指:子类中定义一个方法,并且这个方法的名字、返回类型、参数个数与从父类继承的方法完全相同。如果父类的方法可以被子类继承,子类就有权力重写重写,一般子类重写了父类的方法。如果子类想要使用被隐藏的方法必须使用关键字super。例:
注:方法重写一定要保证方法的名字、类型、参数个数和类型同父类的摸个方法完全相同,只有这样子类继承的这个方法才能完全被隐藏。如果具有相同的名字,但没有保证方法的类型不同,程序就会出现编译错误,如果子类在准备隐藏继承的方法时参数个数或参数类型不尽相同时,子类就会出现方法重载。重写父类的方法时,不可以降低方法的访问权限。
一个类A中的protected成员变量和方法可以被它的直接子类和间接子类继承,如B是A的子类,C是B的子类,D是C的子类,那么类B、C、D都继承了A的protected成员变量,如果在另一个类中Other,用类D创建了一个对象object,子类D的protected成员变量和方法如果不是从父类继承来的,对象访问这些protected成员变量和方法时,只有Other与D在同一个包中就可以,如果类D的protected成员变量和方法时从父类继承来的,就要追溯到D的祖先类,如果类A和Other在同一个包中,object对象就能访问继承的protected变量和protected方法。
关键字super关键字super有两种用法:一种是子类使用super调用父类的构造方法,另一种是子类使用super调用子类隐藏的成员变量和方法。
1.使用super调用父类的构造方法子类不继承父类的构造方法,因此子类想要继承父类的构造方法,子类就必须在子类的构造方法中使用super切必须使用super来表示,而且super必须是子类构造方法的第一条语句,如果子类的构造方法没有明显的指明使用父类的哪个构造方法,子类会默认继承父类的无参构造方法,如果子类构造方法中没有super,会有默认语句super(),如果父类没有提供无参构造方法,会出现错误。
例:
如果子类和父类的中成员变量同名,子类就隐藏了从父类继承的成员变量,当子类进行方法重写时父类的方法就被隐藏,想要使用父类的方法就要使用super。比如:
super.x=100; super.play();final类final方法
final类不能被继承,即final没有子类,如果一个方法被修饰成了final方法,则这个方法不能被重写。
对象的上转型对象假设B是A的子类或间接子类,用子类B创建一个对象,并把这个对象的引用放到类A声明的对象中,如
A a; B b=new B(); a=b;
那么称对象a是子类对象b的上转型对象。
上转型对象的特点:
1.上转型对象不能操作子类声明的定义的成员变量,不能使用子类声明定义的方法。
2.上转型对象可以代替子类去调用子类重写的实例方法,如果子类重写的方法时实例方法,那么上转型对象调用重写的方法时,就是通知子类对应的子类对象去调用者写方法。
3.上转型对象可以调用子类继承的成员变量和隐藏的成员变量。
可以将对象的上转型对象再强制转换到一个子类对象,这时该子类对象又具备了子类的所有属性和功能。
注:不可以将父类创建的对象的引用赋值给予类声明的对象。
多态是指父类的某个实例方法被其子类重写时,可以各自产生自己的功能行为,指同一个操作被不同类型对象调用时可能产生不同的行为。
如果子类都重写了父类中某个实例方法,把子类创建的对象引用放到一个父类的对象时,就得到了该对象的一个上转型对象,那么这个上转型对象再调用这个实例方法时可能具有多种形态,因为不同的子类在重写父类的实例方法时可能产生不同的行为。
用关键字abstract修饰的类称为抽象类。
抽象类的特点:
1.抽象类中可以有抽象方法
抽象类可以有抽象方法,也可以有非抽象方法。抽象方法只能声明,不允许实现,而且不允许使用final和abstract修饰同一个方法。
2.抽象类不能使用new创建对象
对于抽象类,我们不能使用new运算符创建该类的对象。如果一个肥抽象类是一个抽象类的子类,那么它必须重写父类的抽象方法。
3.做上转型对象
尽管抽象类不能创建对象,但它的非抽象子类必须重写起其中的抽象方法,这样可以让抽象类声明的对象成为其子类对象的上转型对象。
面向抽象的核心思想:
1.抽象细节
面向抽象的第一步就是将经常需要变化的部分分割出来,将其作为abstract类中的抽象方法,不让设计者去关心实现的细节,避免所设计的类依赖于这些细节。
2.面向抽象设计类
面向抽象编程的第二步就是面向抽象类来设计一个新类。把任务分派到子类上。
比如:要设计一个Pillar类,通过Pillar类创建的对象进行计算各种柱体的体积,错误示范:
public class Pillar {
double getBottomArea(double r){
return 3.14*r*r;
}
public double getVolume(double r,double h){
return h*getBottomArea(r);
}
}
上面这种类的设计是不合理的,因为这个Pillar这个类只能计算圆柱体的体积,无法计算其他柱体体积,如果想要计算其他柱体的体积Pillar就会不断修改getBottomArea(double r)方法,这会十分影响Pillar类的设计时间,而且只要算法细节需要变化,设计者就需要不断的修改Pillar类,这就会十分麻烦,不利于维护。正确是要将计算底面积任务交给其他类去做。
正确示范:
public abstract class Geometry {
public abstract double getArea();
}
public class Pillar {
Geometry bottom;//将Geometry对象作为成员
double height;
Pillar (Geometry bottom,double height){
this.bottom=bottom;
this.height=height;
}
void changeBottom(Geometry bottom){
this.bottom=bottom;
}
public double getVolum(){
return bottom.getArea()*height;//bottom可以调用子类重写的getArea方法
}
}
上面设计的Pillar类的对象pillar可以计算各种柱体的体积,因为Pillar类的设计没有依赖底面积的算法细节,将计算底面积的算法细节交给Geometry的各种子类。去实现。
接口Java不支持多继承性,即一个类只能有一个父类,关键字interface定义接口。接口的定义与类的定义相似分为接口和接口体。
接口的声明和使用1.接口声明
接口用关键字interface来声明,格式如下:
interface 接口的名字
2.接口体
接口体中包含常量定义和方法定义两个方法。接口体中只进行方法的声明,不允许提供方法的实现,所以方法的定义没有方法体。例如
interface Printable{
final int MAX=100;
void add(){}
float sum(float x,float y)
}
3.接口的使用
一个类可以通过关键字implems声明自己实现一个或多个接口。如果使用多个接口就需要用逗号进行隔开接口名。例如:
class A implements Printable,Addable
如果类实现某个接口,那么这个类必须实现该类的所有方法,即为这些方法提供方法体。在类中实现接口方法时,方法的名字、返回类型、参数个数及类型必须与接口中完全一致。
注意接口中的方法默认是public和abstract,接口在声明方法时可以省略前面的关键词public和abstract,但是类在实现接口方法时必须使用public来修饰。如果接口方法不是void类型时必须要有一个返回值,是void可以不要返回值。
Java提供的接口都在相应的包中,通过引入包刻意使用Java提供的接口,也可以自己定义接口,一个Java源文件时有类和接口组成的。
接口声明时可以使用public来修饰,public接口可以被任何一个类使用。如果接口不加public修饰称为友好接口类,友好接口可以被同一个包中的类使用。
如果父类实现某个接口,子类也就实现了某个接口,接口可以被继承,即可以通过关键字extends来声明一个接口是领一个接口的子接口。子接口将继承父接口所有的常量和方法。
例:
Java支持继承但不支持多继承,即一个类只能有一个父类,单继承使得程序变得更容易维护和健壮,但增加了子类的负担,使用不当会引起混乱。Java使用了接口,一个类可以实现多个接口,接口可以增加很多类要实现的功能,不同的类可以使用相同的接口,同一个类也可以实现多个接口。
接口的思想在于它刻意增加很多类都需要的功能,使用相同接口类不一定有继承关系,就像把各式各样的商品刻能隶属不同的公司,工商部门要求必须有显示商标的功能,但商标的具体内容由个公司自己去实现。
接口回调是多态的另一种体现。接口回调是指:可以把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量中,那么该接口变量就可以调用被类实现的接口中的方,当接口变量调用被类实现的接口中的方法时,就是通知相应对象调用接口的方法,这一过程称为对象功能的接口回调。
例:
当一个方法的参数是一个接口类型时,如果一个类实现了该接口,就可以把该类的实例引用传值给该参数,参数可以回调类实现的接口方法。例:
设计程序时通常使用接口是因为接口只关心功能,不关心这些功能的具体细节。我们刻意吧主要的经理放在程序设计上。
面向接口也可以体现程序的“开闭原理”,即对扩展开放,对修改关闭,为了满足“开闭原理”,在程序设计好后,首先对接口的修改关闭,否则一旦修改接口,如为它在增加一个抽象类,那么实现该接口的类都要进行修改,程序设计好后应当增加实现接口类的开方法,即在程序中在增加实现该接口的类时不需要修改其他的类。
接口语抽象类的比较:
1.抽象类和接口都可以有抽象方法。
2.接口中值可以有常量不能又变量,而抽象类中既可以有常量,也可以又变量。
3.抽象类中也可以有非抽象方法,接口不可以。
如果某个问题需要使用继承才能更好的解决,例如子类除了实现父类的抽象方法,还需要从父类继承一些变量或继承一些重要的非抽象办法,就可以考虑用抽象类。如果某个问题不需要继承没知识需要若干类给出某些重要的抽象办法的实现细节,就可以考虑使用接口。
类有两种成员:成员变量和方法,类中还可以有类,我们称为这种类为内部类。而包含内部类的类称为外嵌类。内部类跟成员变量和方法一样,一个类把内部类看成是自己的成员,外嵌类的所有成员变量在内部类中仍然生效,内部类也可以调用外嵌类的方法。内部类的类体中不可以声明类变量和类方法。外嵌类可以将内部类的声明对象作为外嵌类的成员。
使用类创建对象时,程序允许我们把类体与对象的创建组合在一起。类创建对象时,除了构造方法了类体,此类体被认为是该类的一个子类去掉类声明后的类体,即匿名类。匿名类是一个子类,由于无名可用,所以不可能用匿名类声明的对象,却可以直接用匿名类创建一个对象。
例如Hello是一个类那么下列代码就是用Hello的一个子类(匿名类)创建对象。
new Hello(){
匿名类类体
}
匿名类可以继承类的方法,也可以重写类的方法,我们用匿名类时,必然是在某个类中直接用匿名类创建对象,匿名类一定是内部类。
假设f(B x)是一个方法
void f(B x){
x 调用B类的方法
}
其中参数是B类对象,那么调用f()时可以向f()的参数x传递一个匿名对象
f(new B){
匿名类的类体继承B类方法或重写B类的方法。
}
例:
假设Computerable是一个接口,那么Java允许直接用一个接口名和一个类体创建一个匿名对象,此类体被认为是实现了Computerable接口的类去掉类声明后的类体,即匿名类。下面就是用实现了接口的类创建的对象
new Computerable(){
实现接口的匿名类的类体;
}
如果某个参数是接口类型,那么可以使用接口名和类体组合创建一个匿名对象传递给方法的参数,类体必须实现接口的全部方法,假设f(Computerable x)是一个方法,Computerable是一个接口:
void f(Computerable x){
x调用匿名类实现接口方法
}
其中参数是接口,那么在调用方法f(x)时可以向f(x)传递一个匿名对象。
f(new Computerable (){
实现接口的方法;
}
)
例:
当运行出现异常时,Java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理。 Java使用try-catch语句来处理异常,将可能出现的异常操作放在try-catch部分,当try部分中某个语句中出现异常后,try部分立刻结束执行,而转向执行相应的catch部分。
1.try-catch语句try-catch语句格式如下:
try{
包含可能发生异常的语句;
}
catch(ExpectiionSubclass1 e){}
catch(ExpectionSubclass2 e){}
各个catch参数中的异常类都是Exception的某个子类,表明try部分可能发生的异常,这些子类之间不能有父子关系,否则保留一个 含有父类参数的catch即可。
2.自定义异常类我们也可以拓展Exception类自己定义异常类,然后规定那些方法产生这样的异常,一个方法在声明时可以使用关键字throws声明抛出所要的产生的若干个异常并在该方法的方法体中给出具体出产生异常的操作,即用相应的异常类创建对象,这将导致该方法结束执行是抛出所创建的异常对象。
泛型类 1.泛型类声明可以使用“class 名称<泛型列表>”声明一个类,为了与普通类区分,这种类称为泛型类。如:
class A
其中,A是泛型类的名称,E是其中的泛型。也就是说,我们没有指定E是何种类型数据,他可以是任何对象好接口,但不能是基本类型数据。
泛型类的类体与普通类的类体完全类似由成员变量和方法构成。
使用泛型类声明对象是,必须指定类中使用的泛型的具体实际类型,如:
可以使用interface 名称<反省列表>"声明一个接口,这样的接口称为泛型接口。例如:
interface Computer
其中Computer是泛型接口名称,E是其中的泛型。泛型类可以使用泛型接口。
Java泛型的主要目的是建立具有类型安全的数据结构,如链表、散列表等数据结构,最重要的一个优点是:在使用这些泛型类建立的数据结构时不必进行强制类型转换,即不要求进行运行时类型检查。



