6、面向对象基础

1. 概述

  1. 找/设计对象来解决问题
  2. 类:具有共同属性的对象,是一个抽象的概念。
    比如:汽车、人、狗、神;
  3. 对象:真实存在的具体实例,是类的实例化。
    比如:推土车是汽车的实例化;姚明是人的实例化;小白(狗的名字)是狗的实例化;二郎神是神的实例化;
  4. 属性:描述具体某个对象的特征,是静态的。
    比如:姚明身高2.6米多;小白的毛发是棕色的;二郎神额头上有只眼睛;
  5. 方法:每个对象有它们自己的行为或者是使用它们的方法,是动态的。可以使用方法来操作一个对象;
    比如:一只狗会跑会叫等,我们把这些行为称之为方法
  6. 类的成员:属性和方法称为这个对象的成员,因为它们是构成一个对象的主要部分,没有了这两样东西,那么对象也没什么存在意义了。

2. 设计对象

2.1 格式

  1. 设计类
    public class 类名{
    1、成员属性(变量,一般是名词)
    2、成员方法(行为,一般是动词)
    3、构造器(后面学)
    4、代码块(后面学)
    5、内部类(后面学)
    }
  2. 实例化对象
    类名 对象名 = new 类名();
  3. 访问对象
    对象名.成员属性 //访问变量
    对象名.方法名() //访问行为
//示例
// 设计类
public class Car {
    // 属性
    String name;
    double price;
    // 方法
    public void start(){  }
    public void run(){  }
}
// 实例化对象
public class CarTest {
    public static void main(String[] args) {
        // 如何实例化对象
        Car carA = new Car();

        // 如何使用对象
        carA.name = "carA";
        carA.price = 10000;
        System.out.println(carA.name + ": "+ carA.price);
        carA.start();
        carA.run();

        System.out.println("----------");
        // 如何实例化对象
        Car carB = new Car();

        // 如何使用对象
        carB.name = "carB";
        carB.price = 50000;
        System.out.println(carB.name + ": " + carB.price);
        carB.start();
        carB.run();
    }
}
  1. 注意事项
    • 类名首字母大写,驼峰格式
    • 一个Java文件中,可以定义多个class类,但只有一个是public修饰。将public修饰的类名作为文件名。(建议一个代码文件定义一个class类)
    • 成员属性的完整定义格式:修饰符 数据类型 变量名 = 初始值,一般无需默认值。
byte short char int long 默认值0
float double 默认值0.0
boolean 默认值false
类 接口 数组 String 默认值null
public class ClassAttention {
//    1 类名首字母大写,驼峰格式
//    2 一个Java文件中,可以定义多个class类,但只有一个是public修饰。将public修饰的类名作为文件名。(建议一个代码文件定义一个class类)
//    3 成员属性的完整定义格式:`修饰符 数据类型 变量名 = 初始值`,一般无需默认值。
    public static void main(String[] args) {
        Car carDefault = new Car();
        System.out.println(carDefault.name);  //null
        System.out.println(carDefault.price); //0.0
    }

3. 内存机制

3.1 内存

方法区:字节码文件加载时进入
栈内存:方法运行时进入;变量
堆内存:new的对象会在堆内存中开辟空间并产生地址。

3.2 示例

  1. 对象存储在堆内存中
  2. Car carA = new Car();的变量名carA存储的是对象在堆内存中的地址。
  3. 成员属性(变量)的数据存放在对象中,在堆内存中。
  4. 两个对象的内存图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    5:两个变量指向一个对象的内存图
    在这里插入图片描述
    在这里插入图片描述

3.3 垃圾回收

  1. 如上例,如果s1 = nulls2 = null,则变量s1s2存储的堆内存的地址为null,不能再指向堆内存对象。
  2. 没有变量引用堆内存中的对象,即为垃圾对象。
  3. Java存在自动垃圾回收期,会定期清理

4. 构造器

4.1 构造器的作用

  • 定义在类中的, 可以用于初始化一个类的对象,井返回对象的地址。eg:Car C = new Car()

4.2 构造器格式

  • 方法名与类名相同,大小写也要一致
  • 没有返回值类型,连void都没有
  • 没有具体的返回值(不能由retrun带回结果数据)
  1. 定义格式
修饰符 类名(形参列表){
…
}
  1. 调用格式
    类 变量名称 = new 构造器;

  2. 示例

  • 定义
public class Car {
    String name;
    double price;

    /*
    无参数构造器
     */
    public Car(){
        System.out.println("无参数构造器");
    }
    
    /*
    有参数构造器
     */
    public Car(String n, double p){
        name = n;
        price = p;
        System.out.println("有参数构造器");
    }
}
  • 调用
    public static void main(String[] args) {
        //无参数构造器 默认存在,初始化对象时,成员变量的数据均采用默认值。
        Car c = new Car();
        System.out.println(c.name);
        System.out.println(c.price);
        
        c.name = "奔驰";
        c.price = 39.8;
        System.out.println(c.name);
        System.out.println(c.price);

        //有参数构造器:初始化对象时,同时可以接受参数为对象进行赋值。
        Car c1 = new Car("奔驰",39.8);
        System.out.println(c1.name);
        System.out.println(c1.price);
    }
  1. 分类和作用
  • 无参数构造器:默认存在,初始化对象时,成员变量的数据均采用默认值。
  • 有参数构造器:初始化对象时,同时可以接受参数为对象进行赋值。

4.5. 注意事项

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

5. this关键字

5.1 简介

this关键字:可以出现在构造器方法中;代表当前对象的地址。
作用:可以用于指定访问当前对象的成员变量,成员方法。

5.2 示例

  1. 定义
/*
this 关键字的作用
 */
public class Car {
    public Car(){
        System.out.println("无参数构造器的this:" + this);
    }

    public void run(){
        System.out.println("方法的this:" + this);
    }
}
  1. 调用
public class Test {
    public static void main(String[] args) {
        Car c = new Car();
        c.run();
        System.out.println(c);
    }
}
//无参数构造器this:stu.javase.day6.thisdemo.Car@6cd8737
//方法的this:stu.javase.day6.thisdemo.Car@6cd8737
//stu.javase.day6.thisdemo.Car@6cd8737
  1. 作用
public class Car {
    String name;
    double price;
    //成员变量
    public Car(String name, double price) {
        this.name = name;
        this.price = price;
        System.out.println("有参数构造器的this:" + this);
    }
    //成员方法
    public void goWith(String name){
        System.out.println(this.name + "正在和" + name + "比赛!");
    }
}

public class Test {
    public static void main(String[] args) {
        //成员变量
        Car c1 = new Car("奔驰",39.8);
        System.out.println(c1.name);
        System.out.println(c1.price);
        //成员方法
        c1.goWith("宝马");
    }
}

6. 封装

6.1 定义

  • 封装:如何正确设计对象的属性和方法
  • 原则:对象代表什么,就要封装对应的数据,并提供数据对应的行为。
  • 例如:人画圆:人(变量,方法)& 圆(变量:半径,方法:画圆);
    人关门:人(变量,方法)& 门(变量,方法:关门);
  • 优点:目前已经有很多都封装成相应的对象,使用时直接调用对象方法即可。比如String代表字符串对象,拥有很多操作字符串的方法;Socket代表网络连接,可以连接别人,收发消息。

6.2 如何封装

  1. 一般建议对成员变量使用private关键字修饰,private修饰的成员只能在当前类中访问。
  2. 为每个成员变量提供配套 public修饰的的getter、setter方法暴露其取值和赋值。
  3. 示例
// 学生类
/*
封装
 */
public class Student {
    //1. 对成员变量使用private关键字修饰,private修饰的成员只能在当前类中访问。
    private int age;

    // 构造函数
    public Student(){

    }
    //构造函数
    public Student(int age){
        this.age = age;
    }

    // 2. 为每个成员变量提供配套 public修饰的的getter、setter方法暴露其取值和赋值。
    public void setAge(int age){
        if (age > 0 && age < 200){
            this.age = age;
        }
        else{
            System.out.println("请检查年龄是否有误!");
        }
    }

    public int getAge(){
        return age;
    }
}
// 测试类
public class Test {
    public static void main(String[] args) {
        Student s = new Student(10);
        System.out.println(s.getAge());
        s.setAge(18);
        System.out.println(s.getAge());
    }
}

7. 标准JavaBean

7.1 JavaBean

  1. 可以成为实体类,对象可以用于在程序中封装数据。
  2. 标准JavaBean书写要求:
  • 成员变量使用private修饰;
  • 提供成员变量对应的setXxx()/getXxx()方法;
  • 必须提供一个无参构造器;有参数构造器是可写可不写的;

7.2 示例

用户类
public class User {
    // 1. 成员变量使用private修饰;
    private String name;
    private double height;
    private double salary;

    /*
    3.必须提供一个无参构造器;有参数构造器是可写可不写的;
     */

    public User() {
    }

    public User(String name, double height, double salary) {
        this.name = name;
        this.height = height;
        this.salary = salary;
    }

    /*
        2. 提供成员变量对应的setXxx()/getXxx()方法;
        */
    public String getName() {
        return name;
    }

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

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getSalary() {
        return salary;
    }

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


}
测试类
public class Test {
    public static void main(String[] args) {
        // 无参数构造器
        User u1 = new User();
        u1.setName("lll");
        u1.setHeight(1.60);
        u1.setSalary(10000.0);
        System.out.println("姓名:" + u1.getName() + ";身高(m):" + u1.getHeight() + ";工资(元):" + u1.getSalary());
        // 姓名:lll;身高(m):1.6;工资(元):10000.0

        //有参数构造器
        User u2 = new User("zzz", 1.65, 15000.0);
        System.out.println("姓名:" + u2.getName() + ";身高(m):" + u2.getHeight() + ";工资(元):" + u2.getSalary());
        // 姓名:zzz;身高(m):1.65;工资(元):15000.0
    }
}

8. 补充:成员变量/局部变量

  • 对比

9. 综合案例

9.1 购物车模块

  1. 需求
    模拟购物车模块的功能,需要实现添加商品到购物车中去,同时需要提供修改商品的购买数量,结算商品价格功能。
  2. 分析
  • 购物车中的每个商品都是一个对象,需要定义一个商品类。
  • 购物车本身也是一个对象:可以使用数组对象代表它。
  • 完成界面架构,让用户选择操作的功能。
  1. 实现
  • 商品类
package stu.javase.day6.shopcart;

public class Goods {
    int id; //编号
    String name;  //名称
    double price; //价格
    int buyNum; //购买数量
}
  • 购物车类
package stu.javase.day6.shopcart;

import java.util.Scanner;

public class ShopCartTest {
    public static void main(String[] args) {
        // 1.定义商品类,用于后期创建商品对象
        // 2. 定义购物车对象,使用数组表示。(数组固定长度,有不足。后期会使用集合表示)
        Goods[] shopCar = new Goods[100]; //默认值null
        queryGoods(shopCar);
        boolean flag = true;
        while (flag) {
            // 3. 搭建架构
            System.out.println("*****请选择如下命令进行操作*****");
            System.out.println("--添加商品到购物车:add--");
            System.out.println("--查询购物车的商品:query--");
            System.out.println("--修改商品购买数量:update--");
            System.out.println("--结算商品购买金额:pay--");
            System.out.println("--退出:exit--");

            Scanner sc = new Scanner(System.in);
            System.out.println("请你输入命令:");
            String command = sc.next();
            switch (command){
                case "add":
                    addGoods(shopCar, sc);
                    break;
                case "query":
                    queryGoods(shopCar);
                    break;
                case "update":
                    updateGoods(shopCar, sc);
                    break;
                case "pay":
                    payGoods(shopCar);
                    break;
                case "exit":
                    flag = false;
                    System.out.println("*****购物结束,欢迎下次再来*****");
                    break;
                default:
                    System.out.println("没有该功能,请重新输入!");
                    break;
            }
        }
    }

    /*
    添加商品功能
     */
    public static void addGoods(Goods[] shopCar, Scanner sc){
        //1. 录入用户输入的商品信息
        System.out.print("请输入商品编号:");
        int id;
        while (true){
            int id_input = sc.nextInt();  //编号
            boolean flag = true; //编号不重复
            for (int i = 0; i < shopCar.length; i++) {
                if (shopCar[i] != null) {
                    if (shopCar[i].id == id_input){
                        flag = false;
                        break;
                    }
                }else break;
            }
            if (flag){
                id = id_input;
                break;
            }
        }
        System.out.print("请输入商品名称:");
        String name = sc.next();  //名称
        System.out.print("请输入商品数量:");
        int buyNum = sc.nextInt(); //购买数量
        System.out.print("请输入商品价格:");
        double price = sc.nextDouble(); //价格

        // 2. 将商品信息封装为一个商品对象
        Goods g = new Goods();
        g.id = id;
        g.name = name;
        g.buyNum = buyNum;
        g.price = price;

        // 3. 添加进购物车
        for (int i = 0; i < shopCar.length; i++) {
            //shopCar = [g1, g2, g3, …… null, null……]
            if (shopCar[i] == null){
                shopCar[i] = g;
                break;
            }
        }
        System.out.println("您的商品"+ g.name +"已添加!");
    }

    /*
    查询购物车商品
     */
    public static void queryGoods(Goods[] shopCar){
        System.out.println("======购物车清单======");
        System.out.println("编号\t\t名称\t\t数量\t\t价格");
        for (int i = 0; i < shopCar.length; i++) {
            //shopCar = [g1, g2, g3, …… null, null^]
            if (shopCar[i] != null){
                System.out.println(shopCar[i].id + "\t\t" + shopCar[i].name +
                        "\t\t" + shopCar[i].buyNum + "\t\t" + shopCar[i].price);
            }else{
                // 遍历结束
                break;
            }
        }
    }
    
    /*
    更新购物车商品数量
     */
    public static void updateGoods(Goods[] shopCar, Scanner sc){
        // 商品信息
        queryGoods(shopCar);

        while (true) {
            System.out.print("输入增加商品数量的编号:");
            int id = sc.nextInt();
            Goods g = findIdGoods(shopCar, id);
            // 返回商品
            if (g != null) {
                System.out.print("请重新输入商品数量:");
                int buyNum = sc.nextInt();
                g.buyNum = buyNum;
                break;
            }
            //没有商品
            else{
                System.out.print("请重新输入商品编号:");
            }
        }
    }

    /*
    查询id对应商品
     */
    public static Goods findIdGoods(Goods[] shopCar, int id){
        for (int i = 0; i < shopCar.length; i++) {
            if (shopCar[i] != null) {
                if(id == shopCar[i].id){
                    System.out.println("编号:" + shopCar[i].id + "\t名称" + shopCar[i].name +
                            "\t数量" + shopCar[i].buyNum + "\t价格" + shopCar[i].price);
                    return shopCar[i];
                }
            }else{
                System.out.println("未查询到该编号对应商品!");
                break;
            }
        }
        return null;
    }

    /*
    为商品付款
     */
    public static void payGoods(Goods[] shopCar){
        queryGoods(shopCar);

        int pay = 0;
        for (int i = 0; i < shopCar.length; i++) {
            if (shopCar[i] != null){
                pay += shopCar[i].price * shopCar[i].buyNum;
            }
            else break;
        }
        System.out.println("付款:" + pay);

    }
}

9.2 电影信息展示

  1. 需求
    使用java,模仿电影信息展示
    在这里插入图片描述

  2. 分析

  • 一部电影是一个Java对象,需要先设计电影类,再创建电影对象。
  • 三部电影对象可以采用数组存储起来。
  • 依次遍历数组中的每个电影对象,取出其信息进行展示。
电影类
public class Movie {
    // 1. 成员变量
    private String name;
    private String country;
    private double score;
    private String director;
    private String actor;

    // 3. constructor

    public Movie() {
    }

    public Movie(String name, String country, double score, String director, String actor) {
        this.name = name;
        this.country = country;
        this.score = score;
        this.director = director;
        this.actor = actor;
    }
    // 2. get set

    public String getName() {
        return name;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public double getScore() {
        return score;
    }

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

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getActor() {
        return actor;
    }

    public void setActor(String actor) {
        this.actor = actor;
    }
}
测试类
public class Test {

    public static void main(String[] args) {
        // 1. 设计电影类
        // 2. 实例化3个对象

        // 3. 定义一个电影类型的数组,实例化每个数组对象
        Movie[] movies = new Movie[3];
        movies[0] = new Movie("《长津湖》","china",7.7,"徐克","吴京");
        movies[1] = new Movie("《我和我的父辈》","china",7.8,"吴京","吴京");
        movies[2] = new Movie("《五个扑水的少年》","china",5.9,"宋灏霖","王川");
        // 4. 遍历数字输出电影信息
        for (int i = 0; i < movies.length; i++) {
            System.out.println("----------------------------------------------------");
            System.out.println("电影名:" + movies[i].getName() + "\t国家:" +movies[i].getCountry() + "\t评分:" + movies[i].getScore() + "\t导演:" + movies[i].getDirector() + "\t主演:" + movies[i].getActor());
        }
    }
}
/*
----------------------------------------------------
电影名:《长津湖》	国家:china	评分:7.7	导演:徐克	主演:吴京
----------------------------------------------------
电影名:《我和我的父辈》	国家:china	评分:7.8	导演:吴京	主演:吴京
----------------------------------------------------
电影名:《五个扑水的少年》	国家:china	评分:5.9	导演:宋灏霖	主演:王川
*/

猜你喜欢

转载自blog.csdn.net/deer2019530/article/details/127943162