从零开始学Java Day05 面向对象编程

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

01面向对象编程入门

在程序中的数据存储,我们可以利用变量、数组、二维数组以及对象进行存储。

对象也是一种存储数据的存储方式。

例如要存彭于晏的数据:

1.先设计对象的模板,也就是对象的设计图:类。

public class Star{
    String name;
    int age;
    double height;
    double weight;
}

 

02面向对象-学生案例

//student.java文件定义student类

public class student {
    String name;
    double chinese;
    double math;
}
//evenStudent.java主函数中进行赋值与调用

public class evenStudent {
    public static void main(String[] args) {
        student s1 = new student();
        student s2 = new student();
        s1.name = "播妞";
        s1.chinese = 100;
        s1.math = 100;
        System.out.println("total = " + (s1.chinese + s1.math) + "; even = " + ((s1.chinese + s1.math) / 2));

        s2.name = "播仔";
        s2.chinese = 59;
        s2.math = 100;
        System.out.println("total = " + (s2.chinese + s2.math) + "; even = " + ((s2.chinese + s2.math) / 2));
    }

}

***重要概念:封装***

封装 即为把数据和对数据的处理放到同一个类中去。

在上面的例子中我们可以看到 在定义了student类后,我们仍需要在主程序中写很多操作代码,封装就可以很好的解决这个问题,通过将逻辑代码写在studen.java文件中,让主程序更加的简洁。代码如下:

//student.java

public class student {
    String name;
    double chinese;
    double math;

    //定义方法打印全部分数和
    public void allScore(){
        System.out.println("total = " + (chinese + math));
    }

    //定义方法打印平均分数
    public void evenScore(){
        System.out.println("; even = " + ((chinese + math) / 2));
    }
}
//evenStudent.java

public class evenStudent {
    public static void main(String[] args) {
        student s1 = new student();
        student s2 = new student();
        s1.name = "播妞";
        s1.chinese = 100;
        s1.math = 100;
        s1.allScore();//调用
        s1.evenScore();//调用

        s2.name = "播仔";
        s2.chinese = 59;
        s2.math = 100;
        s2.allScore();//调用
        s2.evenScore();//调用
    }

}

03面向对象编程:对象究竟是什么

对象本质是一种特殊的数据结构(可以理解成一张表)。

每次进行一次new操作 可以视为创建了一张表 这样比较好理解一些。

万物皆对象,谁的数据谁存储。

04类的基本语法

1.构造器

构造器是一种特殊的方法,它的特点是只有修饰符,没有返回值,名称必须是类名,就是构造器。

public class Student {

//构造器

        public Student() { //只有修饰符public 没有返回类型值 这是一个无参构造器

                ...

        }

}

构造器的特点:创建对象时,对象会自动去调用构造器

//Student.java类文件

public class Student {
    String name;
    int age;
    char sex;
    
    //创建类时 类自动携带一个无参构造器 此时如果创建有参构造器 则类自带的无参
    //构造器失效 想要用无参构造器就需要自己创建一个

    //无参构造器
    public Student(){

    }


    //有参构造器 有接收参数
    public Student(String n, int a, char s){
        name = n;
        age = a;
        sex = s;
    }
}
package com.xinsheng.constructor;

public class Test {
    public static void main(String[] args) {
        
        //调用有参构造器 从此赋值只需要一行命令
        //不用是s1.name一个一个点了

        Student s1 = new Student("小明",18,'男');
        System.out.println(s1.name + s1.age + s1.sex);
    }
}

***创建对象的逻辑***

在如下语句中:

Student s1 = new Student();

1. new Student() 实际上是创建对象的部分。它在堆内存中分配空间,并初始化一个新的Student类的实例。这个新创建的、在内存中的实例,就是对象本身。

2. s1 是一个引用变量(或者叫对象引用)。它存储着指向刚才创建的那个Student对象在堆内存中位置的地址。因此如果直接打印s1,出来的是一个地址数字。

总结:

1.对象(object)是new Student()创建出来的、住在内存堆里的那个实体。

2. s1是指向这个对象的引用,就像一个标签或遥控器,让你能够访问那个对象。

所以,在日常交流中人们经常说“s1就是那个对象”,但从技术上讲,s1是对象引用,而不是对象本身

构造器总结:

2.this关键字

this就是一个变量,可以用在方法中,用来拿到当前对象。例如如下代码所示:

//Student.java类文件

public class Student {
    String name;

    public void printThis(){
        System.out.println(this); //使用this拿到当前对象 这个对象是Test.java中创建的
    }

}

当你在 Student.java 类的 printThis() 方法中执行 System.out.println(this); 时:

  1. this 关键字 确实是拿到了当前正在执行这个方法的那个 Student 对象

  2. 这个对象 正是你在另一个文件(你提到的是 Test.java)中,通过像 Student s = new Student(); 这样的语句创建出来的 堆内存中的实体

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "小明";
        s1.printThis();
        System.out.println(s1);
    }
}

当执行到s1.printThis(); 时,Java 虚拟机(JVM)知道:现在要用 s1 指向的那个对象 来执行 printThis() 方法。在方法内部,this 变量就自动指向了 s1 指向的那个对象

打印结果如下,打印出s1对象在堆内存中的地址,结果一直,说明确定this此时指向的是s1对象。

this有啥应用场景?

this主要用来解决:变量名称冲突问题的。举例如下代码:

代码中变量名的命名一般要做到见名知意,因此例如如下情况:

如果在Student.java类文件中定义一个方法,用来打印对象的爱好

    public void printHobby(String name){
        System.out.println(name + "like" + name);
    }

因为要见名知意,所以对象名应为name,同时爱好名应该也为name,此时如果在Test.java文件中调用这个方法:

        Student s2 = new Student();
        s2.name = "小刘";
        s2.printHobby("打游戏");

原本预期结果应为“小刘like打游戏” 运行则出现以下情况

这是因为在printHobby(String name)方法中 依据就近原则 Java会将两个name都认为是方法本身的变量name,而非对象的变量name,因此出现这种情况。

此时如果在方法体中使用this变量,此时this.name变量表明指向当前调用printHobby(String name)方法的这个对象的name变量,即为小刘,则此时打印结果为“小刘like打游戏”

    public void printHobby(String name){
        System.out.println(this.name + "like" + name);
    }

3.封装

封装是面向对象的三大特征之一,面向对象的三大特征为:封装、继承、多态。

封装的设计要求:合理隐藏、合理暴露

类就是一种封装

例如 我们上文提到的学生类Student.java,其中的String name等就是暴露出来的变量属性,我们可以在Test.java轻松的对其进行非法赋值,比如将int age变量赋值为-18或者200岁,这是明显不可能的事情,但如果没有封装,那外界调用学生类时就可以对其进行非法修改。

如果此时我们对其进行封装,即为对student类中的变量,用private对其进行修饰,并写出每个变量的setter和getter方法,则如下图所示,我们可以在setter方法中加入验证逻辑,确保每一个写入的年龄数值age都能合理合法,并在Test.java中调用setAge()方法对变量进行赋值。

这时,如果输入年龄为300,则会报错invaild age number。

//Student.java

public class Student {
    private String name;
    private int age;
    private char gender;

    public void setAge(int age){
        if (age > 0 && age < 200){
            this.age = age;
        }else {
            System.out.println("invalid age number");
        }
    }

    public int getAge() {
        return age;
    }
}
//Test.java

public class Test {
    public static void main(String[] args) {
        Student s1 =new Student();
        s1.setAge(30);
        System.out.println(s1.getAge());
    }
}

封装,即将类的成员变量都设置成private,并为其提供成套的setter和getter方法,已经成为了Java的设计风格,必须遵守。

4.JavaBean(也叫实体类)

JavaBean(或实体类),是一种特殊类,类中要满足如下需求:

- 要求1:类中的成员变量全部私有,并提供public修饰的getter/setter方法

- 要求2:类中需要提供一个无参数构造器,有参数构造器可选

以下即为实例的JavaBean Student类:

//JavaBean(也叫实体类)实例:

public class Student {

    //1.私有化成员变量
    private String name;
    private int age;
    private char gender;

    //2.提供一个无参构造器
    //如果不提供有参构造器 可以不手动提供无参构造器 因为类会自带一个无参构造器 这个构造器即可满足JavaBean要求
    public Student(){

    }

    //3.提供有参构造器
    public Student(String name, int age,char gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    //4.为每个成员变量提供公开的getter和setter方法。
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }
}

实体类有啥应用场景?

实体类对象只负责数据存取,而对数据的业务处理交给其他类的对象来完成,以实现数据和数据业务处理相分离。

例如Student.java类只负责数据存取,而对数据的业务处理交给另外创建的StudentOperator.java类进行处理,实现数据和数据业务的相分离。

例如以下代码,Test.java为程序主入口,Student.java类只负责数据的存取,同时新建一个StudentOperator.java类用以操作数据:

//Test.java

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setAge(18);
        s1.setName("小明");
        s1.setGender('男');
        s1.setChinese(80);

        StudentOperator so1 = new StudentOperator();

        //StudentOperator so1 = new StudentOperator(s1);

        so1.setS(s1);
        so1.printSum();

    }
}
//Student.java

//JavaBean(也叫实体类)实例:

public class Student {

    //1.私有化成员变量
    private String name;
    private int age;
    private char gender;
    private double chinese;

    //2.提供一个无参构造器
    //如果不提供有参构造器 可以不手动提供无参构造器 因为类会自带一个无参构造器 这个构造器即可满足JavaBean要求
    public Student(){

    }

    //3.提供有参构造器
    public Student(String name, int age,char gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    //4.为每个成员变量提供公开的getter和setter方法。
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public double getChinese() {
        return chinese;
    }

    public void setChinese(double chinese) {
        this.chinese = chinese;
    }
}
//StudentOperator.java
public class StudentOperator {
    private Student s;

    //public StudentOperator(Student s){
    //    this.s = s;
    //}

    public void setS(Student s) {
        this.s = s;
    }

    public void printSum(){
        System.out.println(s.getName());
    }
}

其中提供了两种将Student对象s1提供给StudentOperator.java类的方法,见红框与绿框(代码段中被注释掉的代码)

 5.static-关键字

static关键字叫静态,可以修饰成员变量、成员方法。

(1)static修饰成员变量

成员变量按照有无static修饰,分为两种:

- 静态变量(类变量):

有static修饰,属于类的变量,在计算机内存中只有一份,被类里的所有对象共享

- 实例变量(对象的变量):

没有static修饰,属于每一个对象。

例如如下代码段,name为有static修饰的静态变量(类变量),所以无论有多少对象被创建,name都只有一份(内存中只有一份)。而age变量为没有static修饰的实例变量(对象的变量),每创建一个对象,每个对象的内存中就会为每个对象创建一个age区域,用于存储每个对象的age数据。

//Student.java

public class Student {
    //1.静态变量(类变量)
    //有static修饰,属于类的变量,在计算机内存中只有一份,被类里的所有对象共享
    static String name;

    //2.实例变量(对象的变量)
    //没有static修饰,属于每一个对象的变量
    int age;


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void printName(){
        System.out.println(Student.name);
    }

    public void printAge(){
        System.out.println(this.age);
    }
}
//Test.java

public class Test {
    public static void main(String[] args) {
        Student.name = "小明";
        System.out.println(Student.name);


        Student s1 = new Student();
        s1.name = "小红"; //不推荐这样定义静态变量,仅作演示,请使用类名.静态变量名称进行访问和修改
        //s1.printName();

        Student s2 = new Student();
        s2.name = "小黄";
        s2.printName(); //结果为小黄
        s1.printName(); //结果为小黄
        //因为name为静态变量 类中只有一份 内存中也只有一份储存空间 所以修改的是一个东西

        s1.age = 18;
        s2.age = 20;
        s1.printAge();
        s2.printAge();
        //age为对象的变量 所以每个对象内存中都有一个age内存 所以打印出来不一样
    }
}

静态变量的应用场景:

如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成静态变量来记住。

例如,系统启动后,要求用户类可以记住自己创建了多少个用户对象了。那这时我们就可以创建一个静态变量number,每创建一个对象就number++,从而进行记录。

(2)static修饰方法

成员方法的分类

1.静态方法:有static修饰的成员方法,属于类。

2.实例方法:没有static修饰的成员方法,属于每个对象。

示例代码段如下所示:

//Student.java
public class Student {
    private double score;
    //1.静态方法:有static修饰 属于类本身
    public static void printHelloWorld(){
        System.out.println("HelloWorld");
        System.out.println("HelloWorld");
        System.out.println("HelloWorld");
    }

    public double getScore() {
        return score;
    }

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

    //2.实例方法 没有static修饰 属于对象持有
    public void printPass(){
        System.out.println(score >= 60 ? "pass" : "fail");
    }
}
//Test.java
public class Test {
    public static void main(String[] args) {
        Student.printHelloWorld(); //类名.静态方法名

        Student s1 = new Student();
        s1.setScore(59.5);
        s1.printPass(); //对象名.实例方法
    }
}

小结:

(3)静态方法的应用

静态方法的常见应用场景:做工具类。

工具类是什么?

工具类中的方法都是一些静态方法,每个方法用来完成一个功能,以便于供给开发人员使用,进入企业后,企业内部可能有一个上千个方法的utili.java类供给程序员调用。

***多学一招***

因为工具类没有创建对象的需求,那么如果放开创建对象功能,虽然无意义,但程序仍然会在内存中给他分配一个区域,进而占用内存,为避免这种情况,建议将工具类私有化。

(4)static的注意事项

理解完成以下几句话 说明对static的理解程度已经很不错了。

05综合实战-电影信息展示

简易版电影信息展示系统:

Movies.java类文件:

//Movies类只用来存储对象和数据
public class Movies {
    private int id;
    private String name;
    private double price;
    private String actor;

    public Movies(){

    }

    public Movies(int id, String name, double price, String actor){
        this.id = id;
        this.name = name;
        this.price = price;
        this.actor = actor;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getActor() {
        return actor;
    }

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

MoviesOperator.java

import java.util.Scanner;

//MoviesOperator类用以处理逻辑
public class MoviesOperator {
    private Movies[] movies;

    public MoviesOperator(Movies[] movies){
        this.movies = movies;
    }
    public void printAll(){
        for (int i = 0; i < movies.length; i++) {
            System.out.println(movies[i].getId() + "\t" + movies[i].getName() + "\t" + movies[i].getPrice() + "\t" + movies[i].getActor());
        }
    }

    public void printById(){
        Scanner sc = new Scanner(System.in);
        int id = sc.nextInt();
        for (int i = 0; i < movies.length; i++) {
            //********关键代码**********
            Movies m = movies[i];
            //********关键代码**********
            if (m.getId() == id){
                System.out.println(movies[id-1].getId() + "\t" + movies[id-1].getName() + "\t" + movies[id-1].getPrice() + "\t" + movies[id-1].getActor());
                return; //*********结果输出完毕 结束循环********
            }
        }
        System.out.println("wrong movie Id");
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        Movies[] arr = new Movies[6]; //这里的6是数组长度 因此只有6个对象
        arr[0] = new Movies(1,"喜羊羊与灰太狼", 9.5, "喜羊羊、灰太狼");
        arr[1] = new Movies(2,"唐顿庄园", 8.5, "唐顿");
        arr[2] = new Movies(3,"夏洛特烦恼", 9.5, "沈腾");
        arr[3] = new Movies(4,"变形金刚", 9.5, "擎天柱、威震天");
        arr[4] = new Movies(5,"熊出没", 9.5, "熊大、熊二、光头强");
        arr[5] = new Movies(6,"食贫道", 9.5, "饼叔");

        MoviesOperator moviesOperator = new MoviesOperator(arr);


        moviesOperator.printAll();

        moviesOperator.printById();
    }
}

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值