Java基础之面向对象

Java基础之面向对象

一、面向对象

1.1、面向对象概念

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

1.2、面向对象的三大特征

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

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

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

二、类与对象

2.1、构造方法

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

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

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

java 复制代码
public class Car{
    public Car(){

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

2.2、创建对象

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

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

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

java 复制代码
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关键字后跟构造函数来完成的。构造函数是类中的特殊方法,用于初始化对象的属性。

java 复制代码
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 类隐藏了其内部实现细节,外部代码只能通过公共接口来与对象交互。

java 复制代码
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只能继承一个类

    java 复制代码
    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具有多继承的特性,只适用于类接口的情况。可以同时继承多个接口。

    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关键字:指向自己的引用。

java 复制代码
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、多态

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

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

代码示例:

java 复制代码
// 动物类
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、抽象类概念理解:

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

代码示例:

  • 编写一个抽象类:
java 复制代码
abstract class Shape {
    abstract void draw();
    void commonMethod() {
        System.out.println("Common method in Shape class");
    }
}
  • 创建子类:
java 复制代码
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、接口声明

接口的声明:

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

示例:

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

5.5、接口实现

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

代码示例

java 复制代码
interface MyInterface {
    void myMethod();
}

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

5.5.1、实现多个接口

java 复制代码
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 修饰的,实现类不需要提供对静态方法/常量的具体实现。

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

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

5.6、实现类的注意事项

  • 实现类必须提供接口中所有抽象方法的具体实现,否则该类必须声明为抽象类。
  • 如果一个类同时继承类(extends)和实现接口(implements),extends 关键字应该在 implements 关键字之前。
java 复制代码
class MyConcreteClass extends MyParentClass implements MyInterface {
    // 提供对接口和父类的具体实现
}
相关推荐
Abladol-aj41 分钟前
并发和并行的基础知识
java·linux·windows
清水白石00841 分钟前
从一个“支付状态不一致“的bug,看大型分布式系统的“隐藏杀机“
java·数据库·bug
Elihuss2 小时前
ONVIF协议操作摄像头方法
开发语言·php
Swift社区5 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht5 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht5 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20245 小时前
Swift 数组
开发语言
吾日三省吾码6 小时前
JVM 性能调优
java
stm 学习ing6 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc7 小时前
《Python基础》之字符串格式化输出
开发语言·python