第六章、面向对象(oop)

目录

一、面向对象概述

二、设计对象并使用

1、类是什么?

2、如何创建类?

三、对象在内存中的运行机制

1、多个对象的内存图

 2、两个变量指向同一个对象内存图

 补充:垃圾回收

四、模拟购物车

五、构造器

1、学习构造器的目的

2、构造器的基本知识

 3、构造器的注意事项

六、this关键字

1、this关键字是什么

2、this关键字的作用

七、封装

1、封装的基本思想

2、如何更好的封装

八、标准javaBean

 九、面向对象基础案例

案例过程解析:

十、 成员变量和局部变量的区别


一、面向对象概述

面向对象术语:

OOA 面向对象分析

OOD 面向对象设计

OOP 面向对象编程

完成一个软件的过程:分析、设计、编程。

PM 指项目经理

什么是面向对象?

面向对象就是写程序的套路。

面向可以理解为找、拿;对象可以理解为东西;面向对象编程:找\拿 东西过来编程。

为什么用面向编程?

面向对象编程与日常生活中解决问题的方法相一致,例如扫地,必须先找一个扫把或者去某个地方,就必须找辆车,因此写程序解决问题同样需要找一个"东西"来帮助我们实现,这样写程序更符合人类的思维习惯,使编程更简单、更好理解。

面向对象学什么?

通过面向对象的语法学会自己设计对象并使用。例如生活中要拧一颗螺丝就要设计一个螺丝刀来解决问题。

二、设计对象并使用

1、类是什么?

例如日常生活中造房子就需要设计图,通过设计图来建造,而这个设计图就相当于是类。

是对象共同特征的描述。

对象:是真实存在的具体实例。 所以对象就是实例,实例就是对象。

因此,在java中必须先设计类,才能创建对象并使用。

2、如何创建类?

2、创建类注意事项

  • 类名首字母建议大写,满足驼峰模式,不能使用关键字,必须是合法的标识符
  • 一个java文件中可以定义多个class类,但只能一个类是public修饰,而且public修饰的类名必须成为代码文件名,建议一个代码文件只定义一个类。
  • 成员变量(属性)的完整定义格式:修饰符 数据类型 变量名称 = 初始化值;一般无需指定初始化值,存在默认值。

修饰符  数据类型 变量名称 = 初始化值

public        int             a       =       0;

/*
初始化 默认值规则
byte short int long    0
double float           0.0
boolean                false
String等引用类型         null
 */

三、对象在内存中的运行机制

1、多个对象的内存图

先将.class文件加载到方法区,然后将main方法提到栈内存中执行,执行第一句,将Car类的.class文件加载到方法区,(等号左边)定义了一个引用类型的变量c1作为对象名,是一个局部变量,因此,在栈内存中的main方法内分配一块区域存储Car 类型变量 c1,接着执行等号右边,在堆内存中开辟一块内存空间,代表一个Car对象,在对象中开辟区域存放他相应的属性信息,并给他们附默认值,由于对象的方法可能会很多,会极大占据堆内存空间,因此在堆内存中只会存放这些方法的地址(引用地址),通过这个地址去引用方法区的方法,这样堆内存中的对象就表示出来了。对象实际就是一块内存空间

 接着将这块内存空间的地址赋值给左边的c1变量,由c1变量指向这个对象,因此c1中存放的就是对象在堆内存中的地址,然后执行第二行代码,通过c1变量中的地址,找到这个对象,再将这个对象中的name成员变量改成 "奔驰" ,price成员变量改为 39.78,访问c1变量指向对象中的name和price,再执行输出语句,紧接着通过c1调用start()方法,调用方法的原理就是通过c1中存储的地址找到这个对象,然后通过对象中的方法引用的地址找到start()方法,并将start()方法提取到栈内存中执行,由于这个start()方法知道是c1调用的,因此它自然会访问c1中的name信息和price信息,执行start()方法,打印 "奔驰启动了",run()方法同理

 在创建一个新的对象名为c2,在栈内存中的main方法内分配一块区域,在堆内存中开辟一块区域代表一个对象,并在该区域内开辟空间存放其属性信息,再将这个对象的地址赋给c2,通过c2中的地址找到这个对象,将这个对象中的name修改为 "宝马" ,price修改为 "38.98",执行输出语句,再通过c2指向对象中的方法引用找到start()方法的地址,执行这个方法。

 2、两个变量指向同一个对象内存图

 先将.class文件提到方法区,再将main方法加载到栈内存,开始执行第一行代码,将Student类的.class文件提到方法区,在栈内存中的main方法内开辟一块区域存储Student引用类型变量s1,并在堆内存中的main方法内分配一块区域代表一个Student对象,在对象中开辟区域存放其相应的属性信息,将对象在堆内存中的地址赋给s1存储,通过s1中存储的地址,找到其对应的对象,修改他的属性信息,最后通过对象中的方法引用找到study()方法并调用,(重点)再在栈内存中开辟一块区域存放变量s2,将s1中存储的地址赋给s2,使s2也指向堆内存中的对象,再通过s2变量修改其属性值。

 补充:垃圾回收

当堆内存中的对象,没有被任何变量引用(指向)时,就会判定为内存中的"垃圾",在java中有自动垃圾回收器,会定期进行清理。

java虚拟机提供了一个系统级的垃圾回收器线程,它负责自动回收那些无用对象占用的内存,这种内存回收的过程称为垃圾回收。

四、模拟购物车

见案例补充购物车的实现。

五、构造器

1、学习构造器的目的

  • 真正知道对象具体是通过调用什么代码得到的
  • 能够掌握为对象赋值的其他简便写法
  • 为以后学习面向对象编程的其他内容做支撑

2、构造器的基本知识

new出来的东西就相当于一个构造器

 3、构造器的注意事项

  • 任何类定义出来,默认就自带了无参数构造器,写不写都有。Car c = new Car()
  • 一旦定义了有参数构造器,那么无参数构造器就没有了,如果还想用无参数构造器,此时就需要自己手写一个无参数构造器

六、this关键字

1、this关键字是什么

  • this代表当前对象的地址
  • 具体用在在构造器、方法中
  //无参构造器
    public Car() {
        //this输出了对象的地址
        System.out.println("无参数构造器" + this);
    }

这个this会输出当前对象的地址。

2、this关键字的作用

可以用于指定访问当前对象的成员变量、成员方法。

  • 当this出现在有参数构造器
public class Car {
    String name;
    double price;

    //有参数构造器
    //设置参数 n,p在实际开发中会被嫌弃,必须明确传入参数的名称
    public Car(String n , double p) {
        System.out.println("有参数构造器被调用");
        name = n;
        price = p;
    }
}

 因此改进的有参数构造器为:

public class Car {
    String name;
    double price;

    //有参数构造器
    //传入参数见名知义
    public Car(String name , double price) {
        System.out.println("有参数构造器被调用");
        //而如果这样进行传参并不能为当前对象的 name和price进行赋值
        //因为形参接受到传入的数据会就近传入给局部的形参name,不会赋给当前对象的name
        //name = name;
        //price = price;
        
        //所以要通过this获取当前对象的属性进行赋值
        this.name = name;
        this.price = price;
    }
}
  • 当this出现在成员方法中的用法

 区分当前对象的属性和当前的传入参数。

七、封装

1、封装的基本思想

面向对象的三大特性:封装、继承、多态

封装的基本思想:决定属性和行为归属谁的问题。

封装的作用: 告诉我们,如何正确设计对象的属性和方法。

封装的原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为。

封装思想举例:

1、人画圆

定义一个人对象、一个圆对象和一个画圆方法,画圆这个方法就要封装在圆对象中,因为人画圆,这个圆是圆对象自己画的,人只是调用圆对象中的画圆方法。

2、人关门

 定义一个门对象、人对象和一个关门方法,关门方法就要封装在门对象中,门是自己关的,因为人只是调用了门对象中封装的关门方法使门自己关上。

2、如何更好的封装

public class Student {
    //类私有属性 age 对外不能直接访问它
    private int age;

    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        //设置年龄条件 0 - 200 岁
        if (age >= 0 && age <= 200) {
            this.age = age;
        }else {
            System.out.println("您输入的年龄有误");
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Student s = new Student();
        //由于age被私有 所以要通过setter方法对age进行赋值
        // s.age;
        s.setAge(23);
        //通过getter方法 获取age值
        System.out.println(s.getAge());
    }
}

一般会把成员变量使用private隐藏起来,对外就不能直接访问

提供public修饰的getter和setter方法暴露其取值和赋值

八、标准javaBean

javaBean也可以称为实体类(在现实生活中有对应个体),其对象可以用于在程序中封装数据。

一个标准的javaBean须满足如下书写要求:

  • 成员变量使用public修饰。
  • 提供成员变量对应的setXxx() / getXxx()方法。
  • 必须提供一个无参构造器;有参构造器可写可不写。

public class JavaBeanTest {
    //标准javaBean构建步骤
    //1、成员变量私有
    private String name;
    private Double salary;

    //2、提供成员变量对应的setXxx()和getXxx()方法。
    //快捷键 alt + Ins
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    //3、构造无参构造器,默认为无参构造器,所以不需要额外构建。
}

 九、面向对象基础案例

public class MovieTest {
    public static void main(String[] args) {
        //1、设计电影类
        //2、创建三个电影对象,封装电影信息
        //3、定义一个电影类型的数组存储3部电影,简化写法2、3
        Movie[] movies = new Movie[3];
        movies[0] = new Movie("《长津湖》",9.5,"吴京");
        movies[1] = new Movie("《我和我的父辈》",9.0,"吴京");
        movies[2] = new Movie("《扑水少年》",8.0,"王川");

        for (int i = 0; i < movies.length; i++) {
            //将索引结果暂存在m中,再通过m调用方法获取信息
            Movie m = movies[i];
            System.out.println("----------------------------");
            System.out.println("电影名:" + m.getName());
            System.out.println("评分:" + m.getScore());
            System.out.println("主演:" + m.getActor());
            System.out.println("----------------------------");
        }
    }
}
public class Movie {
    //电影类
    private String name;
    private Double score;
    private String actor;

    //alt + Ins 
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }

    public String getActor() {
        return actor;
    }

    public void setActor(String actor) {
        this.actor = actor;
    }

    public Movie() {
    //无参数构造器
    }

    public Movie(String name, Double score, String actor) {
        //有参数构造器
        this.name = name;
        this.score = score;
        this.actor = actor;
    }
}

案例过程解析:

 首先执行main方法,将main方法提到栈内存中,开始执行第一行代码,在main方法中开辟一块区域给变量movies,并在堆内存中开辟一块区域存放Movie类型的数组对象,将数组对象的地址赋给变量movies存储,使变量指向对象在堆内存中的地址,再在堆内存中依次创建三个新的对象,并将地址依次赋给数组对象中存储,使数组对象依次指向三个新对象

十、 成员变量和局部变量的区别

成员变量是类中的成员属性,局部变量是方法中定义的变量,比如main方法。

public class Movie {
    //成员变量
    private String name;
    private Double score;
    private String actor;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值