Java学习 -- 面向对象概述与封装性

Posted 庸人冲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习 -- 面向对象概述与封装性相关的知识,希望对你有一定的参考价值。

文章目录

面向对象思想

概述

Java语言是一种面向对象的程序设计语言,而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下,使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。

面向过程与面向对象的区别

面向过程:当需要实现一个功能时,每一个具体的步骤都要亲历亲为,详细处理每一个细节。

面向对象:当需要实现一个功能时,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我们做事。

举例

洗衣服:

面向过程:把衣服脱下来–>找一个盆–>放点洗衣粉–>加点水–>浸泡10分钟–>揉一揉–>清洗衣服–>拧干–>晾起来

面向对象:把衣服脱下来–>打开全自动洗衣机–>扔衣服–>按钮–>晾起来

区别

面向过程:强调步骤

面向对象:强调对象,这里的对象就是洗衣机。

代码展示

public class Demo01PrintArray 
    public static void main(String[] args) 
        int[] arr = 1,2,3,4,5;
        // 要求打印格式为:[1, 2, 3, 4, 5]

        // 面向过程实现
        System.out.print("[");
        for(int i = 0; i < arr.length; i++)
            if(i < arr.length - 1) 
                System.out.print(arr[i] + ", ");
             else 
                System.out.println(arr[i] + "]");
               // 需要关注功能实现的每一个细节
        

        System.out.println("===============");

        // 面向对象实现
        System.out.println(Arrays.(arr));
        // 不需要关注功能实现的每一个细节,只需要调用具有这个功能的方法即可。
        //Arrays.toString() 
        //JDK提供的Arrays类中的toString() 方法
        //Arrays.toString() 可以将数组转换成字符串格式
    

特点

面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。面向对象的语言中,包含了三大基本特征,即封装继承多态

面向对象三条主线

  1. 类及类的成员:属性(成员变量)、成员方法、构造器、代码块、内部类。
  2. 面向对象三大特性:封装、继承、多态。
  3. 其它关键字:this, super, abstract, interface, final, package, import…

类和对象

什么是类

:是一组相关属性行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。

现实中,描述一类事物:

属性:就是该事物的状态信息。

行为:就是该事物能够做什么。

举例:小猫。

属性:名字、体重、年龄、颜色。

行为:走、跑、叫。

什么是对象

对象:是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性和行为

现实中,一类事物的一个实例:一只小猫。

举例:一只小猫。

属性:tom、5kg、2 years、yellow。

行为:溜墙根走、蹦跶的跑、喵喵叫。

类与对象的关系

类是对一类事物的描述,是抽象的。

对象是一类事物的实例,是具体的。

类是对象的模板,对象是类的实体。

类的定义

事物与类的对比

  1. 现实世界的一类事物:

    属性:事物的状态信息。

    行为:事物能够做什么。

  2. Java中用class描述事物也是如此:

    成员变量:对应事物的属性

    成员方法:对应事物的行为

类的定义格式

public class ClassName 
    //成员变量
    //成员方法

定义类:就是定义类的成员,包括成员变量成员方法

成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外,也叫类的属性,field。

成员方法:和以前定义方法几乎是一样的。只不过把static去掉,static的作用在面向对象后面课程中再详细讲解。

/*
定义一个类,用来模拟"学生",其中就有两个组成部分:
1、属性(是什么):
    姓名、年龄、性别、...
2、行为(能做什么):
    吃饭、睡觉、学习、...

对应到java的类当中:
1、成员变量(属性):
    String name;  // 姓名
    int age;      // 年龄
    byte sex;     // 性别 0:女,1:男,2:保密
2、成员方法(行为):
    public void eat()     // 吃饭
    public void sleep()   // 睡觉
    public void study()   // 学习
 */

public class Student 
    // 成员变量
    String name;  // 姓名
    int age;      // 年龄
    byte sex;     // 性别

    // 成员方法
    public void eat()
        System.out.println("吃!");
    

    public void sleep() 
        System.out.println("睡!");
    

    public void study() 
        System.out.println("学!");
    

对象的使用

使用步骤

通常情况下,一个类并不能直接使用,需要根据类创建一个对象,才能使用,具体分为以下三个步骤:

  1. 导包:指出需要使用的类在什么位置。

    如果类同属于一个包中(同一路径下),可以省略导包语句

// 导包语句
// import packageName.className;
import cn.study.day07.demo03.Demo02Student;
  1. 创建
// className objName = new className();
Student stu = new Student();
  1. 使用

使用成员变量

// objName.memberVarName
stu.name = "张三";

使用成员方法

// objName.memberMethName(para,...)  para可以是0或多个
stu.eat();

总结:想用谁,就用对象名点儿谁。

代码举例

例一

public class Demo02Student 

    public static void main(String[] arg)
        // 1. 导包
        // 需要使用的Student类,和当前所在类同属一个包下,可以省略导包语句。

        // 2. 创建
        // className objName = new className();
        Student stu = new Student();
        // 根据Student类创建了一个stu的对象。

        //3. 使用其中的成员变量
        System.out.println(stu.name);   // null
        System.out.println(stu.age);    // 0
        System.out.println(stu.sex);    // '\\u0000'
        // Student类中没有给成员变量赋值
        // 默认值与数组的规则相同
        System.out.println("=====================");

        // 改变对象当中的成员变量内容
        stu.name = "张三";
        stu.age = 18;
        stu.sex = '男';
        System.out.println(stu.name);   // 张三
        System.out.println(stu.age);    // 18
        System.out.println(stu.sex);    // 男

        System.out.println("=====================");
        // 使用成员方法
        stu.eat();
        stu.sleep();
        stu.study();
    

例二

/*
定义一个类,用来模拟"手机"事物

属性:品牌、价格、颜色...
行为:通话、短信...

对应到类当中:
成员变量(属性)
    String brand;
    double price;
    String color;
成员方法(行为)
    public void call(String who)   // 打电话
    public void sendMessage()      // 群发短信
*/
public class Phone 
    //成员变量
    String brand; // 品牌
    double price; // 价格
    String color; // 颜色

    //成员方法
    public void call(String who)
        System.out.println("给" + who + "打电话");
    
    public void sendMessage() 
        System.out.println("群发短信");
    

public class Demo03PhoneOne 
    public static void main(String[] args) 
        // 根据Phone类,创建一个名为one的对象;
        Phone one = new Phone();
        System.out.println(one.brand);   // null
        System.out.println(one.price);   // 0.0
        System.out.println(one.color);   // null

        System.out.println("===================");
        // 给对象当中的成员重新赋值
        one.brand = "小米";
        one.price = 998.0;
        one.color = "黑色";

        System.out.println(one.brand);   // 小米
        System.out.println(one.price);   // 998.0
        System.out.println(one.color);   // 黑色

        System.out.println("===================");
        one.call("雷军");
        one.sendMessage();
    

成员变量默认值

成员变量如果未赋值,将会有一个默认值,规则如下:

  1. 整数类型,默认为0;
  2. 浮点类型,默认为0.0;
  3. 字符类型,默认为'\\u0000'
  4. 布尔类型,默认为false;
  5. 引用类型,默认为null

对象内存图

jvm内存划分图

一个对象的内存图

堆中的成员变量是参考方法区.class中成员变量的信息创建的,其中的值就保存在堆(Heap)中。

堆中的成员方法保存的是一个地址值,指向了方法区中的成员方法信息。

进栈也叫压栈,先进栈的在后进栈的下面,后来的压着先来的。

出栈也叫弹栈,当方法执行完毕后会立刻从栈中销毁,main方法执行完毕,则程序结束。

先进后出,后进先出。

两个对象引用指向不同对象空间的内存图

对象名,也叫对象引用

从上图可以看到,两个对象在创建时,分别在堆区开辟了不同的内存空间,各自保存着本对象的成员变量和成员方法,但是这两块堆区内存空间同时指向了方法区里同一块空间。也就是它们的所具有的属性和功能是完全相同的,不同的是成员变量的值和成员方法调用的参数。

这会出现一个问题,每创建一个对象就需要在堆中开辟一块内存空间,但是里面保存的信息基本相同,因此十分浪费内存空间。

两个对象引用指向同一对象空间的内存图

对象在方法中的使用

使用对象类型作为方法的参数

任何数据类型都能作为方法的参数。

对象引用作为参数传递给方法的是对象的地址值

public class Demo04PassObjParam 
    public static void main(String[] args) 
        Phone one = new Phone();
        one.brand = "小米";
        one.price = 998.0;
        one.color = "土豪金";
        mothod(one); // 传递的对象的地址
        System.out.println(one);

    

    public static void mothod(Phone param)
        System.out.println(param);
        System.out.println(param.brand);  // 苹果
        System.out.println(param.price);  // 998.0
        System.out.println(param.color);  // 土豪金
    


使用对象类型作为方法的返回值

使用对象类型作为方法的返回值时,返回的是对象的地址值

public class Demo05PhoneReturn 
    public static void main(String[] args) 
        // 用对象类型接收返回值
        Phone two = getPhone();
        System.out.println(two.brand);  // 小米
        System.out.println(two.price);  // 799.0
        System.out.println(two.color);  // RoseGold
    

    public static Phone getPhone() 
        Phone one = new Phone();
        one.brand = "小米";
        one.price = 799.0;
        one.color = "RoseGold";
        return one;
    


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

  1. 定义的位置不一样

    局部变量:在方法的内部

    成员变量:在方法的外部,直接写在类当中。

  2. 作用域不一样

    局部变量:所在方法中可以使用,出了所在方法就不能使用。

    成员变量:整个类全都可以通用

  3. 默认值不一样

    局部变量:没有默认值,要使用,必须先赋值

    成员变量:如果没有赋值,会有默认值,规则和数组一样。

  4. 内存的位置不一样

    局部变量:位于栈内存

    成员变量:位于堆内存。

  5. 声明周期不一样

    局部变量:随着方法进栈而创建,随着方法出栈而销毁。

    成员变量:随着对象创建而创建,随着对象被垃圾回收而消失。

  6. 权限修饰符的使用不同public、 protected、 缺省、 private

    局部变量:不能使用权限修饰符。

    成员变量:可以使用权限修饰符。

public class Demo01VariableDifference 

    String name; // 成员变量

    public void methodA()
        int num = 20; // 局部变量
        System.out.println(num);
    

    public void methodB(int param)  //参数就是局部变量
//      System.out.println(num); // 错误,num是methodA方法中的局部变量,不能在methodB中使用
        System.out.println(name);  // 成员变量,类中都可以使用
        int age;  // 局部变量
//      System.out.println(age);   // 局部变量未赋值不能使用
        // 参数在方法调用时,必然会被赋值
        System.out.println(param); // 这种写法没有问题
    

练习

创建一个学生类,三个属性,学号,年级和成绩。

创建20个学生类,其中学号从1开始到20结束,年级和成绩随机赋值。

Student类

// Student类
package cn.study.day26.demo05;

public class Student 
    private int number = id;  // 学号
    private int state;        // 年级
    private int score;        // 成绩
    private static int id = 1;    // 自增id

    // 无参构造器
    public Student() 
        ++id;
    
    // 有参构造器,number和id变量自增,不允许设置
    public Student(int state, int score) 
        this.state = state;
        this.score = score;
    

    public String stuInfo() 
        String info = "学号:" + this.getNumber() + ", 年级:" +this.getState() + ", 成绩:" + this.getScore();
        return  info;
    

    // Getter/Setter
    public int getNumber() 
       return this.number;
    

    public int getState() 
        return state;
    

    public void setState(int state) 
        this.state = state;
    

    public int getScore() 
        return score;
    

    public void setScore(int score) 
        this.score = score;
    


工具类

// 工具类
package cn.study.day26.demo05;
public class Utility 
    // 遍历打印学生信息

    /**
     * @Description 遍历Student数组,并打印数组中学生对象的信息
     * @author Joker
     * @param stus  要遍历的数组
     */
    public static void traverseStu(Student[] stus) 
        for (int i = 0; i < stus.length; i++) 
            System.out.println(stus[i].stuInfo());
        
    


    /**
     * @Description 筛选出Student数组中指定年级学的信息,并打印。
     * @author Joker
     * @param state 需要筛选出来的年级
     */
    public static void searchStu(Student[] stus, int state) 
        for (int i = 0; i < stus.length; i++) 
            if (stus[i].getState() == state) 
                System.out.println(stus[i].stuInfo());
            
        
    

    /**
     * @Description 使用冒泡排序算法,按照成绩属性给Student数组排序,从小到大。
     * @author Joker
     * @param stus  要排序的数组
     */
    public static void bubbleSortStus(Student[] stus) 
        for (int i = 0; i < stus.length - 1; i++) 
            boolean flag = true;
            for (int j = 0; j < stus.length - 1 - i; j++) 
                if (以上是关于Java学习 -- 面向对象概述与封装性的主要内容,如果未能解决你的问题,请参考以下文章

五类&对象概述

java 封装与this关键字

java面向对象(封装)

[ Java学习基础 ] Java的封装性与访问控制

Java学习--类与对象

Java学习日记 week3 面向对象2:封装,继承,多态