8、面向对象:类、封装、构造方法

一、类

1、定义

类:对现实世界中事物的抽象。Student

对象:现实世界中具体的个体。张三、李四 这些具体的学生

面向对象的特征:抽象、封装、继承、多态

OOP: Object Oriented Programming(面向对象编程)

类和对象的总结:

1、现实世界都是由很多对象组成的,基于对象的共同特征抽象出类。

2、对象:真实存在的对象

3、类中包含:

复制代码
 1)所有对象所共有的特征--属性(静)
 
 2)所有对象所共有的行为--方法(动)

4、类是对象的模板,对象是类的具体实例。

5、一个类可以创建多个对象, 同一个类的不同对象,结构相同,数据不同。

java 复制代码
//实体类:和数据库表一一对应
public class Student {
    //属性、字段
    int id;
    String name;
    int age;
    String gender;
}

@Test
public void test1() {
    Scanner scanner = new Scanner(System.in);
    int num = 3;
    //student1:变量、实例、对象
    Student student1 = new Student();
    //对象.属性
    student1.id = 1;
    student1.name = "张三";
    student1.age = 23;
    student1.gender = "男";
    System.out.println(student1.name);

    Student student2 = new Student();
    student2.id = 2;
    student2.name = "李四";
    student2.age = 24;
    student2.gender = "女";
    System.out.println(student2.name);
    
    //构造数组来存储,方便管理:
    Student[] array = new Student[2];
    array[0] = student1;
    array[1] = student2;
    }
}

对应的内存模型:

new出来的放在堆里面,类的模板放在方法区

2、易混淆知识点

bash 复制代码
int num = 3;
int[] nums = new int[3];
double[] nums = new double[3];
Student student = new Student();  // student :变量、实例、对象
Student[] students = new Student[3];
Teacher teacher = new Teacher();
Teacher[] teachers = new Teacher[3];

int、int[]、Student、Student[]这些都是数据类型,数据类型的后面是这种类型的一个变量。
格式: 数据类型  变量
var v;
let v;

1.Java是编译型、强类型语言(效率高)
2.JavaScript是解释型、弱类型语言

3、数据类型的默认值

bash 复制代码
1.int类型默认值是:0
2.double类型默认值是:0.0
3.boolean类型默认值是:false
4.String类型默认值是:null
5.int[]类型默认值是:null
6.Student[]类型默认值是:null
7.boolean[]类型默认值是:null

所有引用数据类型的默认值都是null
bash 复制代码
1.int[] array = new int[3]; 里面的存放默认值是0
2.boolean[] array = new boolean[3]; 里面的存放默认值是false
3.Student[] array = new Student[3];里面的存放默认值是null(Student是一个类,放的就是类的默认值:null)

总结:构造一个数组的时候如果没有赋值,那么数组里面放的是这个类型的默认值
java 复制代码
@Test
public void test2() {
    Student student = new Student();
    System.out.println(student.id);//0
    System.out.println(student.name);//null
}

@Test
public void test3() {
    int[] array1 = new int[3];
    boolean[] array2 = new boolean[3];
    Student[] students = new Student[3];
    for (int i = 0; i < students.length; i++) {
        System.out.println(students[i]);
    }
    //增强的for循环
    for (Student student : students) {
        System.out.println(student);
    }
}

4、空指针异常

bash 复制代码
ArrayIndexOutOfBoudsException 数组下标越界异常

NullPointerException空指针异常(引用数据类型)
java 复制代码
@Test
public void test4() {
    //NullPointerException空指针异常(引用数据类型)
    Student student = null;
    System.out.println(student);//null
    // null.方法   null.属性 --->空指针异常
    System.out.println(student.id);//空指针异常
}

二、toString()

1、行为--->方法:

基于上面学生的例子演示方法的调用:

上述例子是写死的,我们实际应当实现灵活调用:即以前说的,先写死,再改成逗逗加加:

那么,如果属性很多,进行拼接会很麻烦,解决办法:添加toString()方法生成这些,如下。

2、添加toString():

java 复制代码
//方法:自己手敲的
public String getInfo() {
    //String str = "[Student: id="+id+",name="+name+",age="+age+",gender="+gender+"]";
    //return str;
    return "[Student: id="+id+",name="+name+",age="+age+",gender="+gender+"]";
}

//toString()生成的:
@Override
public String toString() {
    return "Student{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", age=" + age +
            ", gender='" + gender + '\'' +
            '}';
}
java 复制代码
@Test
public void test44() {
    Student student = new Student();
    student.id = 1;
    student.name = "王五";
    student.age = 223;
    student.gender = "男";
    String info = student.getInfo();
    System.out.println(info);
    System.out.println(student.getInfo());
    System.out.println("-----------");
    System.out.println(student.toString());
    //当打印对象的时候,默认就调用了:对象.toString()
    System.out.println(student);
}

完整代码:

java 复制代码
package com.situ.day10;

public class Student {
    int id;
    String name;
    int age;
    String gender;

    //自己写的方法
    public String getInfo(){
        String str = "[student:id = "+id+",name = "+name+",age = "+age+"]";
        return str;
    }

    //toString()生成的:
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}
java 复制代码
package com.situ.day10;

import org.junit.Test;

public class OPPDemo {
    @Test
    public void test1(){
        Student student1 = new Student();
        student1.id = 1;
        student1.name = "zhangsan";
        student1.age = 23;
        student1.gender = "男";
        //调用toString()并输出结果
        System.out.println(student1.toString());

        Student student2 = new Student();
        student2.id = 2;
        student2.name = "lisi";
        student2.age = 24;
        student2.gender = "女";
        //System.out.println(student2.toString());等价于下面这行代码:
        System.out.println(student2);//即打印对象的时候,默认调用toString()。

    }
}

补充:

三、封装 private/get/set

面向对象的封装是一种编程概念和原则,它通过将数据和操作封装在一个对象中,以实现信息隐藏和安全性。

封装使得对象的内部细节对外部不可见,只暴露必要的接口供其他对象进行交互。

java 复制代码
//属性私有private,只有类的内部可以访问
private age;

// 属性私有,通过get、set方法访问:
public void setAge(int age) {
    if (age >= 1 && age <= 125) {
        // The assignment to variable age has no effect
        // this.age 代表的就是属性age
        this.age = age;
    }
}

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

完整代码:

java 复制代码
package com.situ.day10;

public class Student2 {
    //封装:变量私有化处理:
    // 添加private,只能在当前类中使用,通过get、set方法访问:
    private int id;
    private String name;
    private int age;
    private String gender;


    //右键Generate:添加Getter、Setter方法
    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 1 && age <= 125) {//根据实际情况添加限制
            this.age = age;
        }
    }
    public String getGender() {
        return gender;
    }

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

    //添加toString方法:

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}
java 复制代码
package com.situ.day10;

import org.junit.Test;

public class OOPDemo2 {
    @Test
    public void test1(){
        Student2 student4 =new Student2();
        student4.setAge(15);
        int age = student4.getAge();
        System.out.println(age);
    }

    @Test
    public void test2(){
        Student2 student5 = new Student2();
        student5.setId(5);
        student5.setName("wangwu");
        student5.setAge(15);
        student5.setGender("女");
        System.out.println(student5);
    }

}

四、构造方法

bash 复制代码
构造方法是new对象时候调用方法,特点:

1.方法名和类名一样  

2.没有返回值

3.在new对象的时候会调用构造方法
java 复制代码
//无参构造方法
//如果不写,Java默认提供这样一个无参构造方法.
//如果你写了任何一个构造方法,Java就不会再提供这个无参构造方法
public Student() {
   System.out.println("Student.Student()");
}

//有参构造方法
public Student(int id, String name, int age, String gender) {
   this.id = id;//把1这个值赋值给当前new出来的student对象的id属性
   this.name = name;
   this.age = age;
   this.gender = gender;
}

Student student = new Student(2, "李四", 24, "男");
System.out.println(student);
bash 复制代码
1、如果不写任何构造方法,系统默认提供一个无参数构造方法,只是我们看不到而已。
2、如果自己写了任何一个构造方法,不管有参没参,系统就不会提供这个默认无参构造方法。
3、自己写了一个带参数的构造方法,就要把无参数构造方法也要写上。
(后面使用或者学习的一些框架要new这个无参数的构造方法)
bash 复制代码
构造方法和一般方法的不同:
1、构造方法是在new对象的时候运行,而一般的方法是在对象调用的时候才执行。
2、一个对象的建立,构造方法只执行一次,而一般方法可以被改对象调用多次。

五、作业

1、编写Java程序,模拟简单的计算器。

定义名为Cal的类,其中有两个整型数据成员num1和num2,应声明为私有。编写构造方法,赋予num1和num2初始值,再为该类定义加(add)、减(sub)、乘(multi)、除(div)等公有成员方法,分别对两个成员变量执行加、减、乘、除的运算。

在main方法中创建Cal类的对象,调用各个方法,并显示计算结果。

java 复制代码
package com.situ.day11;

public class Cal {
    private int num1;
    private int num2;

    //无参构方法:
    public Cal(){

    }

    //有参构造方法:
    public Cal(int num1,int num2){
        this.num1 = num1;
        this.num2 = num2;
    }

    public int add(){
        int result = num1 + num2;
        return result;
        //return num1 + num2;
    }

    public int sub(){
        int result= num1 - num2;
        return result;
    }

    public int multi(){
        int result = num1 * num2;
        return result;
    }

    public int div(){
        int result = num1 / num2;
        return result;
    }

    public static void main(String[] args) {
        //创建对象:
        Cal cal = new Cal(5,10);
        System.out.println(cal.add());
        System.out.println(cal.sub());
        System.out.println(cal.multi());
        System.out.println(cal.div());
    }
}

2、定义长方形类,含:

属性:宽、高(整型);

构造方法3个:(1)无参------宽、高默认值为1;(2)1个参数------宽、高相等;(3)2个参数------宽、高各为参数值。

方法:求周长、面积;

要求:进行测试计算周长和面积。

java 复制代码
package com.situ.day11;

import org.junit.Test;

public class Rect {
    private int width;
    private int height;
    //无参构造方法:
    public Rect(){

    }

    //有参构造方法
    public Rect(int width, int height) {
        this.width = width;
        this.height = height;
    }

    //一个参数的构造方法
    public Rect(int width){
        this.width = width;
        this.height = width;
    }

    //方法:
    public int zhouChang(){
        return (width + height) * 2;
    }
    public int mianJi(){
        return width * height;
    }

    //测试:
    public static void main(String[] args) {
        Rect rect = new Rect(3,5);
        System.out.println(rect.zhouChang());
        System.out.println(rect.mianJi());
    }

}
相关推荐
小信丶10 分钟前
Spring Cloud Stream EnableBinding注解详解:定义、应用场景与示例代码
java·spring boot·后端·spring
无限进步_14 分钟前
【C++】验证回文字符串:高效算法详解与优化
java·开发语言·c++·git·算法·github·visual studio
亚历克斯神15 分钟前
Spring Cloud 2026 架构演进
java·spring·微服务
七夜zippoe19 分钟前
Spring Cloud与Dubbo架构哲学对决
java·spring cloud·架构·dubbo·配置中心
海派程序猿19 分钟前
Spring Cloud Config拉取配置过慢导致服务启动延迟的优化技巧
java
阿维的博客日记30 分钟前
为什么不逃逸代表不需要锁,JIT会直接删掉锁
java
William Dawson31 分钟前
CAS的底层实现
java
九英里路42 分钟前
cpp容器——string模拟实现
java·前端·数据结构·c++·算法·容器·字符串
YDS8291 小时前
大营销平台 —— 抽奖前置规则过滤
java·spring boot·ddd
仍然.1 小时前
多线程---CAS,JUC组件和线程安全的集合类
java·开发语言