java面向对象编程

面向对象基本概念

面向对象相关的一些常见术语的解释

  1. 面向对象(Object-Oriented,OO):一种程序设计方法,将真实世界中的事物抽象成对象,并通过封装、继承和多态等特性来描述和操作对象的状态和行为。

  2. 面向对象编程(Object-Oriented Programming,OOP):基于面向对象思想的一种编程范式,通过创建和操作对象来实现程序的模块化、重用和可维护性。

  3. 面向对象分析(Object-Oriented Analysis,OOA):软件工程中的一个阶段,通过分析问题域中的概念、属性和关系等,识别和定义出系统中的对象及其交互,以获取对问题域的深入理解。

  4. 面向对象设计(Object-Oriented Design,OOD):软件工程中的一个阶段,基于面向对象分析的结果,将系统功能划分为一组对象,并定义它们的属性、行为和关系,以实现系统的模块化和可扩展性。

  5. 面向对象语言(Object-Oriented Language):支持面向对象编程的编程语言,如Java、C++、Python等,这些语言提供了类、对象、继承、多态等面向对象特性的语法和语义。

面向对象(Object-Oriented)是一种软件开发的编程范式,它将现实世界中的事物抽象为对象,并通过对象之间的相互作用来实现程序的设计和开发。面向对象编程具有以下基本概念:

  1. 类(Class):类是面向对象的基本概念,表示一类具有相同属性和行为的对象的抽象模板。类定义了对象的属性(成员变量)和行为(方法)。

  2. 对象(Object):对象是类的一个实例,可以具体地表示现实世界中的一个事物。每个对象都有自己的状态(属性值)和行为(方法)。

  3. 封装(Encapsulation):封装是将类的数据(属性)和操作(方法)包装在一起,以隐藏内部实现细节,仅对外提供公共接口。通过封装,可以保护数据的安全性和完整性。

  4. 继承(Inheritance):继承是指在已有类的基础上创建新类,新类继承了已有类的属性和方法。通过继承,子类可以复用父类的代码,并可以添加、修改或覆盖父类的方法。

  5. 多态(Polymorphism):多态是指同一类型的对象,在不同的情况下表现出不同的行为。多态通过方法的重写(Override)和方法的重载(Overload)来实现。

  6. 抽象(Abstraction):抽象是指将对象的共同特征提取出来,形成抽象类或接口。抽象类定义了一组抽象方法和非抽象方法,而接口只包含抽象方法。通过抽象,可以实现代码的模块化和复用。

类与对象

类(Class)和对象(Object)是面向对象编程的基本概念,它们之间有着紧密的关系。

  • 类是对一类事物的抽象描述,它定义了对象的属性和行为。通过类可以创建多个具体的对象实例。类是对象的模板,包含了共同的属性和行为,但不具体表示任何特定的对象。

  • 对象是类的一个实例,代表了现实世界中的一个具体事物。对象具有自己的状态(属性值)和行为(方法),可以通过调用对象的方法来操作其状态。每个对象都是独立存在的,它们之间相互独立,拥有各自的属性值和执行过程。

  • 类和对象之间的关系可以理解为类是对象的蓝图或模板,而对象是根据类的定义创建出来的具体实体。类可以看作是对象的抽象,而对象是类的具体化。

类和对象的定义格式

在Java中可以使用以下的语句定义一个类:

class 类名称{
    属性名称;
    返回值类型 方法名称(){}
}

对象的定义: 一个类要想真正的进行操作,则必须依靠对象,对象的定义格式如下:

类名称 对象名称 = new 类名称() ;

按照以上的格式就可以产生对象了。 如果要想访问类中的属性或方法(方法的定义),则可以依靠以下的语法形式:

  • 访问类中的属性: 对象.属性 ;

  • 调用类中的方法: 对象.方法()

对象内存分析

  1. new关键字:表示向内存申请空间,也表示实例化一个对象,创建一个对象。

  2. 一个对象在内存中的大小,由该对象的所有属性所占的内存大小的总和。引用类型变量在32位系统上占4个 字节,在64位系统上占8个字节。加上而外的对象隐性数据所占的大小。

  3. 相同的类型才可以赋值

  4. 不同的引用,指向同一个对象,任何一个引用改变对象的值,其它引用都会反映出来。

  5. 编程时要注意的问题,在确定不使用对象时,要尽早释放对象:引用=null

  6. 当一个堆中的对象没有被任何引用变量所指向时,该对象会被JVMGC程序认为是垃圾对象,从而被回 收。

封装

封装的基本概念

封装性

  1. 封装性是面向对象思想的三大特征之一。

  2. 封装就是隐藏实现细节,仅对外提供访问接口。

  3. 封装有: 属性的封装、方法的封装、类的封装、组件的封装、模块化封装、系统级封装…

封装的好处

  1. 模块化

  2. 信息隐藏

  3. 代码重用

  4. 插件化易于调试

  5. 具有安全性

封装缺点

  • 会影响执行效率

封装之前

class Person{
    String name;
    int age;
}

封装之后

class Person{ 
    //属性是成员变量
    private String name;
    private int age;
    //参数及方法内定义的变量是局部变量
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    } 
}

成员变量和局部变量

  1. 在类中的位置不同 成员变量:在中定义 局部变量:在方法中定义或者方法的参数

  2. 在内存中的位置不同 成员变量:在内存(成员变量属于对象,对象进堆内存) 局部变量:在内存(局部变量属于方法,方法进栈内存)

  3. 生命周期不同 成员变量:随着对象的创建而存在,随着对象的销毁而消失 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

  4. 初始化值不同 成员变量:有默认初始化值,引用类型默认为null 局部变量:没有默认初始化值,必须定义,赋值,然后才能使用

  5. 注意: 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。

构造方法

什么是构造方法

  1. 构造方法就是类构造对象时调用的方法,用于对象的初始化工 作

  2. 构造方法是实例化一个类的对象时,也就是new 的时候,最先调用的方法。

构造方法的定义

  1. 构造方法是在类中定义的

  2. 构造方法的定义格式

    • 方法名称与类名称相同,无返回值类型的声明。

  1. 对象的实例化语法:

    • Dog dog = new Dog(); //new Dog后面有个括号,带括号表示调用了方法,此时调用的方法就是构造方法了

无参构造方法:

public Dog(){}
    带一个参数的构造方法:
    public Dog(String name){
        this.name = name;
    }
}

带多个参数的构造方法

public Dog(String name,int age){
    this.name = name;
    this.age = age;
}

构造方法小结

  1. 构造方法名称与类名相同,没有返回值声明(包括 void)

  2. 构造方法用于初始化数据(属性)

  3. 每一个类中都会有一个默认的无参的构造方法

  4. 如果类中有显示的构造方法,那么默认构造方法将无效

  5. 如果有显示的构造方法,还想保留默认构造 方法,需要显示的写出来。

  6. 构造方法可以有多个,但参数不一样,称为构造方法的重载

  7. 在构造方法中调用另一个构造方法,使用this(...),该句代码必须在第一句。

  8. 构造方法之间的调用,必须要有出口。

  9. 给对象初始化数据可以使用构造方法或setter方法,通常情况下,两者都会保留。

  10. 一个好的编程习惯是要保留默认的构造方法。(为了方便一些框架代码使用反射来创建对象)

  11. private Dog(){},构造方法私有化,当我们的需求是为了 保正该类只有一个对象时。

什么时候一个类只需要一个对象?

比如,工具类(没有属性的类,只有行为)并且该工具对象被频繁使用。 权衡只用一个对象与产生多个对象的内存使用,来确定该类是否要定义为只需要一个对象。

this关键字

在Java基础中,this关键字是一个最重要的概念。使用this关键字可以完成以下的操作:

  • 调用类中的属性

  • 调用类中的方法或构造方法

  • 表示当前对象

在Java中,关键字 "this" 代表当前对象的引用。它可以用于以下几种情况:

  1. 引用当前对象的成员变量:在类的实例方法中,可以使用 "this" 关键字来引用当前对象的成员变量。这样可以区分成员变量和方法参数之间的命名冲突。

public class Person {
    private String name;
    
    public void setName(String name) {
        this.name = name; // 使用 "this" 引用当前对象的成员变量
    }
}
  1. 调用当前对象的其他方法:在类的实例方法中,可以使用 "this" 关键字来调用当前对象的其他方法。这样可以在方法内部方便地访问对象的其他行为。

public class Calculator {
    private int result;
    
    public void add(int num) {
        result += num;
    }
    
    public void printResult() {
        System.out.println("Result: " + this.getResult()); // 使用 "this" 调用当前对象的方法
    }
    
    public int getResult() {
        return result;
    }
}
  1. 在构造方法中引用其他构造方法:当一个类中存在多个构造方法时,可以使用 "this" 关键字在一个构造方法中调用其他构造方法。这样可以避免代码的重复。

public class Rectangle {
    private int width;
    private int height;
    
    public Rectangle() {
        this(0, 0); // 调用带参数的构造方法
    }
    
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

总之,"this" 关键字在Java中表示当前对象的引用。它可以用于引用当前对象的成员变量、调用当前对象的其他方法以及在构造方法中调用其他构造方法。使用 "this" 可以解决命名冲突、方便访问对象的其他行为,并提高代码的可读性和重用性。

static关键字

static关键字的作用:

  1. 使用static关键字修饰一个属性 声明为static的变量实质上就是全局变量

  2. 使用static关键字修饰一个方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法

  3. 使用static关键字修饰一个类(内部类)

"static" 关键字的主要用法

当我们在Java中使用 "static" 关键字修饰某个成员(字段或方法)时,它的含义是这个成员不再属于实例对象,而是属于类本身。这意味着无需创建实例对象,就可以直接访问和使用这个成员。

举例来说,假设我们有一个叫做 "Person" 的类,我们希望记录创建过多少个实例对象。我们可以使用一个静态变量来实现这个功能:

public class Person {
    private static int count; // 静态变量,用于记录创建的实例对象数量
    private String name;
    
    public Person(String name) {
        this.name = name;
        count++; // 每次创建实例对象时,通过静态变量自增来记录数量
    }
    
    public void sayHello() {
        System.out.println("Hello, my name is " + name);
    }
    
    public static int getCount() {
        return count; // 静态方法可以直接访问静态变量
    }
}

现在我们可以创建多个 "Person" 实例对象,并查看创建的对象数量:

Person p1 = new Person("Alice");
Person p2 = new Person("Bob");
​
System.out.println(Person.getCount()); // 输出:2

在这个例子中,静态变量 "count" 被所有的 "Person" 实例对象所共享。每次创建实例对象时,静态变量都会自增,记录了创建的实例对象数量。我们可以通过静态方法 "getCount()" 直接访问静态变量,而无需创建实例对象。

总的来说,使用 "static" 关键字将成员修饰为类级别的,使得它们不再属于实例对象,而是属于类本身。这样可以直接通过类名访问和使用这些成员,而不需要先创建实例对象。

main方法分析

public static void main(String[] args){
    //代码块
}
  • public:公有的,最大的访问权限

  • static:静态的,无需创建对象

  • void::表示没有返回值,无需向JVM返回结果

  • main:方法名,固定的方法名

  • String[] args:表示参数为字符串数组,可以在调用方法时传入参数

继承

继承的基本概念

继承是从已有的类创建新类的过程

1、继承是面向对象三大特征之一 2、被继承的类称为父类(超类),继承父类的类称为子类(派生类) 3、继承是指一个对象直接使用另一对象的属性和方法。 4、通过继承可以实现代码重用

语法

语法:[访问权限] class 子类名 extends 父类名{
    类体定义;
}

示例

public class Dog{
    private String name;
    private String sex;
    public void eat(){
        System.out.println(“吃饭”);
    }
}
​
public class HomeDog extends Dog{
    //类的定义
}
​
public class HuskyDog extends Dog{
    //类的定义
}
  • protected(受保护的访问权限修饰符,用于修饰属性和方法,使用protected修饰的属性和方法可以被子类继承)

继承的限制

继承的限制约定:

  1. Java只能实现单继承,也就是一个类只能有一个父类

  2. 允许多层继承,即:一个子类可以有一个父类,一个父类还可以有其他的父类。

  3. 继承只能继承非私有的属性和方法。

  4. 构造方法不能被继承

继承的好处:

  1. 提高代码的复用性

  2. 提高代码的维护性

  3. 让类与类之间产生关系,是多态的前提

继承的缺点:

  1. 增强了类与类之间的耦合性(开发原则:高内聚,低耦合)

继承小结

  1. 继承是发生在多个类之间

  2. 继承使用关键字extends

  3. JAVA只能单继承,允许多层继承

  4. 被继承的类叫父类(超类),继承父类的类叫子类(派生类)

  5. 在父类中的非私有属性和方法可以被子类继承

  6. protected(受保护的访问权限修饰符),修饰的属性或方法可以被子类继承

  7. 构造方法不能被继承

  8. 创建对象会调用构造方法,调用构造方法不一定就是创建对象

  9. 实例化子类对象,会先调用父类的构造方法,如果父类中没有默认的构造方法,那么子类必须显示的通过 super(...)来调用父类的带参构造方法,super也只能在子类构造方法中的第一句

子类的实例化过程

在子类进行实例化操作的时候,首先会先让其父类进行初始化操作。之后子类再自己进行实例化操作。 子类的实例化过程:

  • 子类实例化时会先调用父类的构造方法

  • 如果父类中没有默认的构造方法,在子类的构造方法中必须显示的调用父类的构造方法

结论:

  • 构造方法只是用于初始化类中的字段以及执行一些初始化代码

  • 调用构造方法并不代表会生成对象

方法的重写

方法重写(overriding method)

在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想做一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。在子类和父类中,重写方法后,在调用时,以创建的对象类型为准,会调用谁的方法。

关于方法重写的一些特性:

  1. 发生在子父类中,方法重写的两个方法返回值、方法名、参数列表必须完全一致(子类重写父类的方法)

  2. 子类抛出的异常不能超过父类相应方法抛出的异常(子类异常不能大于父类异常)

  3. 子类方法的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)

  4. 父类中的方法若使用private、static、final任意修饰符修饰,那么,不能被子类重写。

为什么要重写方法?或者方法重写的目的是什么?

若子类从父类中继承过来的方法,不能满足子类特有的需求时,子类就需要重写父类中相应的方法,方法的重写 也是程序扩展的体现。

super关键字

super可以完成以下的操作:

  1. 使用super调用父类中的属性,可以从父类实例处获得信息。

  2. 使用super调用父类中的方法,可以委托父类对象帮助完成某件事情。

  3. 使用super调用父类中的构造方法(super(实参)形式),必须在子类构造方法的第一条语句,调用父类中相应 的构造方法,若不显示的写出来,默认调用父类的无参构造方法,比如:super();

举例子

假设有一个父类Person和一个子类Student,子类Student继承了父类Person,我们来看一下在实际代码中如何使用super关键字。

class Person {
    String name;
​
    public Person(String name) {
        this.name = name;
    }
​
    public void display() {
        System.out.println("Person: " + name);
    }
}
​
class Student extends Person {
    int grade;
​
    public Student(String name, int grade) {
        super(name); // 调用父类的构造函数
        this.grade = grade;
    }
​
    @Override
    public void display() {
        super.display(); // 调用父类的display方法
        System.out.println("Student Grade: " + grade);
    }
}
​
public class Main {
    public static void main(String[] args) {
        Student student = new Student("Alice", 10);
        student.display();
    }
}

在上面的示例中,子类Student继承了父类Person的实例变量name和方法display。使用super(name)调用父类的构造函数来初始化父类的实例变量。在子类的display方法中,使用super.display()调用父类的display方法,并在其基础上添加了其他功能。

运行上述代码,输出结果为:

Person: Alice
Student Grade: 10

可以看到,通过使用super关键字,我们能够在子类中访问父类的变量、方法或构造函数,并在其基础上进行修改和扩展。

final关键字

使用final关键字完成以下的操作:

  1. 使用final关键字声明一个常量 修饰属性或者修饰局部变量(最终变量),也称为常量。

  2. 使用final关键字声明一个方法 该方法为最终方法,且只能被子类继承,但是不能被子类重写。

  3. 使用final关键字声明一个类 该类就转变为最终类,没有子类的类,fianl修饰的类无法被继承。

  4. 在方法参数中使用final,在该方法内部不能修改参数的值

final应用:

//定义一个常量:
public static final int NUM = 10;
//定义一个final方法(不常用)
​
//定义一个final类:通常在常量类中使用
​
//常量类:在该类中只有常量,通常是应用程序中公共的常量或标记
public final class Constant{
    public static final String SERVER_ROOT_URL ="http://www.baidu.com";
    public static final String CACHE_PATH ="data_cache";
//.... 
}
​

多态

抽象类

抽象类的基本概念

  1. 很多具有相同特征和行为的对象可以抽象为一个类;很多具有相同特征和行为的类可以抽象为一个抽象类。

  2. 使用abstract关键字声明的类为抽象类。

定义一个抽象类

在Java中,可以使用关键字 "abstract" 来定义一个抽象类。抽象类是一种不能被直接实例化的类,它通常用作其他具体子类的基类。

要定义一个抽象类,需要按照以下步骤进行:

  1. 使用关键字 "abstract" 在类声明前面进行修饰。

  2. 可以在抽象类中定义抽象方法,这些方法没有具体的实现。抽象方法使用关键字 "abstract" 进行修饰,并且不包含方法体。

  3. 抽象类中可以包含具体的方法,这些方法有具体的实现代码。

  4. 抽象类可以拥有字段和构造函数。

以下是一个简单的示例,展示如何定义一个抽象类:

abstract class Animal {
    private String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
    
    public abstract void makeSound(); // 抽象方法,无具体实现
    
    public abstract void move(); // 抽象方法,无具体实现
}

在上述示例中,我们定义了一个名为 "Animal" 的抽象类。它有一个私有字段 "name" 和一个构造函数来初始化这个字段。抽象类中还有一个具体的方法 "sleep",它输出动物正在睡觉。另外,还定义了两个抽象方法 "makeSound" 和 "move",这些方法没有具体的实现。

请注意,由于抽象类不能直接实例化,因此我们无法创建 "Animal" 类的对象。我们可以通过继承抽象类并实现其中的抽象方法来创建具体的子类,从而实例化对象。

例如,我们可以创建一个名为 "Dog" 的子类来继承 "Animal" 抽象类,并实现抽象方法:

class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    @Override
    public void makeSound() {
        System.out.println("Woof woof!");
    }
    
    @Override
    public void move() {
        System.out.println("Running on four legs.");
    }
}

在上述示例中,我们创建了一个名为 "Dog" 的子类,继承自 "Animal" 抽象类。我们必须实现抽象方法 "makeSound" 和 "move",提供具体的实现逻辑。

通过定义抽象类,我们可以为一组相关的类定义共同的行为和结构,同时要求具体的子类实现抽象方法。这样可以提高代码的可维护性和灵活性。

抽象类的规则:

  1. 抽象类可以没有抽象方法,有抽象方法的类必须是抽象类

  2. 非抽象类继承抽象类必须实现所有抽象方法

  3. 抽象类可以继承抽象类,可以不实现父类抽象方法。

  4. 抽象类可以有方法实现和属性

  5. 抽象类不能被实例化

  6. 抽象类不能声明为final

  7. 抽象类可以有构造方法

接口

接口的概念

  1. 接口是一组行为的规范、定义,没有实现(JDK1.8默认方法)

  2. 使用接口,可以让我们的程序更加利于变化

  3. 接口是面向对象编程体系中的思想精髓之一

  4. 面向对象设计法则:基于接口编程

接口的定义格式:

public interface 接口名称 {
    // 声明常量
    
    // 声明方法(默认抽象方法)
    
    // 可选:声明默认方法
    
    // 可选:声明静态方法
}

接口的使用规则:

  1. 定义一个接口,使用interface关键字

  2. 在一个接口中,只能定义常量、抽象方法,JDK1.8后可以定义默认的实现方法

  3. 接口可以继承多个接口:extends xxx,xxx

  4. 一个具体类实现接口使用implements关键字

  5. 一个类可以实现多个接口

  6. 抽象类实现接口可以不实现接口的方法

  7. 在接口中定义的方法没有声明 访问修饰符,默认为public

  8. 接口不能有构造方法

  9. 接口不能被实例化

举例子

public interface Flyable {
    int MAX_SPEED = 100; // 声明常量
    
    void fly(); // 声明抽象方法
    
    default void takeOff() { // 默认方法的具体实现
        System.out.println("Taking off...");
    }
    
    static void land() { // 静态方法的具体实现
        System.out.println("Landing...");
    }
}
​
class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("Bird is flying.");
    }
}
​
class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("Airplane is flying.");
    }
}
​
public class Main {
    public static void main(String[] args) {
        Bird bird = new Bird();
        bird.fly(); // 输出:Bird is flying.
        bird.takeOff(); // 输出:Taking off...
        Flyable.land(); // 输出:Landing...
        
        Airplane airplane = new Airplane();
        airplane.fly(); // 输出:Airplane is flying.
        airplane.takeOff(); // 输出:Taking off...
        Flyable.land(); // 输出:Landing...
    }
}

对于默认方法和静态方法,在接口中可以提供具体的默认实现或静态实现,实现类可以选择是否重写这些方法。

默认方法使用关键字 default 进行修饰,它们在接口中有一个默认的实现代码。实现类可以直接继承默认方法的实现,也可以选择重写。

静态方法使用关键字 static 进行修饰,它们在接口中有一个具体的静态实现。静态方法是基于接口本身而不是实现类的,可以直接通过接口名调用,无需实例化对象。

在上述代码中,takeOff() 是一个默认方法,它提供了一个默认的具体实现代码,输出"Taking off..."。如果实现类没有重写该方法,将使用默认实现。

land() 是一个静态方法,它也提供了一个具体的静态实现代码,输出"Landing..."。静态方法可以直接通过接口名调用,例如 Flyable.land()

因此,实现类可以选择是否重写这两个方法。如果不需要自定义实现,可以直接使用接口中提供的默认实现或静态实现。

多态的基本概念

在Java中,多态性(Polymorphism)是指同一类型的对象,通过引用不同的类而表现出不同的行为。简而言之,多态性允许我们使用父类的引用来引用子类的对象,从而实现对不同子类的统一处理。

多态性有两种形式:编译时多态和运行时多态。

  1. 编译时多态(静态多态):在编译时,Java编译器会根据引用变量的类型来确定可以调用的方法。这意味着编译时多态仅限于编译器可见的类型,即基于引用变量的类型调用相应的方法。这种多态只能适用于非静态方法,并且是通过继承和方法重写来实现的。

  2. 运行时多态(动态多态):在运行时,Java的虚拟机根据对象的实际类型来确定要调用的方法。这意味着运行时多态能够动态地根据对象的类型调用相应的方法。这种多态性是通过继承、方法重写和父类引用指向子类对象来实现的。

多态性的好处在于它可以让代码更加灵活和可扩展。通过多态性,我们可以编写通用的代码,而不需要为每个子类编写特定的代码。

以下是一个示例,展示了多态性的用法:

class Animal {
    public void makeSound() {
        System.out.println("Animal is making a sound.");
    }
}
​
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog is barking.");
    }
}
​
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat is meowing.");
    }
}
​
public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog(); // 使用父类引用指向子类对象
        Animal animal2 = new Cat(); // 使用父类引用指向子类对象
​
        animal1.makeSound(); // 输出:Dog is barking.
        animal2.makeSound(); // 输出:Cat is meowing.
    }
}

在上述示例中,我们有一个基类 Animal 和两个派生类 DogCat。这三个类都有一个名为 makeSound() 的方法,但是每个子类都重写了该方法以实现自己的行为。

在主程序中,我们创建了一个 Animal 类型的引用变量 animal1animal2,并将它们分别指向一个 Dog 对象和一个 Cat 对象。然后,我们通过这两个引用变量调用 makeSound() 方法。由于运行时多态性的存在,根据对象的实际类型,正确的方法会被动态地调用,输出相应的结果。这就是多态性的运行时表现。

总结起来,多态性是Java面向对象编程的一个重要概念,它通过父类引用指向子类对象,实现对不同子类对象的统一处理。多态性可以提高代码的灵活性、可扩展性和可维护性。

多态性小结:

  1. 方法的重载与重写就是方法的多态性表现

  2. 多个子类就是父类中的多种形态

  3. 父类引用可以指向子类对象,自动转换

  4. 子类对象指向父类引用需要强制转换(注意:类型不对会报异常)

  5. 在实际开发中尽量使用父类引用(更利于扩展)

instanceof关键字

在Java中,instanceof 是一个关键字用于检查一个对象是否属于某个特定类的实例,或者是其子类的实例。它可以用于在运行时判断一个对象的真实类型,以便进行相应的操作。

instanceof 的语法格式如下:

object instanceof class

其中,object 是待检查的对象,class 是要检查的类名或接口名。

objectclass 类的实例(或其子类的实例)时,instanceof 返回 true;否则,返回 false

以下是一个示例代码,演示了 instanceof 的用法:

class Animal {
    // 父类的方法
}
​
class Dog extends Animal {
    // 子类的方法
}
​
class Cat extends Animal {
    // 子类的方法
}
​
public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        
        if (animal1 instanceof Dog) {
            Dog dog = (Dog) animal1;
            dog.bark(); // 调用 Dog 类的方法
        }
        
        if (animal2 instanceof Cat) {
            Cat cat = (Cat) animal2;
            cat.meow(); // 调用 Cat 类的方法
        }
    }
}

在上述示例中,我们有一个基类 Animal 和两个派生类 DogCat,每个类都有自己的方法。

在主程序中,我们创建了一个 Animal 类型的引用变量 animal1animal2,并将它们分别指向一个 Dog 对象和一个 Cat 对象。

我们使用 instanceof 关键字来检查 animal1animal2 的类型。如果 animal1Dog 类的实例,则将其转型为 Dog 类,并调用 bark() 方法。如果 animal2Cat 类的实例,则将其转型为 Cat 类,并调用 meow() 方法。

通过使用 instanceof 关键字,我们可以在运行时检查对象的类型,以便根据实际情况执行相应的操作。这在处理继承关系中的多态性时非常有用。需要注意的是,在进行类型转换时,我们通常应该先使用 instanceof 进行检查,以确保对象的类型是正确的,避免出现类型转换异常(ClassCastException)。

总结来说,instanceof 关键字是Java中用于检查对象类型的机制,用于判断一个对象是否是某个类的实例或其子类的实例。它可以帮助我们进行类型检查,以便在运行时执行适当的操作。

总结

Java是一种面向对象的编程语言,它支持面向对象编程的核心概念和特性。下面是对Java面向对象的总结:

  1. 类和对象:Java通过类(Class)来定义对象(Object)。类是一个模板,描述了对象的属性(成员变量)和行为(方法)。对象是类的一个实例,具有自己的状态和行为。

  2. 封装(Encapsulation):封装是将数据和代码包装在一个单个实体中的机制。在Java中,我们可以使用访问修饰符(如private、public、protected)来控制成员变量和方法的访问权限,以实现数据的隐藏和保护。

  3. 继承(Inheritance):继承是一种机制,允许一个类继承另一个类的属性和方法。子类(派生类)可以继承父类(基类)的特性,并且可以在此基础上添加自己的额外功能。继承可以提高代码的可重用性和可扩展性。

  4. 多态(Polymorphism):多态性是指同一个类型的对象,在不同情况下表现出不同的行为。通过继承和方法重写,子类可以覆盖父类的方法,从而实现多态性。多态性使得代码更加灵活,能够处理不同类型的对象。

  5. 抽象(Abstraction):抽象是隐藏对象的复杂性,只展示必要的信息和功能。在Java中,我们可以使用抽象类(Abstract Class)和接口(Interface)来定义抽象类型,这些类型不能被实例化,但可以被继承或实现。

  6. 接口(Interface):接口是一种约定,规定了类需要实现的方法。接口定义了一组方法的声明,而没有提供方法的实现。类可以实现一个或多个接口,以满足接口所定义的契约。

  7. 构造函数(Constructor):构造函数是一种特殊类型的方法,用于创建和初始化对象时调用。它具有与类相同的名称,并且没有返回类型。构造函数在使用 new 关键字创建对象时被自动调用。

  8. 成员变量和方法:类包含成员变量和方法。成员变量是类的属性,用于存储对象的状态。方法是类的行为,用于操作和处理数据。

  9. 包(Package):包是一种组织类和接口的机制,用于避免命名冲突。通过将类和接口组织在包中,可以更好地管理和维护代码。

  10. 异常处理(Exception Handling):Java提供了异常处理机制,用于处理程序运行过程中可能出现的错误。通过捕获和处理异常,可以使程序更加健壮和稳定。

通过使用这些面向对象的概念和特性,Java程序可以更加模块化、可读性和可维护性。面向对象编程使得代码更加易于理解和重用,并促进了软件开发过程中的抽象和分离。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿人啊兴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值