程序基础及设计 12_第1页
程序基础及设计 12_第2页
程序基础及设计 12_第3页
程序基础及设计 12_第4页
程序基础及设计 12_第5页
已阅读5页,还剩76页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

单元4面向对象高级特征Java程序设计基础教程(AI助学)(慕课版)人民邮电出版社本单元将介绍如何使用Java的面向对象程序设计原则来设计和实现一个照片管理应用程序;深入讲解类的封装、继承、多态、抽象类和接口等概念,并通过案例展示其应用。这些案例将帮助读者深入理解面向对象程序设计的精髓,并学会如何灵活设计和组织代码,构建出既灵活又易于维护的应用程序。同时,读者还将学习异常处理机制,以确保应用程序的健壮性和稳定性。掌握这些高级概念和技能后,读者将能够构建更加复杂、优秀的Java应用程序,为生活带来更多便利和乐趣。本章导读Thechapter’sintroduction目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.1.1封装的定义封装将对象的属性和方法组合在一个类中,并隐藏对象的属性和实现细节,仅对外提供公共接口,以保护数据的安全性,提高代码的可维护性和可重用性。在Java面向对象的思想中,可以把封装理解为一道保护屏障,用于防止当前类的代码和数据被外界随意访问。publicclassDemo{publicstaticvoidmain(String[]args){Studentstudent=newStudent();="张三";student.age=-12;student.say();}}classStudent{Stringname;intage;publicvoidsay(){System.out.println("大家好,我是:"+name+",我的年龄是:"+age);}}4.1.2封装的步骤封装将对象的属性和方法组合在一个类中,并隐藏对象的属性和实现细节,仅对外提供公共接口,以保护数据的安全性,提高代码的可维护性和可重用性。在Java面向对象的思想中,可以把封装理解为一道保护屏障,用于防止当前类的代码和数据被外界随意访问。定义类在Java中,类是对象的模板,它定义了一类对象的属性和方法。因此,应该先定义一个类,这个类包含要封装的属性和方法。在类中,应该定义一些私有属性。这些属性只能在类的内部访问,外部无法直接访问。这样可以防止外部代码直接修改对象的状态,保护了对象的数据。定义私有属性01OPTION02OPTION4.1.2封装的步骤提供公共的getter和setter方法虽然类的属性被设置为私有的,但是仍然需要提供一种方式让外部代码能够访问这些属性。getter方法用于获取属性的值,setter方法用于设置属性的值。这些方法是公共的,可以被外部代码调用。在setter方法中,可以添加一些控制代码,以防止设置不合理的属性值。通过以下几个步骤,对4.1.1小节中的代码进行修改。添加控制代码03OPTION04OPTION(1)变量使用private修饰,私有化属性。(2)对外提供使用public修饰的方法,让外部对象可以通过方法访问属性。(3)对可以修改属性的方法进行功能限制,如限制年龄不可以为负数。4.1.2封装的步骤publicclassDemo{//main()函数,程序入口

publicstaticvoidmain(String[]args){//创建一个学生对象

Studentstudent=newStudent();//设置学生的名字为“张三”

student.setName("张三");/*尝试设置一个不合法的年龄(-12),但由于setAge()方法中有检查,这个值不会被设置*/student.setAge(-12);//输出学生的信息

student.say();}}//学生类classStudent{//私有属性,用于存储学生的名字

privateStringname;//私有属性,用于存储学生的年龄

//注意:年龄通常应该是非负的,但在这里只限制了其为int类型,没有特别的约束

privateintage;

//方法,用于输出学生的信息

publicvoidsay(){4.1.2封装的步骤System.out.println("大家好,我是:"+name+",我的年龄是:"+age);}//getter方法,用于获取学生的名字

publicStringgetName(){returnname;}//setter方法,用于设置学生的名字

publicvoidsetName(Stringname){=name;}//getter方法,用于获取学生的年龄

publicintgetAge(){returnage;}//setter方法,用于设置学生的年龄

//注意:这里有一个检查,如果年龄小于0,则输出错误信息并返回,不设置年龄

publicvoidsetAge(intage){if(age<0){System.out.println("年龄不合法,年龄不能是负数");return;//如果年龄不合法,则直接返回,不执行下面的代码

}this.age=age;}}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.2.1继承的概念类的继承是面向对象程序设计中的一个重要概念,它允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法。继承是一种创建类之间关系的方式,它可以在不修改现有类的情况下创建新的类,并在新的类中使用已有类的属性和方法。动物的继承关系如图4.1所示。图4.1动物的继承关系继承通常使用关键字extends,子类继承父类的语法格式如下。class父类{…}class子类extends父类{…}4.2.1继承的概念一个完整的继承关系示例如下://定义一个Animal类,表示动物classAnimal{//动物的名称,使用private修饰符,表示只能在类内部访问

privateStringname;//动物的颜色,同样使用private修饰符

privateStringcolor;//定义一个公共方法play(),表示动物玩耍的行为

publicvoidplay(){//输出动物玩耍时的信息

System.out.println("动物玩得很开心");}//通常这里还会包含其他属性的getter和setter方法

//但为了简洁,这里省略了这些方法的定义}//定义一个Dog类,继承Animal类,表示狗是动物的一种classDogextendsAnimal{//Dog类继承了Animal类的所有非私有属性和方法

//在这个例子中,Dog类没有添加新的属性和方法}4.2.1继承的概念//定义一个Cat类,继承Animal类,表示猫是动物的一种classCatextendsAnimal{//Cat类继承了Animal类的所有非私有属性和方法

//同样,在这个例子中,Cat类没有添加新的属性和方法}//定义一个Test类,用于演示Animal、Dog和Cat类的使用classTest{//main()函数,程序入口

publicstaticvoidmain(String[]args){//创建一个Dog对象

Dogdog=newDog();/*调用Dog对象的play()方法,由于Dog类继承了Animal类的play()方法,这里可以调用play()方法*/dog.play();//创建一个Cat对象

Catcat=newCat();//调用Cat对象的play()方法,同样地,Cat类继承了Animal类的play()方法

cat.play();}}4.2.2方法重写方法重写是指在子类继承父类的方法后,对该方法进行重新定义,以适应子类的特定需求。在方法重写中,子类可以提供对继承自父类的方法的新实现,这样在调用该方法时,实际执行的是子类中的方法。(4)不能重写父类中的final方法,因为final表示该方法不能被子类修改(3)重写的方法不能抛出比父类方法更宽泛的异常(可以抛出相同的异常或其子类异常,或者不抛出异常)(2)访问权限修饰符的限制不能比父类中被重写的方法的访问权限修饰符的限制更严格(1)方法名、参数列表和返回类型必须与父类中被重写的方法相同方法重写需要满足的条件4.2.2方法重写//定义一个Animal类,表示动物classAnimal{//动物的名称,使用private修饰符,表示只能在类内部访问

privateStringname;//动物的颜色,同样使用private修饰符

privateStringcolor;//定义一个公共方法play(),表示动物玩耍的行为

//此方法在子类中会被重写,也称为“被重写的方法”

publicvoidplay(){//输出动物玩耍时的信息

System.out.println("动物玩得很开心");}//通常这里还会包含其他属性的getter和setter方法

//但为了简洁,这里省略了这些方法的定义}//定义一个Dog类,继承Animal类,表示狗是动物的一种classDogextendsAnimal{//Dog类继承了Animal类的所有非私有属性和方法

//在这里,Dog类重写了父类Animal的play()方法

//重写意味着子类提供了一个与父类方法同名、参数列表相同但实现不同的方法继续以动物的继承关系举例,在继承逻辑中,重写猫和狗的玩耍方法。4.2.2方法重写@Override//使用@Override注解来表明该方法意图重写父类方法,并且编译器会检查这一点

publicvoidplay(){//输出小狗玩耍时的信息

System.out.println("小狗玩得很开心");}}//定义一个Cat类,继承Animal类,表示猫是动物的一种classCatextendsAnimal{//Cat类继承了Animal类的所有非私有属性和方法

//Cat类同样重写了父类Animal的play()方法

@Override//使用@Override注解来表明该方法意图重写父类方法

publicvoidplay(){//输出小猫玩耍时的信息

System.out.println("小猫玩得很开心");}}//定义一个Test类,用于演示Animal、Dog和Cat类的使用classTest{//main()函数,程序入口4.2.2方法重写publicstaticvoidmain(String[]args){//创建一个Dog对象

Dogdog=newDog();

/*调用Dog对象的play()方法,由于Dog类重写了Animal类的play()方法,会输出“小狗玩得很开心”*/dog.play();//创建一个Cat对象

Catcat=newCat();//调用Cat对象的play()方法,由于Cat类重写了Animal类的play()方法,会输出“小猫玩得很开心”*/cat.play();}}图4.3方法重写后的输出结果方法重写后的输出结果如图4.3所示。4.2.3super关键字1.访问父类的属性和方法在子类中,如果存在与父类相同名称的属性或方法,则可以使用super关键字明确指示使用的是父类的属性和方法,而不是子类的属性和方法,这样可以避免歧义。下面通过super关键字来访问父类的属性和方法。//定义一个Parent类,作为父类classParent{//定义一个名为value的整型属性,并初始化为10intvalue=10;//定义一个display()方法,用于输出信息

voiddisplay(){System.out.println("Parentclassmethod");}}//定义一个Child类,继承Parent类classChildextendsParent{//在Child类中,定义一个与Parent类中同名的整型属性value,并初始化为20//注意:这并不会覆盖Parent类中的value属性,而是隐藏了它(在Child类内部)

intvalue=20;4.2.3super关键字

//重写Parent类中的display()方法

voiddisplay(){//在Child类的display()方法内部,定义一个名为value的局部变量,并初始化为30//这个局部变量与类的属性名称相同,但它的作用域仅限于当前方法

intvalue=30;//输出信息,表明当前在Child类的display()方法中

System.out.println("Childclassmethod");//使用this关键字引用Child类自身的value属性(值为20)

//注意:这里并不会访问局部变量value,因为局部变量和属性名称相同但作用域不同

System.out.println("Childvalue:"+this.value);//子类自身的属性

//使用super关键字引用Parent类中的value属性(值为10)

/*注意:这里不会访问Child类中的value属性,因为Child类的value属性隐藏了Parent类的value属性*/System.out.println("Parentvalue:"+super.value);//父类的属性

//调用Parent类中被重写的display()方法

super.display();//调用父类的方法

}}4.2.3super关键字2.在子类的构造方法中调用父类的构造方法在子类的构造方法中,可以使用super关键字调用父类的构造方法。这样可以确保父类的构造方法在子类构造方法执行之前被调用,保证了对象的正确初始化顺序。//定义一个Parent类,作为父类classParent{//定义一个带有整型参数的构造方法

//当创建Parent类的对象时,需要传递一个整型值给这个构造方法

Parent(intvalue){//在构造方法中输出一条信息,显示传递的value值

System.out.println("Parentclassconstructorwithvalue:"+value);}}//定义一个Child类,继承Parent类classChildextendsParent{//定义一个带有整型参数的构造方法

//当创建Child类的对象时,需要传递一个整型值给这个构造方法

Child(intvalue){4.2.3super关键字//使用super关键字调用父类的构造方法,并将value参数传递给父类

/*这是必需的,因为Java规定,如果子类构造方法没有调用父类构造方法,那么会自动调用父类的无参构造方法*//*但如果父类没有无参构造方法,则会出现编译错误。所以这里显式地调用了父类的带参构造方法*/super(value);//调用父类的构造方法

//在子类的构造方法中输出一条信息,表示子类的构造方法正在执行

System.out.println("Childclassconstructor");}}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.3.1final修饰类当final修饰一个类时,表示这个类不能被继承,也就是说,这个类是一个“最终类”或“不可变类”。这样可以确保类的稳定性和一致性。示例代码如下。finalclassFinalClass{//类的内容}//无法继承final类//classAnotherClassextendsFinalClass{…}//这行代码会触发编译错误在这个示例中,使用final关键字修饰一个类(FinalClass)时,这个类就被声明为不可继承的。这意味着其他类(AnotherClass)不能通过extends关键字继承final类(FinalClass)。如果尝试这样做,则编译器会报错,指出不能继承一个被声明为final的类。4.3.2final修饰变量当final修饰一个变量时,表示这个变量的值一旦被初始化,就不能再改变。这种变量通常被称为“常量”或“最终变量”。这样的设计有助于增强代码的可读性和可维护性,同时防止程序中的错误赋值。finalintx=10;x=20;//这行代码会触发编译错误,因为x是final变量,所以不可修改其值final通常用来定义一些常量(如在计算过程中使用的常量PI、最大值等),在实际开发中应用广泛。4.3.3final修饰方法final关键字在Java中修饰方法时,表示该方法是一个“最终方法”,它不能被任何子类重写。这种机制可以确保方法的行为在继承体系中保持不变,防止子类意外或错误地修改父类方法的行为。classParent{finalvoidshow(){System.out.println("Thisisafinalmethod.");}}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.4.1多态的概念多态(Polymorphism)是面向对象程序设计中的一个核心概念,它允许不同的对象对同一个函数调用做出不同的响应。多态为不同数据类型的实体提供统一的接口。多态允许使用相同的方法或操作符来对待不同的对象,而无须关心这些对象的具体类型。多态是基于继承和重写(覆盖)机制实现的,大大增加了代码的灵活性、可扩展性和可维护性。在面向对象程序设计中,多态的核心思想是“一个接口,多种实现”。下面通过一个动物类(Animal)和它的两个子类来演示多态的使用。//定义一个Animal类,作为父类classAnimal{//声明一个私有属性name,用于存储动物的名称

privateStringname;//声明一个私有属性color,用于存储动物的颜色(虽然在这个例子中并没有使用到)

privateStringcolor;//定义一个公共方法play(),用于描述动物玩耍的行为

publicvoidplay(){System.out.println("动物玩得很开心");}//注意:通常会添加一些构造方法、getter和setter方法来完善这个类4.4.1多态的概念

//但在这个例子中,为了简洁,省略了这些方法}//定义一个Dog类,继承Animal类classDogextendsAnimal{//重写父类的play()方法,以描述小狗玩耍的特定行为

@Override//使用@Override注解来明确表示正在重写父类的方法

publicvoidplay(){System.out.println("小狗玩得很开心");}}//定义一个Cat类,继承Animal类classCatextendsAnimal{//重写父类的play()方法,以描述小猫玩耍的特定行为

@Override//同样使用@Override注解

publicvoidplay(){System.out.println("小猫玩得很开心");}}//定义一个Test类,用于测试Animal、Dog和Cat类的行为4.4.1多态的概念

classTest{

publicstaticvoidmain(String[]args){//创建一个Dog对象,并将其引用赋给Animal类型的变量animal//这就是多态的一个示例:父类引用指向子类对象

Animalanimal=newDog();/*调用play()方法,因为animal实际指向的是Dog对象,所以会执行Dog类中的play()方法*/animal.play();/*这里应该是animal.play();而不是dog.play();,因为变量名是animal*/

//创建一个Cat对象,并将其引用赋给Animal类型的变量catAnimalcat=newCat();//调用play()方法,会执行Cat类中的play()方法

cat.play();}}4.4.2对象类型的转换1.向上转型向上转型是指将子类的对象引用赋给父类的引用变量。这是一个隐式的转换过程,子类对象可以自动地转换为父类对象,而不需要任何显式的类型转换操作。//定义一个Animal类,它是所有动物的父类classAnimal{//定义一个makeSound()方法,用于表示动物发出声音

voidmakeSound(){System.out.println("Animalmakesasound");}}//定义一个Dog类,继承Animal类classDogextendsAnimal{//重写父类的makeSound()方法,以表示狗发出声音的方式

@Override//使用@Override注解表明该方法重写了父类的方法

voidmakeSound(){System.out.println("Dogbarks");}}4.4.2对象类型的转换//定义一个Cat类,继承Animal类classCatextendsAnimal{//重写父类的makeSound()方法,以表示猫发出声音的方式

@Override//使用@Override注解表明该方法重写了父类的方法

voidmakeSound(){System.out.println("Catmeows");}}//主类,包含程序入口publicclassMain{publicstaticvoidmain(String[]args){//创建一个Dog对象,但将其引用赋给Animal类型的变量myDog//这是一个向上转型的例子,因为Dog是Animal的子类

AnimalmyDog=newDog();//调用myDog的makeSound()方法

//由于Java的多态特性,这里会调用Dog类中重写的makeSound()方法

myDog.makeSound();//输出:Dogbarks}}4.4.2对象类型的转换2.向下转型向下转型是指将父类的引用变量转换为子类的引用变量。这是一个显式的转换过程,因为必须使用强制类型转换操作符“()”来完成转换。AnimalmyAnimal=newDog();DogmyDog=(Dog)myAnimal;//向下转型myDog.makeSound();//输出:Dogbarks进行向下转型时需要注意,如果转换的对象实际上不是目标类型,则会抛出ClassCastException。因此,在进行向下转型时,最好先进行类型检查,确保安全性。修改以上代码,将创建出来的Dog对象强制转换为Cat类型。AnimalmyAnimal=newDog();CatmyDog=(Cat)myAnimal;//向下转型myDog.makeSound();运行程序,输出结果如图所示。4.4.3instanceof关键字instanceof是Java中的一个关键字,用于在运行时检查对象是否为一个类的实例,或者对象的父类是否为该类的父类,或者对象是否实现了特定的接口。instanceof关键字的使用格式如下。objectinstanceofClass其中:object是待检查的对象Class是要检查的类如果object是Class的实例,则返回true,否则返回false。4.4.3instanceof关键字//定义一个Animal类,作为父类classAnimal{}//定义一个Dog类,继承Animal类classDogextendsAnimal{}//定义一个Cat类,继承Animal类classCatextendsAnimal{}//主类,包含程序入口publicclassMain{publicstaticvoidmain(String[]args){//创建一个Dog对象,但将其引用赋给Animal类型的变量myDog//这是一个向上转型的例子,因为Dog是Animal的子类

AnimalmyDog=newDog();//创建一个Cat对象,但将其引用赋给Animal类型的变量myCat//同样是一个向上转型的例子

AnimalmyCat=newCat();//使用instanceof关键字来检查myDog是否为Dog类的实例

//因为myDog实际上引用的是一个Dog对象,所以输出trueSystem.out.println(myDoginstanceofDog);/*输出true,myDog是Dog类的实例*///使用instanceof关键字来检查myCat是否为Dog类的实例

//因为myCat实际上引用的是一个Cat对象,不是Dog对象,所以输出falseSystem.out.println(myCatinstanceofDog);/*输出false,myCat不是Dog类的实例*/}}4.4.3instanceof关键字1.在向下转型时进行类型检查instanceof可以用于在向下转型时进行类型检查,避免出现ClassCastException。//使用instanceof关键字来检查animal是否指向Dog类的实例//如果是,则可以安全地将它转为Dog类型,因为可以确定它的实际类型是Dog或其子类if(animalinstanceofDog){//将animal向下转为Dog类型,这是安全的,因为已经通过instanceof验证了它的类型

Dogdog=(Dog)animal;//安全的向下转型

//现在可以调用Dog类特有的方法,如bark()dog.bark();//调用Dog类的bark()方法}4.4.3instanceof关键字2.判断对象的类型在某些场景下,可能需要根据对象的实际类型执行不同的操作。instanceof可以帮助判断对象的类型。//使用instanceof关键字来检查shape是否指向Circle类的实例if(shapeinstanceofCircle){//如果shape确实指向一个Circle类的实例,那么可以安全地将其向下转为Circle类型

//这是安全的,因为已经通过instanceof检查确认了这一点

Circlecircle=(Circle)shape;//安全的向下转型

//现在可以调用Circle类特有的方法或访问其特有的属性

//例如,假设Circle类有一个draw()方法,可以这样调用它

circle.draw();//假设Circle类有一个draw()方法用于绘制圆形

//或者,如果Circle类有一个获取半径的方法getRadius(),可以这样调用它

doubleradius=circle.getRadius();//假设Circle类有一个获取半径的方法}//如果shape不是Circle类的实例,则要进一步检查它是否为Square类的实例elseif(shapeinstanceofSquare){//如果shape指向一个Square类的实例,则可以将其向下转为Square类型

Squaresquare=(Square)shape;//安全的向下转型

//现在可以调用Square类特有的方法或访问其特有的属性

//例如,假设Square类有一个calculateArea()方法,可以这样调用它

doublearea=square.calculateArea();//假设Square类有一个计算面积的方法

//或者,如果Square类有一个获取边长的方法getSideLength(),可以这样调用它

doublesideLength=square.getSideLength();//假设Square类有一个获取边长的方法}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.5.1抽象类抽象类(AbstractClass)是Java中的一种特殊类,它不能被实例化,但可以被继承。它主要用于定义子类共有的属性和方法,其中可能包含抽象方法(即只有方法签名、没有实现的方法)。抽象类允许子类继承其属性和非抽象方法,并实现其中的抽象方法。抽象类的主要作用是提供一种继承结构,使得子类可以共享和扩展公共的特性和行为,同时保证子类的实现具有一定的灵活性和多样性。4.5.1抽象类1.抽象类的定义抽象类是一种不能被直接实例化的类,它主要用于为子类提供一个通用的类型,定义子类共有的属性和方法。抽象类中可以包含抽象方法,即只有方法签名(方法名、返回类型和参数列表)而没有方法体(没有花括号及其中的实现代码)的方法。抽象方法必须使用abstract关键字进行修饰。任何继承抽象类的子类都必须实现抽象类中的所有抽象方法(提供方法体),除非该子类本身也是抽象类。//定义一个抽象类AnimalabstractclassAnimal{//声明一个抽象方法makeSound()//抽象方法是没有具体实现的方法,只定义了方法签名

//子类必须提供该抽象方法的实现,除非子类也是抽象的

abstractvoidmakeSound();//抽象方法,没有具体实现}4.5.1抽象类2.抽象类的作用(1)抽象类定义了一些通用的方法和属性,为其子类提供了一个基本的结构模板。子类继承抽象类后,可以专注于实现抽象方法,而不必关心基本结构。(2)抽象类可以包含一些抽象方法,子类必须实现这些方法。这种约束保证了子类的一致性,使得子类的实现更加规范。(3)抽象类中可以包含普通方法,这些方法的具体实现可以被子类继承和复用。这样可以避免在每个子类中重复编写相似的代码。下面通过abstract关键字来定义计算形状面积的抽象方法。//定义一个抽象类Shape//Shape类用于表示几何形状,但它本身不表示具体的形状,因此是抽象的abstractclassShape{

//声明一个抽象方法calculateArea()//这是一个没有具体实现的方法,子类必须实现该方法以计算形状面积

abstractdoublecalculateArea();//抽象方法,子类必须实现4.5.1抽象类

//定义一个普通方法display()//这个方法可以在Shape类中直接实现,子类可以复用或覆盖该方法

voiddisplay(){System.out.println("Thisisashape.");//普通方法,子类可以复用

}}//定义一个Circle类,继承Shape类//Circle类表示具体的圆形,并实现Shape类中的抽象方法classCircleextendsShape{//定义一个私有变量radius,用于存储圆形的半径

privatedoubleradius;//构造方法,接收一个double类型的参数来设置圆形的半径

Circle(doubleradius){this.radius=radius;}//覆盖Shape类中的抽象方法calculateArea()//提供具体的实现来计算圆形的面积

@OverridedoublecalculateArea(){returnMath.PI*radius*radius;//使用圆形的面积公式

}}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.6.1接口的定义与作用在Java中,接口是一种抽象的数据类型,它定义了一组抽象方法(没有方法体)及常量(接口中的变量默认是常量,即publicstaticfinal)。接口是一种约定,它规定了实现类必须提供的方法,但不涉及方法的具体实现。Java中的接口使用关键字interface来定义,定义方式如下。interfaceMyInterface{voidmyMethod();//抽象方法,没有具体实现

intMAX_VALUE=100;//接口中的常量,默认是publicstaticfinal}接口实现了多继承机制,定义了统一的规范或协议,使代码实现解耦和复用,支持回调机制,增强了系统的灵活性和可扩展性。4.6.1接口的定义与作用Java中的类是单继承的,但是可以实现多个接口。通过接口,一个类可以具备多个行为,从而实现多继承的效果。(1)实现多继承//MyClass类实现了Interface1和Interface2接口//这意味着MyClass类需要提供Interface1和Interface2接口中定义的所有方法的具体实现classMyClassimplementsInterface1,Interface2{/*实现Interface1或Interface2接口中的method1()方法(假设该方法在两个接口中都有定义)*///如果method1()只在其中一个接口中定义,则只需要满足该接口的规范

@Overridevoidmethod1(){//method1()的具体实现

//这里编写实现Interface1或Interface2接口中method1()方法的代码

}//同样地,实现另一个接口的方法method2()/*如果method2()是在Interface1和Interface2接口中都定义的方法,则需要确保满足两个接口的要求*///如果method2()只在其中一个接口中定义,则只需要满足该接口的规范

@Overridevoidmethod2(){//method2()的具体实现

//这里编写实现Interface1或Interface2接口中method2()方法的代码

}}4.6.1接口的定义与作用接口定义了一组规范,实现这个接口的类必须提供这些规范中定义的方法。这样可以确保实现类具有特定的行为。(2)实现规范//定义一个名为Shape的接口,它表示一个形状//接口中定义了一个方法calculateArea(),用于计算形状的面积interfaceShape{//计算面积的方法,任何实现Shape接口的类都必须提供这个方法的具体实现

doublecalculateArea();}//Circle类实现了Shape接口,表示一个圆形classCircleimplementsShape{//圆形的半径

doubleradius;//实现了Shape接口中的calculateArea()方法

//使用Math.PI和半径的平方来计算圆形的面积

@OverridepublicdoublecalculateArea(){//返回计算得到的圆形的面积

returnMath.PI*radius*radius;}}4.6.1接口的定义与作用接口可以将接口定义和实现分离,使不同的实现类可以灵活地替换,从而降低了类与类之间的耦合度,提高了代码的灵活性和可维护性。(3)代码解耦接口可以用于实现回调机制,让一个对象(通常是实现了某个接口的类的实例)在特定事件发生时调用另一个对象的方法。(4)实现回调//定义一个回调接口,用于在事件发生时执行特定操作interfaceCallback{/***回调方法,在特定事件发生时被调用*/voidonEvent();}//一个事件通知器类,允许注册回调并在事件发生时通知它们classEventNotifier{4.6.1接口的定义与作用//回调接口的一个引用,用于在事件发生时触发回调

privateCallbackcallback;/***设置回调接口的实现**@paramcallback回调接口的实现*/voidsetCallback(Callbackcallback){this.callback=callback;}/***执行某些操作并在操作完成时(如果需要)触发注册的回调*/voiddoSomething(){//执行某些操作

//…//如果回调已设置,则触发回调方法

if(callback!=null){callback.onEvent();}}}4.6.2接口的实现在Java中,接口的实现指的是一个类实现了某个接口,并提供了接口中定义的所有抽象方法的具体实现。通过实现接口,一个类可以获得接口中定义的所有方法,并且必须提供这些方法的具体实现。一个类可以实现一个或多个接口。下面通过定义一个MyClass类来实现MyInterface接口。//定义一个名为MyInterface的接口interfaceMyInterface{//声明了一个抽象方法myMethod(),接口中的方法默认都是抽象的

//抽象方法没有方法体,只提供方法签名(方法名、返回类型和参数列表)

voidmyMethod();//抽象方法,没有方法体}//定义一个名为MyClass的类,该类实现了MyInterface接口classMyClassimplementsMyInterface{//使用@Override注解来表明该方法是从接口或父类中继承或实现的

//这样可以帮助编译器检查方法签名的正确性

@Override//实现MyInterface接口中的抽象方法myMethod()//提供抽象方法myMethod()的具体实现

publicvoidmyMethod(){//输出一条消息到控制台,作为方法的具体实现

System.out.println("ImplementationofmyMethod");}}4.6.3抽象类与接口的区别抽象类和接口是Java中用于实现抽象类型的两种不同机制,它们在使用和设计上有一些区别,如表4.1所示。区别抽象类接口构造方法有没有成员变量有没有普通方法有没有,所有方法均由publicabstract修饰访问权限修饰符public、protected、default均由publicstaticfinal修饰继承、实现单一继承实现多个接口表4.1抽象类与接口的区别目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.7.1单例模式的应用场景及特点单例模式是一种常用的软件设计模式,其主要目标是确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。单例模式的应用场景如下。04当一个全局使用的资源被许多对象频繁访问,且资源只有一个状态时需要控制实例数量的场景,如系统只能启动一个进程,或者一个网络中只能存在一个服务器实例等03创建时耗时过多或耗费资源过多,但又经常用到的对象02需要频繁实例化并销毁的对象014.7.1单例模式的应用场景及特点数据库连接、文件系统、线程池等都是常见的使用单例模式的例子,因为这些资源通常都需要被全局控制,以防止资源的过度使用导致系统性能下降。单例模式的特点02单例类通常包含一个私有的静态变量,用于存储该类的唯一实例01单例类的构造方法必须是私有的,以防止外部类直接实例化该类03单例类提供一个公共的静态方法,用于获取该类的实例4.7.2懒汉式单例模式懒汉式单例模式是单例模式的一种实现方式,其核心是在第一次使用时才创建单例对象,也就是说,它在需要的时候才创建实例。懒汉式单例模式的一种典型实现方式如下。publicclassSingleton{//定义一个私有的静态实例变量,用于存储Singleton类的唯一实例

privatestaticSingletoninstance;//将构造方法私有化,防止外部通过newSingleton()创建实例

privateSingleton(){}//提供一个公共的静态同步方法,用于获取Singleton类的唯一实例

//synchronized关键字用于保证线程安全,确保在多线程环境下只有一个实例被创建

publicstaticsynchronizedSingletongetInstance(){//如果instance为null,则说明尚未创建实例,需要创建一个新的实例

if(instance==null){instance=newSingleton();}//返回Singleton类的唯一实例

returninstance;}}4.7.3饿汉式单例模式饿汉式单例模式是单例模式的另一种实现方式,其特点是在类加载时就完成实例的初始化,也就是说,在程序启动或者单例类加载的时候,单例类的实例就创建并初始化好了。饿汉式单例模式的一种典型实现方式如下。publicclassSingleton{//使用静态块来初始化Singleton类的唯一实例,这是一种线程安全的单例实现方式

//静态块在类加载时执行,而Java类加载器是线程安全的

privatestaticSingletoninstance=newSingleton();//私有构造方法,以防止外部类通过newSingleton()创建实例

privateSingleton(){}//提供一个公共的静态方法,用于获取Singleton类的唯一实例

publicstaticSingletongetInstance(){//直接返回初始化好的唯一实例

returninstance;}}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.8Object类在Java中,Object类是所有类的父类。如果一个类中没有使用extends关键字明确指定这个类的父类,那么这个类的默认父类就是Object类。Object类位于java.lang包中,Java中的每个类都自动引入了这个包,在编程时不需要显式地引入Object类。01toString()方法用于返回一个表示对象值的字符串,默认返回的是类名后跟“@”符号和对象的哈希值的无符号十六进制表示03hashCode()方法用于获取对象的哈希值,这个哈希值主要用于哈希表数据结构05clone()方法clone()方法用于创建并返回当前对象的一个副本02equals()方法用于检查一个对象是否等于当前对象04getClass()方法getClass()方法用于获取对象所属的类的Class对象06finalize()方法当垃圾回收器确定不存在对当前对象的更多引用时,调用finalize()方法4.8Object类下面以一个简单的Person类为例,展示如何重写Object类中的toString()、equals()、hashCode()等方法。publicclassPerson{privateStringname;privateintage;publicPerson(Stringname,intage){=name;this.age=age;}//重写toString()方法

@OverridepublicStringtoString(){return"Person{"+"name='"+name+'\''+",age="+age+'}';}//重写equals()方法

@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;Personperson=(Person)o;returnage==person.age&&Objects.equals(name,);}//重写hashCode()方法

@OverridepublicinthashCode(){returnObjects.hash(name,age);}//getClass()方法继承Object类,无须重写

//…//clone()和finalize()方法一般不建议在常规类中重写,这里省略

//…}目录导航4.1类的封装4.2类的继承4.3

final关键字4.4多态4.5抽象类4.6接口4.7单例4.8

Object类4.9内部类4.10异常处理4.11【商业实例】“银行提款机”项目——转账功能4.12【综合实训】车类定义及接口使用4.9.1成员内部类成员内部类就像其外部类的一个成员,可以有自己的变量和方法,也可以访问外部类的所有变量和方法。但是,成员内部类不能含有静态成员。成员内部类的定义如下。//外部类定义publicclassOuterClass{//外部类的私有成员变量

//外部类中的成员变量对内部类是可见的

privateintouterVariable=1;//定义一个内部类

publicclassInnerClass{//内部类的方法

publicvoidinnerMethod(){//在内部类中可以直接访问外部类的私有成员变量

//因为内部类持有外部类的隐式引用

System.out.println("Inner:"+outerVariable);}}}成员内部类虽然可以访问外部类的所有成员,包括私有成员,但是在成员内部类中不能定义任何静态成员,因为静态成员需要在类加载时就初始化,而成员内部类的对象的创建依赖外部类的实例。4.9.2静态内部类静态内部类是一种特别的内部类。因为它被声明为静态的,所以它的行为与其他的静态成员相同。静态内部类不依赖外部类的实例,而是直接依赖外部类。静态内部类的定义如下。//外部类定义publicclassOuterClass{//外部类的静态成员变量

//因为是静态的,所以不需要外部类的实例即可访问

privatestaticintouterVariable=1;//静态内部类定义

//静态内部类不依赖外部类的实例,可以直接通过类名访问

publicstaticclassInnerClass{//内部类的方法

publicvoidinnerMethod(){//静态内部类可以直接访问外部类的静态成员变量

//因为静态内部类不持有外部类的实例引用,所以可直接访问外部类的类级别的成员

System.out.println("Inner:"+outerVariable);}}}

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论