Java面向对象(初级)

2023-12-23 07:29:33

面向对象编程(基础)

  • 面向对象编程(OOP)是一种编程范式,它强调程序设计是围绕对象、类和方法构建的。在面向对象编程中,程序被组织为一组对象,这些对象可以互相传递消息。面向对象编程的核心概念包括封装、继承和多态。

  • 相对应的,面向对象编程的对立面可以说是面向过程编程(Procedural Programming)。在面向过程编程中,程序主要由一系列的步骤或过程组成,更加侧重于顺序执行。与面向对象编程不同,面向过程编程没有对象的概念,而是专注于如何分解问题和编写独立的函数来解决它们。

两者对比:

特征面向过程编程面向对象编程
组织方式注重顺序执行,数据和功能分离数据和功能被组织成对象
可维护性较差,修改可能需要涉及多个部分更好,通过封装和抽象降低耦合度
可重用性较差,函数通常与特定问题耦合更高,对象和类的概念提高了代码的重用性
可扩展性较差,添加新功能可能需要对多处进行修改更强,继承和多态特性使得修改和扩展更为容易
代码复杂度高,数据和功能交织在一起,难以理解和维护低,通过对象的封装和抽象,代码结构更清晰
适用场景小型、直接问题的解决大型、复杂问题的解决

面向对象编程比面向过程编程可以适用更加复杂的场景。

1、类与对象

类是一种数据类型,是抽象、泛指的概念,定义了对象的属性和行为,但是并不是一个具体的实体。一个类可以有多个对象。并不占用空间

对象是一个类的具体的实例,拥有类描述的特征和行为。占据内存空间

在这里插入图片描述

对象在内存中的存储方式:

  1. 栈: 一般存放的是基本的数据类型(局部变量)
  2. 堆:存放的是对象(数组、Person等)
  3. 方法区:常量池(常量,比如字符串),类的加载信息。
(1)属性/成员变量/字段

属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类的int age 就是属性

属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;

共有四种访问修饰符:public, proctected, 默认, private

属性如果不赋值,有默认值,规则和数组一致。具体说: int 0short 0, byte 0, long 0, float 0.0``,double 0.0char \u0000boolean falseString null

举例:

class person{
    //四个属性:性别,姓名,年龄,存款
    String name;
    int age;
    double stroage;
    boolean gender;
}
(2) 创建对象
  1. 先声明,再创建

    //1、先声明再创建
    Person xiaoming;
    xiaoming = new Person();
    
  2. 直接创建

    //2、直接创建
    Person xiaoming = new Person();
    
(3)访问对象的属性

基本语法
对象名.属性名;

//访问属性
xiaoming.name;
xiaoming.age;
xiaoming.stroage;

2、成员方法

Java中的成员方法是指属于类或对象的函数,用于执行特定的操作或者返回特定的数值。它们可以访问类的属性和其他方法。

(1)方法调用机制

方法调用机制:执行方法或者函数时,会开辟一个独立的空间。

在这里插入图片描述

(2)成员方法的好处
  1. 可以提高代码的复用性
  2. 将实现的细节封装起来,可以供其他用户调用
(3)成员方法定义

访问修饰符 返回数据类型 方法名(形参列表){

语句:

return 返回值;

}

示例:

   public void f3(String s, int n){
        int m = n;
        return;			//没有返回值
    }
}
(4)类定义完善

在这里插入图片描述

3、成员方法传参机制

  • 基本数据类型:采用的事值传递(值拷贝),形参改变不影响实参。

  • 引用数据类型:引用类型传递的是地址**(传递的也是值,但是是地址的值),可以通过形参影响实参。**

        public static void main(String args[]){
            //引用传参,传递的是地址,拷贝了一份地址的值
            Person xiaoming = new Person();
            xiaoming.name = "小明";
            xiaoming.stroage = 1202.23;
            xiaoming.f3(xiaoming);
            //虽然穿进的f3将xiaoming置为空了,但是外面的xiaoming不影响,只是在新的栈空间拷贝了一份地址。
            System.out.println("xiaoming"+xiaoming.stroage);
        }
    }
    class Person{
        String name;
        double stroage;
        public void f3(Person xiaoming){
            xiaoming = null;
        }
    

4、overload(方法重载)

(1)概念

? java方法重载指的是在同一个类中可以有多个方法具有相同的名称,但参数列表不同的情况。参数列表可以包括参数的类型、数量或顺序。

(2)优点
  • 代码可读性和易用性:相同方法名结合不同的参数类型或数量可以简化代码并提高易用性。
  • 灵活性:允许处理不同类型或数量的输入。
  • 避免命名冲突:避免为不同功能编写相似但不同的方法名。
  • 代码复用:通过重载方法,可以避免为每个略有不同的情况编写新的方法,提高了代码的复用性。
(3)举例
public class MathHelper {
    // 重载的方法1:计算两个整数之和
    public int add(int a, int b) {
        return a + b;
    }

    // 重载的方法2:计算三个整数之和
    public int add(int a, int b, int c) {
        return a + b + c;
    }

    // 重载的方法3:计算两个小数之和
    public double add(double a, double b) {
        return a + b;
    }
}
(4)注意事项
  • 方法名必须相同
  • 形参列表,必须不同,(形参类型或者个数或者顺序,至少一样不同,参数名没有要求)
  • 返回类型,没有要求

5、可变参数

(1)概念

可变参数允许方法接受不定数量的参数。在 Java 中,使用省略号 ... 来表示可变参数。这些参数被封装为数组,并且只能出现在方法参数列表的最后。

(2) 基本语法

基本的语法:

javaCopy codepublic void methodName(DataType... parameterName) {
    // 方法体
}

其中:

  • methodName 是方法的名称。
  • DataType 是可变参数的数据类型。它可以是任何数据类型,甚至可以是自定义的类。
  • parameterName 是可变参数的名称。习惯上使用复数形式,如 numbersvalues 等,但也可以使用其他合适的名称。
  • ... 表示可变参数的语法。
(3)举例
public class MyClass {
    public void printValues(String... values) {
        for (String value : values) {
            System.out.println(value);
        }
    }

    public static void main(String[] args) {
        //可变参数
        MyClass obj = new MyClass();
        obj.printValues("Hello", "World");
        obj.printValues("Java", "is", "awesome");
        obj.printValues(); // 可以不传入任何参数
    }
}
(4)注意事项
  1. 可变参数实参可以为0个或者多个
  2. 可变参数的实参可以为数组
  3. 可变参数的本质就是数组
  4. 可变参数可以和普通类型参数一起放在形参列表,但是必须保证可变参数在最后面
  5. 一个形参列表当中只可以出现一个可变参数

6、作用域

(1)基本概念

在java中,变量主要有两种,一种是属性(类里面的成员,也可以成为全局变量)变量一种是局部变量。一般的局部变量是指定义在成员方法中的变量,作用域是定义的代码块中,随着代码块的执行而创建,随着代码块的结束而销毁。。全局变量,一般是指属性,作用域为整个类。伴随着对象的创建而创建,对象的销毁而销毁。

(2)异同点
  1. 声明位置
    • 属性变量(成员变量):定义在类中,但在任何方法、构造函数或块之外。
    • 局部变量:定义在方法、构造函数或块内部。
  2. 作用域
    • 属性变量(成员变量):整个类可见,或者其他类使用(通过对象调用)。
    • 局部变量:仅在所属的方法、构造函数或块中可见。
  3. 默认值
    • 属性变量(成员变量):如果未显式初始化,会有默认值。
    • 局部变量:必须在使用之前显式初始化,没有默认值,否则会产生编译错误。
  4. 生命周期
    • 属性变量(成员变量):对象创建至销毁。
    • 局部变量:方法执行期间。
  5. 修饰符(public,private,protected,默认)
    • 属性变量(成员变量):可以加修饰符。
    • 局部变量:不可以加修饰符。

全局变量和局部变量可以重名,访问的原则是就近原则。

(3) 举例
public class Example {
        // 属性变量(成员变量)
        private int memberVariable;
    public void someMethod() {
        // 局部变量
        int localVar = 10;
        System.out.println(memberVariable); // 成员变量在类的任何方法中可见
        System.out.println(localVar); // 局部变量仅在 someMethod() 方法中可见
    }

    public void anotherMethod() {
        // 局部变量
        int anotherLocalVar = 20;
        // System.out.println(localVar); // 这里会产生编译错误,局部变量 localVar 不可见
        System.out.println(anotherLocalVar);
    }
}

7、构造器(构造方法)

构造类是类的一种特殊方法,主要作用就是完成对新对象的初始化。

(1)概念

构造器用于在创建对象时进行初始化。构造器的名称必须与类名完全相同,并且没有返回类型,甚至不是 void 类型。它们的主要作用是初始化新创建的对象,并且在使用 new 关键字实例化对象时被自动调用。

(2) 特点
  1. 与类同名:构造器的名称必须与类名完全相同。
  2. 没有返回类型:与普通方法不同,构造器没有返回类型。
  3. 自动调用:在使用 new 关键字创建对象时,构造器会自动被调用。
  4. 重载: 一个类可以定义多个不同的构造器
  5. 默认构造器: 如果没有定义构造器,系统会自动生成一个默认的无参的构造器
  6. 覆盖默认构造器:一旦自己定义了一个新的构造器,默认的构造器就被覆盖了,除非自己显示定义一下。即:Dog(){}
(3)举例
public class Car {
    private String make;
    private String model;
    private int year;

    // 构造器1:接受三个参数
    public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    // 构造器2:接受两个参数(默认年份为0)
    public Car(String make, String model) {
        this.make = make;
        this.model = model;
        this.year = 0; // 默认年份为0
    }

    // 构造器3:接受一个参数(默认制造商为Unknown,型号为Unknown,年份为0),无参构造器,显示定义
    public Car() {
        this.make = "Unknown";
        this.model = "Unknown";
        this.year = 0;
    }

    // 其他方法
    public void displayDetails() {
        System.out.println("Make: " + make + ", Model: " + model + ", Year: " + year);
    }

    public static void main(String[] args) {
        // 使用不同的构造器创建对象
        Car car1 = new Car("Toyota", "Corolla", 2022);
        Car car2 = new Car("Honda", "Civic");
        Car car3 = new Car();

        // 显示对象的属性信息
        car1.displayDetails();
        car2.displayDetails();
        car3.displayDetails();
    }
}
(4)对象创建的流程

代码如下:

//类person
class Person{
    int age = 90;
    String name;
    
    //构造器
    Person(String n, int a){
        name = n;       //给属性赋值
        age = a;
    }
}

Person p = new Person("小明", 20);

流程分析如下:

  1. 加载Person类信息(Person.class),只会加载一次
  2. 在堆中分配空间(地址)
  3. 完成对象的初始化
    1. 第一步:默认初始化,age = 0, name = null;
    2. 第二步: 显式初始化,age = 90, name = null
    3. 第三步:构造器初始化,age = 20, name = 小明
  4. 在对象在堆中的地址,返回给p(p是对象名,也可以理解成对象的引用)

到目前为止,类的定义如下:
在这里插入图片描述

8、this

(1)概念

java 虚拟机会给每个对象分配this,this 可以在类的方法中引用当前对象的实例。例如,在类的方法内部使用 this 可以访问当前对象的属性和方法。

(2)内存理解

this可以理解为一个当前对象,存在当前对象的堆内存当中,**这个对象指向的地址就是本身对象所处的地址。**如下图所示:
在这里插入图片描述

(3)举例
public class changeKind {
    public static void main(String args[]){
        Person p = new Person("小明", 20);
        //hashcode可以近似表示对象的地址,可以输出this和当前对象的hashcode看看对象是否一样
        System.out.println("person的地址:"+p.hashCode());
        //输出:person的地址:1163157884
        p.info();
        //输出:小明当前对象的hashcode是1163157884,与前面的相同
        //说明this指向当前对象,哪个对象调用,this就代表哪个对象
    }
}
//类person
class Person{
    int age = 90;
    String name;
    //构造器
    Person(String n, int a){
        name = n;       //给属性赋值
        age = a;
    }
    public void info(){
        System.out.println(this.name+"当前对象的hashcode是"+this.hashCode());
    }
}
(4)注意事项
  1. this关键字可以访问本类的属性,方法和构造器

  2. this可以用来区分当前类的属性和局部变量

  3. 访问成员方法的语法:this.方法名(参数列表);

  4. 访问构造器语法:this(参数列表);注意只能在构造器中使用 (在构造器中访问另外一个构造器,必须放在构造器的第一条语句)

    class T{
        public  T(){
            //必须放在构造器的第一条语句,在一个构造器中访问另外一个构造器
            this("jack",100);
            System.out.println("T()构造器");
        }
    
        public T(String name, int age){
            System.out.println("T(String name, int age)构造器");
        }
    }
    
  5. this不能在类定义的外部使用,只能在类定义的方法中使用。

9、递归

? 递归的重要规则:

  1. 执行一个方法时,就会创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的,不会相互影响
  3. 如果方法中使用的是引用类型的变量(比如:数组,对象),就会共享该引用类型的数据
  4. 递归必须向退出条件逼近(递归出口),否则就是无限递归,出现栈溢出的情况
  5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就会将结果返回给谁。当方法执行完毕或者返回时,该方法也就执行完毕了。

举例:

在这里插入图片描述

文章来源:https://blog.csdn.net/m0_46335449/article/details/135162765
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。