面向对象OOP(上)

1 面向对象的基本概念

1.1 什么是面向对象

面向对象程序设计(Object Oriented Programming,OOP)是一种基于对象概念的软件开发方法,是目前软件开发的主流方法。

1.2 对象

1.2.1 什么是对象

在面向对象的世界中认为万事万物皆可成为对象,但对象强调的是一个具体的个体,例如:杨树不是一个对象,但我家院子里的那颗杨树就是一个对象。

1.2.2 对象由什么构成

  • 对象由状态和行为构成。
  • 对象的状态是指对象的数据,对象的状态由变量表示,也叫对象的属性。
  • 对象的行为是指对象的功能,对象的行为由方法表示。
    例如:
学生对象{
  状态:姓名,成绩
  行为:听课,写作业
}

1.2.3 怎样创建对象

对象是由类实例化的时候创建,因此创建对象必须先定义类。

1.3 类

1.3.1 什么是类

类是具有相同的状态和相同的行为的一组对象的集合。例如:有学号、有姓名、有成绩的状态,有听课、写作业的行为的所有对象可以归为一个类,称其为学生类。类简单的理解就是具有多个对象的统称,而不是一个个体。

1.3.2 类与对象的关系

类与对象的关系就如同模具与由此模具制作出的模型之间的关系。一个类给出它所有对象的一个统一的定义,而它每个对象则都是符合这种定义的一个实例,因此类和对象的关系就是抽象和具体的关系。

1.3.3 类与对象的区别

  • 类是对某一类事物的抽象描述,不是具体的个体。
  • 对象是对某一事物的具体描述,是具体的个体。

2 定义类

2.1 类的构成

类是由属性和方法构成的。

2.2 类的定义

语法:

public class 类名 {
  //可编写0到n个属性
  数据类型 变量名1;
  数据类型 变量名2;

  //可编写0到n个方法
  修饰符 返回值类型 方法名(参数) {
    执行语句;
  }
}

注意:

  • public类的类名必须和类所在文件的文件名一致。
  • 如果不是public类,那么类名与类所在的文件名可以不一致。
  • 类名的命名规则是:帕斯卡命名法。

示例:

class Student{
    //类的属性
    String name;
    int score;
    String no;
    //类的方法
    public void play(){
        System.out.printf("我的名字是%s,我的成绩是%d,我的学号是%s",name,score,no);
    }
}

3 实例化对象

通过类创建对象的过程称为类的实例化,实例化的结果是产生一个实例,实例也叫对象。

3.1 实例化对象

语法
在程序中,实例化用new表示,new也是分配内存的意思

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

示例:

Student s1 = new Student();
Student s2 = new Student();

3.1.1 对象的内存分配

内存分配图

4 使用对象

对象的调用和方法是使用成员运算符来完成的。

4.1 对象调用属性

Student s1 = new Student();
    s1.name = "haha";
    s1.score = 78;

Student s2 = new Student();
    s2.name = "yaya";
    s2.score = 98;
内存分配图

4.2 对象调用方法

Student s1 = new Student();
    s1.name = "haha";
    s1.score = 78;
    s1.play();//调用方法

Student s2 = new Student();
    s2.name = "yaya";
    s2.score = 98;
    s2.play();//调用方法

运行结果:


5 方法重载(overload)

方法重载是OOP中的一个重要概念,而实际开发中经常用到方法重载。

5.1 方法重载的定义

在同一个类中:同名不同参,与返回值无关。
例如:

public class Student{
    public void play(){
    }
    public int play(int time){
        return 0;
    }
}

5.2 方法重载的调用

方法重载根据参数匹配原则进行调用

public void play(){
    System.out.printf("我的名字是%s,我的成绩是%d,我的学号是%s",name,score,no);
    System.out.println();
}
public int play(int time){
    return 0;
}
...(省略部分代码)
s1.play(1);//调用的是第5行的方法
s2.play();//调用的是第1行的方法

6 构造方法

6.1 什么是构造方法

在Java中,当类创建一个对象时,为该类对象的属性进行初始化的方法被称作构造方法。构造方法也叫构造函数,或者叫构造器。

  • 构造方法的方法名必须与类名相同。
  • 构造方法没有返回值,也不写void。
class Student{
    //构造方法
    Student(){

    }
}

6.2 构造方法的作用

为成员变量进行初始化。

6.3默认构造函数

当一个类没有定义构造函数时,那这个类默认具有一个无参的构造函数。默认构造函数为对象的属性赋默认值。
例如:

class Student{
    String name;
    int score;
    String no;
    
    public void play(){
        System.out.printf("我的名字是%s,我的成绩是%d,我的学号是%s",name,score,no);
    }
}

public class StudentTest {
    public static void main(String[] args) {
        Student s1 = new Student;
        s1.play();
    }
}

输出结果为:


运行结果

为什么输出的是null,0,null?

因为本例中没有定义构造函数,系统会自动添加一个默认构造函数,默认构造函数是无参的,会为所有的属性赋默认值,因此name是null,score是0,no是null。

6.4 构造方法的调用

构造方法是在实例化对象时调用的。并且实例化时传递的参数必须有构造方法的参数一致。
例如:

class Student {
    String name;
    int score;
    String no;
  
    Student(String name1,int score1){
        name= name1;
        score= score1;
    }
}
public class StudentTest {
    public static void main(String[] args) {
        Student s1 =new Student("haha",76);//调用student类的构造方法,为name和score属性初始化,no为默认值null
    }
}

注意:构造方法不允许通过对象名调用。

6.5 构造方法的重载

class Student{
    String name;
    int score;
    String no;
    //第1种构造方法的重载
    Student(String name1, int score1){
        name = name1;
        score = score1;
    }
    //第2种构造方法的重载
    Student(String name1, int score1, String no1){
        name = name1;
        score = score1;
        no = no1;
    }
    public void play(){
        System.out.printf("我的名字是%s,我的成绩是%d,我的学号是%s",name ,score ,no);
        System.out.println();
    }
}

public class StudentTest {
    public static void main(String[] args) {
        Student s1 = new Student("yaya",78);//调用第1种构造方法的重载
        s1.play();
        Student s2 = new Student("haha", 98,"111");//调用第2种构造方法的重载
        s2.play();
    }
}

7 this关键字

7.1 this关键字的使用

在类中,如果类的属性名和方法内部的局部变量同名时,那么在方法内部使用的是局部变量,也就是变量使用遵循就近原则,例如:

Student(String name,int score){
    name = name;
    score = score;

此时,就无法判断name的指代了,如此看来类的属性名和构造方法的参数名称不能相同。
但使用this关键字就能使类的属性名和构造方法的参数名称相同。使用示例如下:

class Student{
    String name;
    int score;
    String no;
    Student(String name,int score){
        //this代表正在运行的对象,当执行第16行代码时,调用了构造函数,此时this代表第16行的s1
        this.name = name; //this.name指的是对象的属性,name是指方法的参数
        this.score = score; //this.score指的是对象的属性,score是指方法的参数
    }
    public void play(){
        System.out.printf("我的名字是%s,我的成绩是%d,我的学号是%s",name ,score ,no);
    }
}

public class StudentTest {
    public static void main(String[] args) {
        Student s1 = new Student("yaya", 78);
        s1.play();
    }
}

运行结果:


运行结果

7.2 this关键字的省略

在非static方法内部使用属性,可以省略,例如:

public void sayHello(){
    System.out.printf("我是%s,我的成绩是%d,我的学号是%s",this.name,this.score,this.no);
}

可以写成

public void sayHello(){
    System.out.printf("我是%s,我的成绩是%d,我的学号是%s",name,score,no);
}

7.3 this调用重载方法

例如:我们知道学生姓名和成绩,不知道学号,但是显示学生信息时要求将学号显示为”未知“,而不是null。

分析:

有两种情况

  1. 知道姓名和成绩,不知道学号
  2. 知道姓名,成绩,学号

所以要设计两种构造的重载,设计结果如下:

class Student {
    String name;
    int score;
    String no;
    Student(String name,int score){
        this(name,score,"未知");//构造方法内部的this()表示调用本类的其他构造方法
    }

    Student(String name,int score,String no){
        this.name= name;
        this.score= score;
        this.no = no;
    }
}

注意:当使用this调用本类其他构造方法时,必须是构造方法内的第一行代码。

8 变量

变量分为成员变量和局部变量

8.1 局部变量

局部变量是定义在方法内的变量
例如:

    public void sayHello(){
        int height = 20;//局部变量
    }

8.2 成员变量

成员变量是类的属性,是定义在类内,方法外的变量。
例如:

class Student {
    String name;
    int score;
    String no;
}

8.3 成员变量和局部变量的区别

  • 作用域不同
    1. 成员变量作用域:整个类
    2. 局部变量的作用域:方法内
  • 初始值不同
    1. 成员变量由构造函数初始化的
    2. 局部变量需要手动初始化

在同一个方法中不允许有同名的局部变量,在不同的方法中可以有同名的局部变量。

局部变量可以和成员变量名相同,并且在使用时局部变量有更高的优先级。

9 对象数组

需求:

  1. 班级里有5名学生,输入每名学生的姓名和总成绩。
  2. 根据学生总成绩从高到低排名,显示学生名次、姓名、总成绩。

分析:

  1. 有哪些对象?有学生对象,有班级对象
  2. 对象有什么属性和方法?
    1. 学生有姓名,成绩的属性,学生不需要方法
    2. 班级有多名学生的属性,班级有排序方法,输出的方法

代码:
1:创建学生类

public class Student {
    //属性
    String name;
    int score;
    //构造
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
}

班级类:

public class ClassInfo {
    //属性
    Student []stus = null;

    //构造函数初始化班级大小
    public ClassInfo(int size){
        this.stus = new Student[size];
    }

    //排序方法
    public void sort(){
        if(this.stus.length==0){
            return;
        }
        for (int i = 0; i < this.stus.length-1; i++) {
            for (int j = 0; j < this.stus.length - i - 1; j++) {
                if(this.stus[j].score<this.stus[j+1].score){
                    Student temp = this.stus[j];
                    this.stus[j] = this.stus[j+1];
                    this.stus[j+1] = temp;
                }
            }
        }
    }

    //输出方法
    public void print(){
        for (int i = 0; i < stus.length; i++) {
            System.out.printf("姓名:%s,成绩%d,名次:%d",stus[i].name,stus[i].score,(i+1));
            System.out.println();
        }
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        //1:创建5个学生
        Student s1 = new Student("刘茂兵",60);
        Student s2 = new Student("田舍翁",80);
        Student s3 = new Student("杨礼之",90);
        Student s4 = new Student("余晨",65);
        Student s5 = new Student("乔思义",70);

        //2:创建班级
        ClassInfo classInfo = new ClassInfo(5);
        classInfo.stus[0] = s1;
        classInfo.stus[1] = s2;
        classInfo.stus[2] = s3;
        classInfo.stus[3] = s4;
        classInfo.stus[4] = s5;

        //3:排序
        classInfo.sort();

        //4:输出
        classInfo.print();
    }
}

运行结果

姓名:杨礼之,成绩90,名次:1
姓名:田舍翁,成绩80,名次:2
姓名:乔思义,成绩70,名次:3
姓名:余晨,成绩65,名次:4
姓名:刘茂兵,成绩60,名次:5

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容