Java基础之面向对象

Java基础之面向对象

  • 一、面向对象
    • 1.1、面向对象概念
    • 1.2、面向对象的三大特征
  • 二、类与对象
    • 2.1、构造方法
    • 2.2、创建对象
    • 2.3、实例化
      • 2.3.1、什么是实例化
      • 2.3.2、实例化的过程
      • 2.3.3、实例化的用途
  • 三、面向对象三大特征
    • 3.1、封装
      • 3.1.1、封装概念理解
      • 3.1.2、封装目标
      • 3.1.3、封装实现
    • 3.2、继承
      • 3.2.1、继承概念理解
      • 3.2.2、继承的实现
      • 3.2.3、super和this关键字
    • 3.3、多态
      • 3.3.1、多态的实现方式
  • 四、抽象类
    • 4.1、抽象类概念理解:
    • 4.2、抽象类总结:
  • 五、接口
    • 5.1、接口概念理解:
    • 5.2、接口和类的区别:
    • 5.3、接口的特点
    • 5.4、接口声明
    • 5.5、接口实现
      • 5.5.1、实现多个接口
      • 5.5.2、静态方法/常量的实现
    • 5.6、实现类的注意事项

一、面向对象

1.1、面向对象概念

  • 面向对象编程(Object-Oriented Programming, OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据
  • 抽象:编程思想!持续的学习,茅塞顿开!多实践,多测试大脑中的想法!实践出真知
  • 三大特性:封装,继承,多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板

1.2、面向对象的三大特征

  • 封装(Encapsulation): 封装是将对象的状态和行为包装在一起,并对外部隐藏对象的内部实现细节。通过使用 private 访问修饰符来限制对类的直接访问,通过公共的 getter 和 setter 方法来控制对对象状态的访问和修改。

  • 继承(Inheritance): 继承允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和行为。子类可以使用父类的成员,并且可以通过添加新的成员或修改现有成员来扩展或修改其行为。

  • 多态(Polymorphism): 多态允许一个对象在不同的上下文中表现出不同的行为。它有两种形式:编译时多态(方法重载)和运行时多态(方法重写)。在运行时多态中,同一类的对象可以根据其实际类型调用不同的方法,这提高了代码的灵活性和可扩展性。

二、类与对象

2.1、构造方法

每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。

在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。

下面是一个构造方法示例:

public class Car{
    public Car(){

    }
    public Car(String name){
        //构造器只有一个参数:name
    }
}

2.2、创建对象

对象是根据类创建的。在Java中,使用关键字 new 来创建一个新的对象。创建对象需要以下三步:

  • 声明:声明一个对象,包括对象名称和对象类型。
  • 实例化:使用关键字 new 来创建一个对象。
  • 初始化:使用 new 创建对象时,会调用构造方法初始化对象。

下面是一个创建对象的实例:

public class Car{
    public Car(){

    }
    public Car(String name){
        //构造器只有一个参数:name
        System.out.println("车的名字:"+name);
    }
    
    //一个类是一个模板,它描述了对象的属性和行为
    //当我们实例化一个类时,我们创建了一个具体的对象,该对象具有类中定义的属性和行为
    public static void main(String[] args){
        //创建一个Car对象
        Car myCar =new Car("BMW");
    }
}

2.3、实例化

实例化是面向对象的一个概念,在创建对象和使用对象中使用。以下是实例化的过程和用法

2.3.1、什么是实例化

在Java中,实例化是指创建一个类的对象(instance)。类是一种抽象的模板,而实例是这个模板具体化后的一个具体对象。简而言之,实例化就是根据类的定义创建类的对象的过程。

实例化是通过使用new关键字后跟构造函数来完成的。构造函数是类中的特殊方法,用于初始化对象的属性。

public class Car {
    // 数据成员
    private String brand;
    private int year;

    // 构造函数
    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    public String getBrand(){
        return brand;
    }

    public int getYear(){
        return year;
    }

    // 方法
    public void start() {
        System.out.println("The car is starting.\nit's name:"+brand+" \nit's year:"+year);
    }


    public static void main(String[] args){
        //创建一个Car对象
        Car myCar = new Car("Toyota", 2022);
        myCar.start();

    }
}

2.3.2、实例化的过程

当我们使用new关键字实例化一个对象时,实际上发生了以下几个步骤:

  • 内存分配:Java会在内存中为对象分配一块空间,用于存储对象的属性值。
  • 初始化:Java会调用类的构造方法来对对象进行初始化。构造方法是一个特殊的方法,用于初始化对象的属性。
  • 返回引用:Java会返回一个指向新创建对象的引用。我们可以使用该引用来操作对象,如访问其属性或调用其方法。

2.3.3、实例化的用途

实例化Java对象有多种用途,包括:

  • 创建对象:通过实例化一个类,我们可以创建一个具体的对象,用于存储和操作数据。
  • 调用方法:通过实例化一个类的对象,我们可以调用该类的方法来执行特定的操作。例如,在上面的示例中,我们通过调用Car类的getBrand和getYear方法来获取对象的属性值。
  • 传递参数:通过实例化一个类的对象,并将该对象作为参数传递给其他方法,我们可以在方法中使用该对象来执行特定的操作。

三、面向对象三大特征

3.1、封装

3.1.1、封装概念理解

封装是一种面向对象编程的原则,它将对象的内部细节隐藏在对象外部不可见的层次。封装有助于保护对象的状态,防止外部直接访问或修改对象的内部数据,从而提高代码的可维护性和安全性。

在封装中,通过使用访问修饰符(如 privateprotectedpublic)来限制对类的成员的访问。通常,类的字段(成员变量)被声明为私有(private),而提供公共的方法(getter和setter)来允许外部访问和修改这些字段。

3.1.2、封装目标

  1. 隐藏内部实现细节: 封装将对象的内部实现细节隐藏在类的内部,只暴露必要的接口。这使得对象在不暴露其内部工作原理的情况下,可以被其他代码使用。
  2. 提供公共接口: 通过提供公共的方法,可以控制对对象的访问和修改。这使得可以在这些方法中添加逻辑,例如验证和处理,以确保对对象的安全操作。
  3. 增加灵活性: 封装提供了一种更改对象内部实现的灵活性,而不会影响与对象交互的其他代码。只要对象的公共接口保持不变,对象的内部实现可以自由地修改。

3.1.3、封装实现

在这个例子中,Person 类封装了 nameage 两个私有字段,通过公共的getter和setter方法提供对这些字段的访问和修改。构造方法用于在创建对象时初始化这些字段的值。在setter方法中,可以添加逻辑进行验证,例如确保年龄不为负数。通过封装,Person 类隐藏了其内部实现细节,外部代码只能通过公共接口来与对象交互。

public class Person {
    // 私有字段
    private String name;
    private int age;

    // 构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 公共的getter方法用于获取私有字段的值
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    // 公共的setter方法用于修改私有字段的值
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        // 在setter方法中可以添加逻辑进行验证
        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("年龄不能为负数");
        }
    }

    public static void main(String[] args) {
        // 创建一个Person对象
        Person person = new Person("John", 30);

        // 通过getter方法获取私有字段的值
        System.out.println("Name: " + person.getName());
        System.out.println("Age: " + person.getAge());

        // 通过setter方法修改私有字段的值
        person.setName("Jane");
        person.setAge(25);

        // 再次通过getter方法获取修改后的值
        System.out.println("Modified Name: " + person.getName());
        System.out.println("Modified Age: " + person.getAge());
    }
}

3.2、继承

3.2.1、继承概念理解

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承的特性:

  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

3.2.2、继承的实现

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object(这个类在 java.lang 包中,所以不需要 import)祖先类。

  1. extends关键字

    类的继承是单一继承、一个子类只能有一个父类,因此extends只能继承一个类

    public class Animal { 
        private String name;   
        private int id; 
        public Animal(String myName, int myid) { 
            //初始化属性值
        } 
        public void eat() {  //吃东西方法的具体实现  } 
        public void sleep() { //睡觉方法的具体实现  } 
    } 
     
    public class Dog  extends  Animal{ 
    }
    
  2. implements关键字

    使用implements关键字可以使Java具有多继承的特性,只适用于类接口的情况。可以同时继承多个接口。

    public interface A {
        public void eat();
        public void sleep();
    }
     
    public interface B {
        public void show();
    }
     
    public class C implements A,B {
    }
    

3.2.3、super和this关键字

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

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

class Animal {
  void eat() {
    System.out.println("animal : eat");
  }
}
 
class Dog extends Animal {
  void eat() {
    System.out.println("dog : eat");
  }
  void eatTest() {
    this.eat();   // this 调用自己的方法
    super.eat();  // super 调用父类方法
  }
}
 
public class Test {
  public static void main(String[] args) {
    Animal a = new Animal();
    a.eat();
    Dog d = new Dog();
    d.eatTest();
  }
}

3.3、多态

多态:就是对象的多种表现形式。

即统一行为的不同表现形式(比如:发出叫声,不同的物种发出的声音不同)

代码示例:

// 动物类
class Animal {
    void makeSound() {
        System.out.println("发出通用动物声音");
    }
}

// 狗类
class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("汪汪汪!");
    }
}

// 猫类
class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("喵喵喵!");
    }
}

// 鹦鹉类
class Parrot extends Animal {
    @Override
    void makeSound() {
        System.out.println("咕咕咕!");
    }
}

// 动物园
public class Zoo {
    public static void main(String[] args) {
        // 使用多态,同样的方法调用会表现出不同的行为
        Animal dog = new Dog();
        Animal cat = new Cat();
        Animal parrot = new Parrot();

        dog.makeSound();    // 输出: 汪汪汪!
        cat.makeSound();    // 输出: 喵喵喵!
        parrot.makeSound(); // 输出: 咕咕咕!
    }
}

3.3.1、多态的实现方式

  • 方法一:重写。【参考:Java重写(Override)与重载(Overload)】
  • 方法二:接口
  • 方法三:抽象类和抽象方法

四、抽象类

4.1、抽象类概念理解:

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

代码示例:

  • 编写一个抽象类:
abstract class Shape {
    abstract void draw();
    void commonMethod() {
        System.out.println("Common method in Shape class");
    }
}
  • 创建子类:
class Circle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a circle");
    }
}

class Rectangle extends Shape {
    @Override
    void draw() {
        System.out.println("Drawing a rectangle");
    }
}

4.2、抽象类总结:

  • 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含具体方法体,就是不给出方法的具体实现也就是方法的具体功能。
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

五、接口

5.1、接口概念理解:

它允许定义一组方法的声明,但没有提供这些方法的具体实现。接口是一种约定,指定了实现它的类应该具有哪些行为。

5.2、接口和类的区别:

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

5.3、接口的特点

  • 接口使用 interface 关键字声明。
  • 接口中可以包含抽象方法和常量(public static final)。
  • 接口中的方法默认是公有的(public)。
  • 类通过 implements 关键字实现接口。且类实现接口时必须实现接口中的所有抽象方法。

5.4、接口声明

接口的声明:

[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}

示例:

//接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
//接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
interface MyInterface {
    // 抽象方法的声明
    void myAbstractMethod();
	public void eat();
    // 接口中的常量
    int MAX_VALUE = 100;
}

5.5、接口实现

一个类通过使用 implements 关键字来实现一个或多个接口。实现接口的类必须提供接口中定义的所有抽象方法的具体实现。

代码示例

interface MyInterface {
    void myMethod();
}

class MyClass implements MyInterface {
    @Override
    public void myMethod() {
        // 具体实现
    }
}

5.5.1、实现多个接口

interface Interface1 {
    void method1();
}

interface Interface2 {
    void method2();
}

class MyClass implements Interface1, Interface2 {
    @Override
    public void method1() {
        // 实现 Interface1 中的方法
    }

    @Override
    public void method2() {
        // 实现 Interface2 中的方法
    }
}

5.5.2、静态方法/常量的实现

接口中的静态方法可以直接在接口中调用/接口中的常量是隐式地被 public static final 修饰的,实现类不需要提供对静态方法/常量的具体实现。

interface MyInterface {
    static void myStaticMethod() {
        // 静态方法实现
    }
     int MAX_VALUE = 100; // 常量
}

class MyClass implements MyInterface {
    // 不需要提供对静态方法的具体实现
}

5.6、实现类的注意事项

  • 实现类必须提供接口中所有抽象方法的具体实现,否则该类必须声明为抽象类。
  • 如果一个类同时继承类(extends)和实现接口(implements),extends 关键字应该在 implements 关键字之前。
class MyConcreteClass extends MyParentClass implements MyInterface {
    // 提供对接口和父类的具体实现
}

你可能感兴趣的:(java,开发语言)