JAVA面向对象

面向对象的思想是一种程序设计的方法论,它将程序的设计和实现分解为对象的创建、操作和交互。面向对象的思想将现实世界中的事物抽象为对象,每个对象包含属性(数据)和方法(行为),并且具有封装、继承和多态的特性。

面向对象的思想强调将程序划分为独立的对象,每个对象负责自己的任务,对象之间通过消息传递的方式交互。这种方式可以提高代码的可维护性、可复用性和可扩展性,使程序更易于理解和修改。

面向对象的思想还提供了一种抽象的方法,通过定义类来描述对象的共同特征和行为,从而实现代码的模块化和组件化。通过继承机制,可以创建新的类并从现有类继承属性和方法,从而减少代码的重复和冗余。

面向对象的特点主要有以下几点:

  1. 封装:将数据和对数据的操作封装在一起,形成一个类,外部只能通过类的接口来访问和操作数据,从而实现了数据的隐藏和保护。

  2. 继承:通过继承,子类可以继承父类的属性和方法,从而减少代码的重复性。并且通过继承,可以实现多态性,即同一个方法可以根据不同的对象调用不同的实现。

  3. 多态:同一种类型的对象,执行同一个方法时,可以有不同的行为表现,这就是多态性。多态性可以提高代码的灵活性和可扩展性。

  4. 抽象:通过抽象,可以将一类对象的共同特征和行为抽象出来,形成类的继承层次结构。抽象可以隐藏对象的具体实现细节,只对外提供接口,从而降低系统的复杂性。

  5. 接口:接口定义了对象与外界之间的通信协议。通过接口,可以实现类之间的松耦合,增加代码的可维护性和可扩展性。

总结来说,面向对象的思想是一种以对象为中心的程序设计方法,通过将程序分解为独立的对象来实现代码的可维护性、可复用性和可扩展性。它是现代软件开发中广泛使用的一种编程范式。


目录

封装

实现封装

案例

题目1

题目2 

题目3

题目4

继承

实现继承

继承关键字 

extends关键字

implements关键字

super 与 this 关键字

final 关键字

Object类

Object类的常用方法

案例

题目1

题目2

题目3

抽象类

实现抽象类

案例 

 题目1

 题目2

接口

接口与类的区别

抽象类和接口的区别

 接口的声明

接口的实现 

接口的继承

 案例

题目1

题目2

多态

向上转型

向下转型

instanceof关键字

import 关键字

案例

题目1

题目2

题目3


封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

要访问该类的代码和数据,必须通过严格的接口控制。

封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

封装的优点

  • 隐藏实现细节

  • 提高代码的可维护性

  • 提供接口

  • 实现数据封装和保护

实现封装

Java通过访问修饰符来实现封装,主要有public、private和protected三种修饰符。

  1. public修饰符:使用public修饰的成员变量和成员方法可以被任何类访问。

  2. private修饰符:使用private修饰的成员变量和成员方法只能被自身类中的其他成员访问,其他类无法直接访问。

  3. protected修饰符:使用protected修饰的成员变量和成员方法可以被自身类、同一包内的其他类以及不同包中的子类访问。

封装还可以通过getter和setter方法来实现。

  1. getter方法:用于获取私有成员变量的值,一般以get开头,返回该成员变量的值。
private String name;

public String getName() {
    return name;
}
  1. setter方法:用于设置私有成员变量的值,一般以set开头,接收一个参数,将参数的值赋给该成员变量。
private int age;

public void setAge(int age) {
    this.age = age;
}

通过getter和setter方法,可以在类的外部访问私有成员变量,同时可以对成员变量的值进行控制和验证。这种方式更加安全和灵活,也符合面向对象编程的封装特性。

案例

题目1

 定义一个类Person,定义name和age私有属性,定义有参的构造方法对name和age进行初始化。在测试类中创建该类的2个对象,姓名、年龄分别为lili、19和lucy、20,在屏幕打印出2个对象的姓名和年龄。

代码

package DEMO230201.encapsulationdemo;
class Person {
    private String name;//私有属性
    private int age;//私有属性

    public Person(String name, int age){//定义有参的构造方法
        this.name=name;
        this.age=age;
    }
    public void read(){ //在屏幕打印出对象的姓名和年龄的方法
        System.out.println("姓名:"+name+",年龄:"+age);
    }

}
public class encapsulation1 {
    public static void main(String[] args){
        Person p1=new Person("lili",19);
        Person p2=new Person("lucy",20);
        p1.read();
        p2.read();
    }
}

运行结果

姓名:lili,年龄:19
姓名:lucy,年龄:20
题目2 

首先定义一个计算长方形面积的类rectangle,要求类中有一个定义长方形左上角和右下角座标的构造函数,以及一个通过长方形右下角座标与左上角座标计算长方形面积,并实例化两个长方形进行测试。

代码

package DEMO230201.encapsulationdemo;
class Rectangle{
    int topLeftX;   //左上的x坐标
    int topLeftY;   //左上的y坐标
    int bottomRightX;   //右下的x坐标
    int bottomRightY;   //右下的y坐标
    public Rectangle(int topLeftX,int topLeftY,int bottomRightX,int bottomRightY){
        this.topLeftX=topLeftX;
        this.topLeftY=topLeftY;
        this.bottomRightX=bottomRightX;
        this.bottomRightY=bottomRightY;
    }
    public void area(){   //计算长方形面积的方法
        int len=bottomRightX-topLeftX;
        int wid=topLeftY-bottomRightY;
        System.out.println("长方形面积为:"+len*wid);
    }
}
public class encapsulation2 {
    public static void main(String[] args) {
        Rectangle r1=new Rectangle(1,8,2,6);   //实例化第一个例子
        r1.area();
        Rectangle r2=new Rectangle(0,2,2,0);   //实例化第二个例子
        r2.area();
    }
}

运行结果

长方形面积为:2
长方形面积为:4
 题目3

设计一个表示图书的Book类,它包含图书的书名、作者、月销售量等私有属性,另有两个构造方法(一个不带参数,另一个带参数),成员方法setBook( ) 和printBook()分别用于设置和输出书名、作者、月销售量等数据。并设计相应的测试Book类的应用程序主类,测试并显示输出提供所有功能的结果。

代码

package DEMO230201.encapsulationdemo;
class Book{
    private String title;
    private String author;
    private int monthlySales;
    public Book(){   //无参构造
    }
    public Book(String title,String author,int monthlySales){   //有参构造
        this.title=title;
        this.author=author;
        this.monthlySales=monthlySales;
    }
    public void setTitle(String title){
        this.title=title;
    }
    public void setAuthor(String author){
        this.author=author;
    }
    public void setMonthlySales(int monthlySales){
        this.monthlySales=monthlySales;
    }
    public void printBook(){
        System.out.println("本书的书名:"+title+",作者:"+author+",月销售量:"+monthlySales);
    }
}
public class encapsulation3 {
    public static void main(String[] args){
        Book b1=new Book();
        b1.setTitle("尘埃落定");
        b1.setAuthor("阿来");
        b1.setMonthlySales(100000);
        b1.printBook();
        Book b2=new Book("命运","蔡崇达",200000);
        b2.printBook();
    }
}

运行结果

本书的书名:尘埃落定,作者:阿来,月销售量:100000
本书的书名:命运,作者:蔡崇达,月销售量:200000
题目4

请创建一个银行帐户类,要求如下:(1)类包括帐户名、帐户号、存款额等私有属性;(3)有三个参数的构造方法(2)可实现余额查询,存款和取款的操作。(3)创建该类的对象,验证以上两项。

代码

package DEMO230201.encapsulationdemo;
class BankAccount{
    private String accountName;
    private String accountNumber;
    private int depositAmount;
    public BankAccount(String accountName,String accountNumber,int depositAmount){
        this.accountName=accountName;
        this.accountNumber=accountNumber;
        this.depositAmount=depositAmount;
    }
    public void balanceInquiry(){   //余额查询
        System.out.println("您好!您的帐户名:"+accountName+",您的帐户号:"+accountNumber+",您当前余额还剩:"+depositAmount);

    }
    public void deposit(int money){   //存款
        depositAmount=depositAmount+money;
        System.out.println("存款成功,当前余额还剩:"+depositAmount);

    }
    public void Withdrawal(int money){   //取款
        depositAmount=depositAmount-money;
        System.out.println("取款成功,当前余额还剩:"+depositAmount);

    }
}
public class encapsulation4 {
    public static void main(String[] args){
        BankAccount b1=new BankAccount("R","1818181818",1000000);
        b1.balanceInquiry();
        b1.deposit(100000);
        b1.Withdrawal(1000);
    }
}

运行结果

您好!您的帐户名:R,您的帐户号:1818181818,您当前余额还剩:1000000
存款成功,当前余额还剩:1100000
取款成功,当前余额还剩:1099000

继承

在JAVA中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类称为子类,现有类称为父类。子类继承父类的属性和方法,使得子类对象(实例)具有父类的特征和行为。

特征

(1)继承关系是传递的。若类C继承类B,类B继承类A(多层继承),则类C既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性和方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。

(2)继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。

(3)继承提供了软件复用功能。(复用性主要是可以多次使用,不用再多次写同样的代码)若类B继承类A,那么建立类B时只需要再描述与基类(类A)不同的少量特征(数据成员和成员方法)即可。

(4)继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。

(5)提供多重继承机制。从理论上说,一个类可以是多个一般类的特殊类,它可以从多个一般类中继承属性与方法,这便是多重继承。Java出于安全性和可靠性的考虑,仅支持单重继承,而通过使用接口机制来实现多重继承。

实现继承

在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

class 父类 {
    ...   // 父类的属性和方法
}
class 子类 extends 父类 {
    ...   // 子类的属性和方法
}

需要注意的是 Java 不支持多继承,但支持多重继承。

继承关键字 

extends关键字

在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

implements关键字

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

super 与 this 关键字

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

                     (super调用父类构造时,一定要放在构造方法的首行上,且只能出现一次)

super.成员变量
super.成员方法(参数1,参数2,...)

this关键字:指向自己的引用。

this.成员变量   //调用本类中的属性
this.成员方法(参数1,参数2,...)   //调用成员方法
this()   //调用本类中的构造方法

在使用this调用类的构造方法时,注意:

  • 只能在构造方法中使用this调用其他构造方法,不能再成员方法中通过this调用其他构造方法
  • 在构造方法中,使用this调用构造方法的语句必须位于第一行,且只能出现一次
  • 不能在一个类中的两个构造方法中使用this互相调用
final 关键字

final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。

final 含义为 "最终的"。

使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:

  • 声明类:

    final class 类名 {//类体}
  • 声明方法:

    修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

注: final 定义的类,其中的属性、方法不是 final 的。

Object类

JAVA提供了一个Object类,它是所有类的父类,每个类都直接或间接地继承Object类,因此Object类通常称为超类。Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。

Object 类可以显式继承,也可以隐式继承,以下两种方式是一样的:

显式继承:

public class Runoob extends Object{
}

隐式继承:

public class Runoob {
}
Object类的常用方法
方法 & 描述
boolean equals(Object obj)

比较两个对象是否相等

String toString()

返回对象的字符串表示形式

案例

题目1

设计一个学生类Student,其数据成员有name(姓名)、age(年龄)和degree(学位)。由Student类派生出本科生类Undergraduate和研究生类Graduate,本科生类Undergraduate增加成员specialty(专业),研究生类增加成员direction(研究方向)。每个类都有show()方法,用于输出数据成员信息。最后请输出下列信息:

代码

package DEMO230201.inheritdemo;
class Student{ //父类Student
    String name;
    int age;
    String degree;
    public Student(String name,int age,String degree){
        super();
        this.name=name;
        this.age=age;
        this.degree=degree;
    }
    public void show(){
        System.out.printf("姓名:"+name+"     年龄:"+age+"     学位"+degree);
    }
}
class Undergraduate extends Student{  //子类Undergraduate父类Student
    String specialty;
    public Undergraduate(String name,int age,String degree,String specialty){
        super(name,age,degree);
        this.specialty=specialty;
    }
    public void show(){
        super.show();  
        System.out.println("     专业:"+specialty);
    }

}
class Graduate extends Student{   子类Graduate父类Student
    String direction;
    public Graduate(String name,int age,String degree,String direction){
        super(name,age,degree);
        this.direction=direction;
    }
    public void show(){
        super.show();
        System.out.println("     研究方向:"+direction);
    }
}
public class inherit1 {
    public static void main(String[] args){
        Undergraduate u1=new Undergraduate("张三",20,"本科","通信");
        Undergraduate u2=new Undergraduate("李四",21,"本科","电子");
        Graduate g1=new Graduate("王五",25,"硕士","通信");
        Graduate g2=new Graduate("刘六",36,"博士","通信");
        u1.show();
        u2.show();
        g1.show();
        g2.show();
    }
}

运行结果

姓名:张三     年龄:20     学位本科     专业:通信
姓名:李四     年龄:21     学位本科     专业:电子
姓名:王五     年龄:25     学位硕士     研究方向:通信
姓名:刘六     年龄:36     学位博士     研究方向:通信
题目2

有工人、服务员、教师、科学家四种角色,其中服务员、工人只有月固定工资(元/月),教师除月固定工资外,还有课酬(元/节)。科学家除月固定工资外,还有科研激励奖(元/季度)。请通过继承设计出相应的类,将各种类型的员工的全年工资打印出来,并测试(张三、工人、4000元/月)、(李四、服务员、3500元/月)、(王五、教师、5000元/月、100元/节,200节/年)、(刘六、科学家、7000元/月、20000元/季度)。

代码

package DEMO230201.inheritdemo;
class Occupation{
    String name;
    String job;
    int monthlySalary;
    public Occupation(String name,String job,int monthlySalary){
        super();
        this.name=name;
        this.job=job;
        this.monthlySalary=monthlySalary;
    }
}
class WaitersWorkers extends Occupation{
    public WaitersWorkers(String name,String job,int monthlySalary) {
        super(name,job,monthlySalary);
    }
    public void printSalary(){
        int yearlySalary=super.monthlySalary*12;
        System.out.println(super.job+super.name+"的全年工资为:"+yearlySalary);
    }
}
class Teacher extends Occupation{
    int remuneration;//课酬
    int number;//课时
    public Teacher(String name,String job,int monthlySalary,int remuneration,int number){
        super(name,job,monthlySalary);
        this.remuneration=remuneration;
        this.number=number;
    }
    public void printSalary(){
        int yearlySalary=super.monthlySalary*12+remuneration*number;
        System.out.println(super.job+super.name+"的全年工资为:"+yearlySalary);
    }
}
class Scientist extends Occupation{
    int researchIncentiveAward;
    public Scientist(String name,String job,int monthlySalary,int researchIncentiveAward){
        super(name,job,monthlySalary);
        this.researchIncentiveAward=researchIncentiveAward;
    }
    public void printSalary(){
        int yearlySalary=super.monthlySalary*12+researchIncentiveAward*4;
        System.out.println(super.job+super.name+"的全年工资为:"+yearlySalary);
    }

}
public class inherit2 {
    public static void main(String[] args){
        WaitersWorkers w1=new WaitersWorkers("张三","工人",4000);
        WaitersWorkers w2=new WaitersWorkers("李四","服务员",3500);
        Teacher t1=new Teacher("王五","教师",5000,100,200);
        Scientist s1=new Scientist("刘六","科学家",7000,20000);
        w1.printSalary();
        w2.printSalary();
        t1.printSalary();
        s1.printSalary();
    }
}

运行结果

工人张三的全年工资为:48000
服务员李四的全年工资为:42000
教师王五的全年工资为:80000
科学家刘六的全年工资为:164000
题目3

根据下述继承关系图,请完成父类Pet 、子类Dog、Penguin的设计,并写一个测试类,测试类中完成狗对象的创建与输出,企鹅对象的创建与输出。

代码

package DEMO230201.inheritdemo;
class Pet{
    String name;
    int health;
    int love;
    public Pet(String name,int health,int love){
        super();
        this.name=name;
        this.health=health;
        this.love=love;
    }
    public String getName(){
        return name;
    }
    public int getHealth(){
        return health;
    }
    public int getLove(){
        return love;
    }
    public void printPet(){
        System.out.print("My name is "+getName()+",my health is "+getHealth()+",my love is "+getLove());
    }
}
class Dog extends Pet{
    String strain;
    public Dog(String name,int health,int love,String strain){
        super(name,health,love);
        this.strain=strain;
    }
    public String getStrain(){
        return strain;
    }
    public void printPet(){
        super.printPet();
        System.out.println(",my strain is "+getStrain());
    }
}
class Penguin extends Pet{
    String sex;
    public Penguin(String name,int health,int love,String sex){
        super(name,health,love);
        this.sex=sex;
    }
    public String getSex(){
        return sex;
    }
    public void printPet(){
        super.printPet();
        System.out.println(",my sex is "+getSex());
    }
}
public class inherit3 {
    public static void main(String[] args){
        Dog d1=new Dog("A",100,20,"牧羊犬");
        Penguin p1=new Penguin("Q仔",100,20,"female");
        d1.printPet();
        p1.printPet();
    }
}

运行结果


My name is A,my health is 100,my love is 20,my strain is 牧羊犬
My name is Q仔,my health is 100,my love is 20,my sex is female

抽象类

当定义一个类是时,常常需要定义一些成员方法描述类的行为特征,但有时这些方法的实现是无法确定的。针对这种情况,JAVA提供了抽象方法来满足需求。

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

实现抽象类

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。

Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。

抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

abstract class 抽象类名称 { 
    属性;
    访问权限 返回值类型 方法名称 (参数){    //普通方法
          return [返回值];
    }
    访问权限 abstract 返回值类型 抽象方法名称 (参数);   ///抽象方法,无方法体
}

声明抽象方法会造成以下两个结果:

  • 如果一个类包含抽象方法,那么该类必须是抽象类。
  • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

规定

  • 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;

  • 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

案例 

题目1

首先设计一个学生抽象类Student,其数据成员有name(姓名)、age(年龄)和degree(学位),以及一个抽象方法show()。然后由Student类派生出本科生类Undergraduate和研究生类Graduate,本科生类Undergraduate增加成员specialty(专业),研究生类增加成员direction(研究方向)。并且每个类都有show()方法,用于输出数据成员信息。请定义对象,并打印输出下列信息:

  张三:20,本科,计算机科学

李四:21,本科,物联网

王五:25,硕士,软件工程

刘六:36,博士,通信工程

代码

package DEMO230201.abstractdemo;
abstract class Student{
    String name;
    int age;
    String degree;
    public Student(String name,int age,String degree){
        super();
        this.name=name;
        this.age=age;
        this.degree=degree;
    }
    public abstract void show();
}
class Undergraduate extends Student {
    String specialty;
    public Undergraduate(String name,int age,String degree,String specialty){
        super(name,age,degree);
        this.specialty=specialty;
    }
    public void show(){
        System.out.println(super.name+" :"+super.age+","+super.degree+","+specialty);
    }
}
class Graduate extends Student {
    String direction;
    public Graduate(String name,int age,String degree,String direction){
        super(name,age,degree);
        this.direction=direction;
    }
    public void show(){
        System.out.println(super.name+" :"+super.age+","+super.degree+","+direction);
    }
}
public class abstract1 {
    public static void main(String[] args){
        Undergraduate u1=new Undergraduate("张三",20,"本科","计算机科学");
        Undergraduate u2=new Undergraduate("李四",21,"本科","物联网");
        Graduate g1=new Graduate("王五",25,"硕士","软件工程");
        Graduate g2=new Graduate("刘六",36,"博士","通信工程");
        u1.show();
        u2.show();
        g1.show();
        g2.show();
    }
}

运行结果

张三 :20,本科,计算机科学
李四 :21,本科,物联网
王五 :25,硕士,软件工程
刘六 :36,博士,通信工程
 题目2

设计一个抽象类Graphics,它具有一个String类型参数name和两个抽象方法parameter()、area(),name用来存储图形的名称,parameter()方法用于输出图形的名称和其它属性特征,area()方法用于输出图形的面积。请用该类派生的子类实现输出一个形状为长方形、长为3宽为2和它面积以及输出一个形状为圆形、颜色为红色、半径为4和它面积。

代码

package DEMO230201.abstractdemo;
abstract class Graphics{
    String name;
    public Graphics(String name){
        super();
        this.name=name;
    }
    public abstract void parameter();
    public abstract void area();
}
class Rectangle extends Graphics{
    int length;
    int width;
    public Rectangle(String name,int length,int width){
        super(name);
        this.length=length;
        this.width=width;
    }
    public void parameter(){
        System.out.println("图形属性为:"+name+",图形的长为:"+length+",宽为:"+width);
    }
    public void area(){
        System.out.println("图形面积为:"+length*width);
    }
}
class Rotundity extends Graphics{
    String color;
    int radius;
    public Rotundity(String name,String color,int radius){
        super(name);
        this.color=color;
        this.radius=radius;

    }
    public void parameter(){
        System.out.println("图形属性为:"+name+",图形的颜色为:"+color+",图形的半径为:"+radius);
    }
    public void area(){
        System.out.println("图形面积为:"+3.14*radius*radius);
    }
}
public class abstract2 {
    public static void main(String[] args){
        Rectangle re1=new Rectangle("长方形",3,2);
        Rotundity ro1=new Rotundity("圆形","红色",4);
        re1.parameter();
        re1.area();
        ro1.parameter();
        ro1.area();
    }
}

运行结果

图形属性为:长方形,图形的长为:3,宽为:2
图形面积为:6
图形属性为:圆形,图形的颜色为:红色,图形的半径为:4
图形面积为:50.24

接口

如果一个抽象类的所有方法都是抽象的,则可以将这个类定义为接口。接口中除了可以包括抽象方法外,还可以包括默认方法和静态方法(也交类方法),默认方法用default修饰,静态方法用static修饰,这两种方法都允许有方法体。

接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

接口与类的区别

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

抽象类和接口的区别

  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

 接口的声明

x修饰符 interface 接口名称 extends 接口1,接口2... {
        // 声明变量
        访问权限 abstract 返回值类型 抽象方法名称 (参数);   ///抽象方法
}
  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。

接口的实现 

修饰符 class 类名 implements 接口1,接口2...{
    ...
}

 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

接口的继承

一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

在Java中,类的多继承是不合法,但接口允许多继承。

在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口,用 ‘ ,’ 分隔。

 案例

题目1

设计一个接口circleInterface,要求接口中有一个定义PI的常量以及一个计算圆面积的空方法circleArea()。然后设计一个类circleClass实现该接口,通过构造函数circleClass(double r)定义圆半径,并增加一个显示圆面积的方法。最后,通过上述类生成两个半径分别为3.5、5.0的圆对象circle1、circle2进行测试。

代码

package DEMO230201.Interfacedemo;
interface CircleInterface{
    double PI = 3.1415926535; // 定义PI常量
    void circleArea();
}
class CircleClass implements CircleInterface{
    double r;
    public CircleClass(double r){
        this.r=r;
    }
    public void circleArea(){
        System.out.println("圆的面积为:"+PI*r*r);
    }
}
public class Interface1 {
    public static void main(String[] args){
        CircleClass circle1=new CircleClass(3.5);
        CircleClass circle2=new CircleClass(5.0);
        circle1.circleArea();
        circle2.circleArea();
    }
}

运行结果

圆的面积为:38.484510005375
圆的面积为:78.5398163375
题目2

设计一个Shape接口和它的两个实现类Square和Circle,要求如下:1)Shape接口中有一个抽象方法area(),方法接收一个double类型的参数,返回一个double类型的结果。2)Square和Circle中实现了Shape接口的area()抽象方法,分别求正方形和圆形的面积并返回。在测试类中创建Square和Circle对象,计算边长为2的正方形面积和半径为3的园面积

代码

package DEMO230201.interfacedemo;
interface Shape{
    double area(double a);
}
class Square implements Shape{
    public double area(double length){
        return length*length;
    }
}
class Circle implements Shape{
    double PI = 3.1415926535;
    public double area(double radius){
        return PI*radius*radius;
    }
}
public class interface2 {
    public static void main(String[] args){
        Square s=new Square();
        Circle c=new Circle();
        System.out.println("正方形面积为:"+s.area(2));
        System.out.println("圆形面积为:"+c.area(3));
    }
}

运行结果

正方形面积为:4.0
圆形面积为:28.2743338815

多态

多态是同一个行为具有多个不同表现形式或形态的能力。

多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

向上转型

多态本身就是向上转型过的过程

使用格式:

	父类类型 变量名 = new 子类类型();
	如:Animal a = new Cat();
  • 向上转型后,子类单独定义的方法会丢失(父类并不知道子类定义的新属性与方法)
  • 父类引用可以指向子类对象,但是子类引用不能指向父类对象
  • 如果子类中重写了父类的方法,那么调用这个方法的时候,将会调用子类中的方法

适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。 

假如现在我们写一个方法用来接收不同子类的对象,然后调用它们的print()方法输出各个子类对象的相关信息,那么此时,有多少个子类,我们就需要写多少个方法,分别用来接收各个不同子类的对象

public static void main(String[] args){
        Test test=new Test();
        test.getMessage(new Student());
        test.getMessage(new Teacher());
        test.getMessage(new Worker());
 } 
public void getMessage(Student p) {
      p.print();
 }
public void getMessage(Teacher p) {
      p.print();
 }
public void getMessage(Worker p) {
      p.print();
 }

当我们使用了向上转型之后,就可以只写一个方法来接收所有Person类的子类对象,这样就实现了参数的统一化

public static void main(String[] args){
        Test test=new Test();
        test.getMessage(new Student());
        test.getMessage(new Teacher());
        test.getMessage(new Worker());
 } 
public void getMessage(Person p) {
      p.print();
 }

向下转型

一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用各类型          

使用格式

子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c =(Cat) a;

 适用场景:当要使用子类特有功能时。

向下转型之前一定要进行向上转型!!
否则在转型时会出现ClassCastException(类型转换异常–运行时异常)
想避免这类问题发生,可以先判断(依靠instanceof关键字实现)该引用是否能表示该类实例。

instanceof关键字

JAVA中可以使用instanceof 关键字判断一个对象是否是某个类(或接口)的实例。

对象 instanceof 类 (或接口)

如果对象是指定类的实例对象,则返回true,否则返回false。

eg: 

class Person{
    public void print(){
        System.out.println("I am a person");
    }
    public void p(){
        System.out.println("sad");
    }
}
class Student extends Person{
    public void print(){
        System.out.println("I am a student");
    }
    public void fun(){
        System.out.println("happy");
    }
}
public class Test{
    public static void main(String[] args)
    {
        Person per = new Student();  //向上转换
        System.out.println(per instanceof Person);
        System.out.println(per instanceof Student);
        if(per instanceof Student){
            Student stu = (Student)per;   //向下转换
            stu.fun();   //调用特有方法
        }
    }
}

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

包的作用

  • 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。

  • 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。

  • 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

包语句的语法格式为:

package 包名.包名...;

import 关键字

为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。

在 Java 中,import 关键字用于导入其他类或包中定义的类型,以便在当前源文件中使用这些类型。

import 关键字用于引入其他包中的类、接口或静态成员,它允许你在代码中直接使用其他包中的类,而不需要完整地指定类的包名。

在 java 源文件中 import 语句必须位于 Java 源文件的头部,其语法格式为:

import 包名.包名…类名;

如果在一个包中,一个类想要使用本包中的另一个类,那么该包名可以省略。

可以使用 import语句来引入一个特定的类:

import 包名.包名...特定类;

这样,你就可以在当前源文件中直接使用 MyClass 类的方法、变量或常量。

也可以使用通配符 * 来引入整个包或包的子包:

import 包名.包名...*;

这样,你可以导入 com.runoob.mypackage 包中的所有类,从而在当前源文件中使用该包中的任何类的方法、变量或常量。注意,使用通配符 * 导入整个包时,只会导入包中的类,而不会导入包中的子包。

案例

题目1

在biology包中的animal包中有human类,它具有name,height,weight的属性,还具有eat(),sleep()和work()的行为,在biology包中的plant包中有flower类,它具有name,color,smell的属性,还具有drink()和blossom()的行为.现在在一个school包中的garden包中一个张三的人,他是一个human类的对象,种植的rose是一个flower类对象,编程实现并测试各自的方法.

代码

package DEMO230201.packagedemo.package1.biology.animal;

public class human {
    String name;
    int height;
    int weight;
    public human(String name,int height,int weight){
        this.name=name;
        this.height=height;
        this.weight=weight;
    }
    public void eat(){
        System.out.println("I am eating");
    }
    public void sleep(){
        System.out.println("I am sleeping");
    }
    public void work(){
        System.out.println("I am working");
    }
    public void printHuman(){
        System.out.println("My name is "+name+",my height is "+height+",my weight is "+weight);
    }
    public static void main(String[] args){

    }
}
package DEMO230201.packagedemo.package1.biology.plante;

public class flower {
    String name,color,smell;
    public flower(String name,String color,String smell){
        this.name=name;
        this.color=color;
        this.smell=smell;
    }
    public void drink(){
        System.out.println("I am drinking");
    }
    public void blossom(){
        System.out.println("I am blossoming");
    }
    public void printFlower(){
        System.out.println("I am a "+name+",my color is "+color+",my smell is "+smell);
    }
    public static void main(String[] args){

    }
}
package DEMO230201.packagedemo.package1.school;

import DEMO230201.packagedemo.package1.biology.animal.human;
import DEMO230201.packagedemo.package1.biology.plante.flower;

public class garden {
    public static void main(String[] args){
        human h=new human("张三",188,160);
        h.printHuman();
        h.eat();
        h.sleep();
        h.work();
        flower f=new flower("芍药","粉白","香");
        f.printFlower();
        f.drink();
        f.blossom();
      //测试human类和flower类里面的共五个方法,因为是跨包定义的类,因此这五个方法必须是public权限
    }
}

运行结果

My name is 张三,my height is 188,my weight is 160
I am eating
I am sleeping
I am working
I am a 芍药,my color is 粉白,my smell is 香
I am drinking
I am blossoming
题目2

在computer包中的mainbroad包中有一个VGACard的类,它有一个显示方法show(),显示”VGA checked success”,在server的包的mainbroad包中的showCard类是继承自VGACard,请测试showCard的show()功能。

代码

package DEMO230201.packagedemo.package2.computer.mainbroad;

public class VGACard {
    public void show(){
        System.out.println("VGA checked success");
    }
    public static void main(String[] args){
    }
}
package DEMO230201.packagedemo.package2.server.mainbroad;

import DEMO230201.packagedemo.package2.computer.mainbroad.VGACard;

public class showCard extends VGACard {
    public void show(){
        super.show();
    }
    public static void main(String[] args){
        showCard s = new showCard();
        s.show();
    }
}

运行结果

VGA checked success
题目3

在com.graphic包中定义一个圆柱体类Cylinder,其半径r,高h都为私有属性,有构造方法和求体级方法volume()。在com.test包中定义一个测试类test,测试一个半径为5.34、高为2的圆柱体体积。半径PI为3.14

代码

package DEMO230201.packagedemo.pakage3.com.graphic;

public class Cylinder {
    private double r;
    private double h;
    public Cylinder(double r,double h){
        this.r=r;
        this.h=h;
    }
    public void volume(){
        double PI=3.14;
        double area=PI*r*r*h;
        System.out.println("圆柱体体积为:"+area);
    }
}
package DEMO230201.packagedemo.pakage3.com;

import DEMO230201.packagedemo.pakage3.com.graphic.Cylinder;

public class test {
    public static void main(String[] args){
        Cylinder c=new Cylinder(5.34,2);
        c.volume();
    }
}

运行结果

圆柱体体积为:179.077968
  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java面向对象编程电子书是一本详细介绍Java面向对象编程概念、原理和实践的电子书籍。本书从基础概念开始,逐步深入到高级主题,使读者能够全面理解Java面向对象编程的核心思想和技术。 首先,本书会介绍面向对象编程的基本理念和原则,例如封装、继承和多态等。读者将能够了解到如何使用Java语言中的类、对象和方法来实现这些概念,并学会如何通过类和对象之间的关系来进行数据和行为的组织。 接着,本书将详细介绍Java中的类和对象的创建、属性和方法的定义以及对象之间的交互。读者将学会如何使用构造函数来创建对象实例,并掌握如何在类中定义属性和方法,并使用它们来访问和修改对象的状态。 另外,本书还会涵盖继承和多态的概念和实践。读者将了解到如何通过继承来创建子类,并使用多态来实现不同对象之间的统一接口。这些技术将大大提高代码的可复用性和可扩展性。 此外,本书还会介绍Java面向对象编程中的其他重要概念,如抽象类、接口、封装和设计模式等。这些概念和技术将使读者更加熟悉Java面向对象编程的整体框架,并能够应用到实际的开发中。 总而言之,Java面向对象编程电子书是一本很好的学习资料,它详细介绍了Java面向对象编程的基本概念、原则和实践。读者通过学习本书,将能够深入理解并掌握Java面向对象编程的核心思想和技术,从而提高自己的编程能力和应用水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值