Chapter 07 OOP初级 part2
侧边栏壁纸
  • 累计撰写 53 篇文章
  • 累计收到 5 条评论

Chapter 07 OOP初级 part2

bbchen
2022-09-19 / 1 评论 / 47 阅读 / 正在检测是否收录...

方法重载(OverLoad)

java 中允许同一个类中,多个同名方法的存在,但要求形参列表不同

比如: System.out.println(); out 是 PrintStream 类型

好处:

  1. 减轻起名的麻烦
  2. 减轻记名的麻烦

快速入门

image-20220919123908782

public class OverLoad01 {
    public static void main(String[] args) {
        MyCaculator c = new MyCaculator();
        System.out.println(c.calculate(1, 2)); 
        System.out.println(c.calculate(1, 2.5));
        System.out.println(c.calculate(1.5, 2));
        System.out.println(c.calculate(1, 2, 3));   
    }
}

class MyCaculator {
    public int calculate(int n1, int n2){
        return n1 + n2;
    }

    public double calculate(int n1, double n2){
        return n1 + n2;
    }

    public double calculate(double n1, int n2){
        return n1 + n2;
    }

    public int calculate(int n1, int n2, int n3){
        return n1 + n2 + n3;
    }
}

细节

  1. 方法名要相同
  2. 形参列表:必须不同(形参类型或个数或顺序,至少有一个不同,形参名无要求)
  3. 返回类型无要求

可变参数

java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。

细节

  1. 可变参数的实参可以为 0 个或任意多个
  2. 可变参数的实参可以为数组
  3. 可变参数的本质就是数组
  4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
  5. 一个形参列表中只能出现一个可变参数

练习

image-20220919155449060

public class VarParameterExercise {
    public static void main(String[] args) {
        HspMethod method = new HspMethod();
        System.out.println(method.showScore("bbchen", 100, 80));    // 2门
        System.out.println(method.showScore("Tim", 90, 100, 80));    // 3门
        System.out.println(method.showScore("Eason", 90, 100, 80, 70.5, 100));   //5门
    }

}

class HspMethod {
    // 传入可变参数 scores
    public String showScore(String name, double... scores){
        double totalScore = 0;
        for(int i = 0; i < scores.length; i++){
            totalScore += scores[i];    // 当作数组处理求和
        }
        String ret = name + " " + scores.length 
                    + "门课的总分为:" + totalScore;
        return ret;
    }
}

作用域 (scope)

  1. 在 java 编程中,主要的变量就是属性(成员变量)和局部变量
  2. 局部变量一般是指在成员方法中定义的变量
  3. 作用域分类:

    全局变量:也就是属性

    局部变量:除了属性之外的其他变量,作用域为定义它的代码块中

  4. 全局变量(属性)可以不赋值,直接使用,因为有默认值;局部变量必须赋值后才能使用,因为有默认值

细节

  1. 属性和局部变量可以重名,访问时遵循就近原则
  2. 在同一个作用域中,比如同一个成员方法中,两个局部变量不能重名
  3. 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。即在一次方法调用过程中。
  4. 作用域范围不同

    全局变量(属性):可以被本类使用,或者被其他类使用(通过对象调用)。两种调用方法:

    image-20220919165056848

    局部变量:只能在本类的对应方法中使用

  5. 修饰符不同

    全局变量(属性)可以加修饰符(public protected private..)

    局部变量不可以加修饰符

构造方法/构造器(constructor)

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

基本语法

[修饰符] 方法名(形参列表){

​ 方法体;

}

说明:

  1. 构造器的修饰符可以默认,也可以是 public protected private
  2. 构造器没有返回值
  3. 方法名和类名必须一样
  4. 参数列表 和 成员方法一样的规则
  5. 构造器的调用由系统完成

快速入门

public class Constructor01 {
    public static void main(String[] args) {
        // new一个对象时,直接通过构造器指定名字和年龄
        Person p1 = new Person("Smith", 45);
        System.out.println("p1对象的name=" + p1.name);
        System.out.println("p1对象的age=" + p1.age);
    }
}
class Person{
    String name;
    int age;
    // 构造器
    // 1.没有返回值,也不能写void
    // 2.构造器的名称和类Person一样
    // 3.构造器形参列表的规则和成员方法一致
    public Person(String pName, int pAge){
        System.out.println("构造器被调用,完成对象的属性初始化");
        name = pName;
        age = pAge;
    }
}

image-20220919170749959

细节

  1. 一个类可以定义多个不同的构造器,即构造器重载
  2. 构造器名和类名要相同
  3. 构造器没有返回值
  4. 构造器是完成对象的初始化,不是创建对象
  5. 在创建对象时,系统自动调用该类的构造方法
public class ConstructorDetail {
    public static void main(String[] args) {
        // new一个对象时,直接通过构造器指定名字和年龄
        Person p1 = new Person("Smith", 45);    // 第一个构造器
        System.out.println("p1对象的name=" + p1.name);
        System.out.println("p1对象的age=" + p1.age);

        Person p2 = new Person("Jim");      // 第二个构造器
        System.out.println("p2对象的name=" + p2.name);
    }
}
class Person{
    String name;
    int age;
    // 第一个构造器
    public Person(String pName, int pAge){
        name = pName;
        age = pAge;
    }
    // 第二个构造器,只初始化姓名
    public Person(String pName){
        name = pName;
    }
}
  1. 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫做默认构造器),使用 javap 指令反编译查看

    image-20220919192431958

    image-20220919192533380

  1. 一旦定义了自己的构造器,默认的构造器就被覆盖了,就不能再使用默认的无参构造器,除非显式地定义一下:Dog(){}

对象创建的流程分析

对象(在堆中)数据先进行默认初始化,再进行显性初始化,最后构造器的初始化

image-20220919194749211

  1. 加载Person类信息(Person.class),只会加载一次
  2. 在堆中分配空间(地址)
  3. 完成对象初始化 =》三步
  4. 对象在堆中的地址,返回给p(p是对象名,即对象的引用)
public class ConstructorExercise {
    public static void main(String[] args) {
        // new一个对象时,直接通过构造器指定名字和年龄
        Person p1 = new Person();    // 第一个构造器
        System.out.println("p2对象的name=" + p1.name);      // null
        // 构造器初始化总是最后执行,因此 p1.name 并非80而是18
        System.out.println("p1对象的age=" + p1.age);        // 18

        Person p2 = new Person("Jim", 17);      // 第二个构造器
        System.out.println("p2对象的name=" + p2.name);
        System.out.println("p2对象age=" + p2.age);
    }
}
class Person{
    // 第一个构造器,无参
    public Person(){
        age = 18;
    }
    // 第二个构造器,初始化 name 和 age
    public Person(String pName, int pAge){
        name = pName;
        age = pAge;
    }
    String name;
    int age = 80;
}

this 关键字

引出

image-20220919200328785

java 虚拟机会给每个对象分配 this,代表当前对象。使用 this 解决上图的变量命名问题。

public Dog(String name, int age){
    // this.name 就是当前对象的属性 name
    this.name = name;
    // this.age 就是当前对象的属性 age
    this.age = age;
}

理解 this

image-20220919210410203

简单的说,哪个对象调用,this 就代表哪个对象

细节

  1. this 可以用来访问本类的属性、方法、构造器
  2. this 用于区分当前类的属性和局部变量
  3. 访问成员方法的语法:this.方法名(参数列表)
  4. 访问构造器语法:this(参数列表);

    注意只能在构造器中使用(即只能在构造器中访问另一个构造器)

    注意this(参数列表)必须放置在第一条语句

  5. this 不能在类定义的外部使用,只能在类定义的方法中使用
public class This01 {
    public static void main(String[] args) {
        Person p1 = new Person("Tim", 18);
        Person p2 = new Person("Smith", 20);
        Person p3 = new Person("Tim", 18);

        System.out.println("p1 p2比较结果:" + p1.compareTo(p2));
        System.out.println("p1 p3比较结果:" + p1.compareTo(p3));
    }
}

class Person{
    String name;
    int age;

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

    public boolean compareTo(Person p){
        // 姓名年龄是否一样
        // if(this.name.equals(p.name) && this.age == p.age){
        //     return true;
        // }
        // else{
        //     return false;
        // }
        return this.name.equals(p.name) && this.age == p.age;
    }
}
0

评论

博主关闭了所有页面的评论