5、封装
5.1包
Java语言引用包(package)的概念来管理类。
(1)包的概念
包是Java语言提供的一种区别类名的机制,是类的组织方法。在物理存储时,包就对应一个文件夹,包中还可以包含包,称为等级。同一个包中的类名不能重复,不同包中的类名可以相同,在引用某一个包的某一个类时,不但要指定类名,而且要指定报名,通过“.”类表示包的层次,如java.util.Date。
(2)创建包
格式:
package 包名1[.包名2[.包名3]...];
(3)引用包
要在当前类中引用不同包中别的类(该类可能是系统类也可能是自己定义的类),首先必须将该类引用过来,否则编译不通过。如果要使用别的包中的类,必须在源程序中用import语句导入所需要的类。
import语句的格式为:
import包名1[.包名2[.包名3]...].类名|*;
注意
(1)如果一个包中的类很多,可以用“import包名.*”导入该包中的所有类。
(2)在本例中,TeacherTest 类访问Teacher类,必须要保证Teacher是public类(定义时class前必须加关键字public),这将在后面章节讲解。
(3)有时候,包名中有“.”,例如“school.admin”,这并不是说school包中包含了admin包,school.admin仅是一个包名而已。因此,“import school. *;”只是导入了 school 包中的类,并没有导入school.admin包中的类,如果要导入school.admin包中的类,必须使用“import school.admin. *;”。
5.4 使用访问控制修饰符
5.4.1 访问控制修饰符
前文讲解了两个访问控制修饰符,分别是private和public,但是没有对它们进行详细讲解,本节将结合包的相关知识对访问控制修饰符进行详细讲解。
5.4.2 类的访问控制修饰符
在定义类时,有时会在类的前面加上关键字public,示例代码如下。
public class Customer String name; String sex; int age;
写与不写关键字public有何区别?
在不写public的情况下属于默认访问修饰,此时该类只能被同一包中的所有类识别。
如果写了public,该类则是一个公共类,可以被包内、包外的所有类识别。
5.4.3 成员的访问控制修饰符
对于成员来说,访问控制修饰符共有4个,分别是private、default、protected、public,示
例代码如下。
public class Customer {
private String name;
String sex;
protected int age;
public void display(){}
}
name成员为private类型,sex成员为default类型,age成员为protected类型,display成员为public类型。其中,default类型的成员前面没有任何修饰符。
其特性如下。
(1) private类型的成员只能在定义它的类的内部被访问。
(2) default类型的成员可以在定义它的类的内部被访问,也可以被这个包中的其他类访问。
(3) protected类型的成员可以在定义它的类的内部被访问,也可以被这个包中的其他类访问,还可以被包外的子类访问。关于子类,将在后面章节讲解。
(4)public类型的成员可以在定义它的类的内部被访问,也可以被包内、包外的所有其他类访问。
很明显,从开放的程度上讲,private<default<protected
6、继承(重用)
继承:(extends super 方法的重写 父类引用)
Java只支持单继承,不允许多重继承,即一个类只能有一个父类,但是可以由多层继承,即一个类可以继承某一类的子类,如类B继承了类A,类C又可以继承类B,那么类C也间接继承了类A。Object类是Java类层中的最高层类,是所有类的超类。
继承通过在类的声明中加入extends字句来创建一个类的子类:
package extends1;
public class Dialog {
protected String title;
public void show(){
System.out.println(title+”对话框显示");
}
}
如果默认extends字句,则该类为java.lang.Object的子类,即所有类在没有通过extends关键字指定其父类时,则自动默认继承Object。
子类可以继承父类中访问权限设定为:public 、protected、default(父类和子类在同一个包中)成员变量和方法,但是不能继承访问权限为private的成员变量和方法。
注意:子类写了构造方法,则第一行必须调用父类的构造方法,默认super(超类)
super:隐式调用(系统给的);显示调用(自己写的)
6.1子类对父类构造方法的继承
子类无条件地继承父类不带参数的构造方法,当通过子类构造方法创建子类对象时,先执行父类不含参数的构造方法,在执行子类的不带参数的构造方法。
给父类赋值:通过构造方法给所以属性赋值。
6.2子类对父类构造方法的调用
如果子类调用父类的构造函数,则通过super()关键字类实现,但注意super()必须是第一行语句。
6.3方法重写
子类覆盖父类的同名同参同返回的方法(不能降级)
子类也可以重写或覆盖父类中的属性。
6.4子类和父类之间的转换
(1)子类转换成父类
(2)父类转换成父类
父类对象转换成子类对象时,必须要强制转换。
(1)给父类增加一个不带参数的空构造函数,代码错误即可消失。
class Dialog
protected String title;
public Dialog(){}//不带参数的构造函数
public Dialog(String title){
this.title=title;
}
.....
}
6.3.2 使用多态
到此为止,我们还看不出多态有什么作用。实际上,“父类引用可以指向子类对象”能够延伸到以下两个方面。
1.函数传入的形参可以是父类类型,而实际传入的可以是子类对象
示例代码如下。
public class Main ( public static void fun(Dialog dialog)( dialog.show(); public static void main(String[] args)(
在fun方法中,参数类型是父类引用,但在实际调用时传入的却是子类对象。当然,此时调用的也是子类对象的show方法。
下面用一个案例来强化该概念。在显示对话框时,如果要美观一些,最好将对话框显示在屏幕中央。因此,必须编写一个函数来计算当前屏幕的宽度和高度,并结合对话框的宽度和高度将其显示。对于FontDinlog,编写代码如下
package poly2;
class Dialog
public void show()(
System.out.printin("Dialog.show()");
class FontDialog extends Dialog(
public void show()(
System, out.println("FontDialog,show()");
public class Main (
public static void toCenter(FontDialog fd)(System.out.println("计算屏幕数据");fd.show();
public static void main(String[ ] args)( FontDialog fd=new FontDialog();
toCenter(fd);
运行代码,控制台打印结果如图6-10所示
如此达到了相应的效果。但是,toCenter函数存在一
题,例如代码:
public static void toCenter(FontDialog fd)( System. out.println("计算屏幕数据"); fd.show();
2.函数的返回类型是父类类型,而实际返回的可以是子类对象
示例代码如下。
public class Main ( public static Dialog fun()( return new FontDialog(); ) public static void main(String[] args)( Dialog dialog=fun(); dialog.show();
在fun方法中返回的是父类类型,而实际返回的是子类对象。当然,主函数中dialog调用的也是子类对象的show方法。
可以看出,在main函数中根本没有FontDialog类的痕迹,main函数仅仅需要认识Dialog类就能够调用Dialog的所有不同子类的函数,而不需要知道这些函数是怎么实现的。如果fun函数中返回的对象由FontDialog改为ParagraphDialog,main函数不需要做任何修改。
8、抽象类和接口
8.1抽象类
(1)抽象类可以拥有没有方法体的抽象成员,抽象成员的具体代码是在其派生类(子类)中实现的。
(2)抽象类不一定有抽象方法。
(3)抽象类不能创建对象。(不能实例化)
(4)只有抽象类才有抽象方法。
(5)若父类中有抽象方法,继承时要实现方法重写。
(6)关键字:abstract。
(7)抽象类中可以有非抽象类的方法。
(8)抽象类可以有构造方法。
(9)抽象方法的类一定是抽象类,但抽象类中不一定都是抽象方法。
(10)抽象类可以继承非抽象类,也可以包含main()方法。
(11)实现一个接口,但没有完全实现接口中包含的抽象方法的类是抽象类。
(12)继承一个抽象类,但没有完全实现父类包含的抽象方法的类是抽象类。
(13)直接定义了一个抽象方法的类是抽象类。
(14)抽象类的非抽象子类必须实现父类中的抽象方法。
8.2接口
如果一个抽象类中的多有方法都是抽象的,就可以将这个类用另外一种方式来定义,也就是接口定义。
接口(interface)就是方法定义和常量值的集合。从本质上讲,接口就是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有方法的实现。
接口命名要符合Java标识符命名规则。接口与一般的类一样,也具有成员变量与成员方法,但是成员变量一定要赋值,且不能被修改。若省略成员变量修饰符,系统默认为public、static、final;而其成员方法必须是抽象方法,方法钱即使省略修饰符,系统仍然默认public abstract。
(2)实现接口
接口和抽象类相似,只能被继承,不能被实例化,一旦继承一个接口不叫继承,而叫实现。用implements关键字类表示一个类实现某个接口。一个类在实现一个接口时,则该类可以使用接口中的定义的常量,但必须实现接口中定义的所有方法。
(3)接口的继承
与类相似,接口也有继承性。定义一个接口时,可以通过extends关键字声明该新接口是某个已存在接口的子接口,它讲继承父接口的所有变量和方法。与类的继承不相同的是一个接口可以有一个以上的直接父接口,它们之间用逗号隔开,形成父接口列表。新接口将继承父接口中的变量与方法。如果子接口中定义了与父接口同名的常量或者相同的方法,则父接口中的常量被隐藏,方法被重写。
(4)接口的作用
利用接口可以实现多重继承,即一个类可以实现多个接口,在implements子句中用逗号分隔。Java不支持多继承,即一个类只能有一个父类,利用接口可以达到多继承的效果。
接口的作用和抽象类相似,只定义原型,不直接定义方法的内容。
8.3抽象类和接口的比较
(1)接口中定义的变量均是公有的,静态的,最终常量(public static final)。接口中定义的方法(即使没有特别声明)均为抽象的和公共的(public abstract),而抽象类没有要求。
(2)实现接口时需要实现接口中定义的所有方法;抽象类的子类可以全部重写所有抽象方法;也可以不重写,此时子类还是一个抽象类。
(3)接口不能有构造方法,抽象类可以有
(4)接口不能有静态方法,抽象类可以有
(5)接口不能有方法体,抽象类可以有
(6)接口可以实现多重继承
(7)接口不可以实现另一个接口。(但是接口可以继承接口,并可以继承多个接口,但是不能实现接口。)
(8)一个类可以继承抽象类的同时实现一个或多个接口。



