面向对象学习总结--何为类、引用,类实例出对象的过程和原理

概述:在上一篇面向对象学习总结中主要围绕着何为对象展开,浅析了对象如何抽象出类。接下来,主要讲围绕着类如何实例出对象作一些学习总结。

涉及到的关键词:抽象,类,类型,实例,引用变量,对象引用,引用,指向,内存地址,栈,堆


何为类

类: 将所有具有相同的属性和方法的对象归属为一个类。
相当于:类是对象的模版,从类中刻印出l来的对象都是一个模子的。

在上篇总结中有提到,这个定义类的过程就叫抽象:
1.确定对象(找到对象,找到对象属性,找到方法)。
2.定义类的属性和方法

何为抽象

从字面意思上理解:抽是抽取,象是形象,形象即表示比较特别的性质。
抽象即,抽取比较特别的性质。
在现实世界中,我们看到的实体/事物都是具体的,由于这些实体太过于具体,我们在编程中,没办法把所有这些具体的事物一个一个的表现出来,所以就诞生了抽象的概念。
从相似的具体的事物中抽取它们本质特征相同的部分形成一个概念性的实体,这个实体还并不是对象,而是类/类型。

抽象,通俗点理解就是:归类。

比如:麻雀,乌鸦,老鹰……等动物都是具体的动物,想要描述一个这种会飞,会下蛋,有喙,有羽毛,有两条腿的动物,这些性质,是它们都共有的,我们没办法说这种会飞,会下蛋,有喙,有羽毛,有两条腿的动物就是麻雀或者是乌鸦或者是其他动物。所以我们需要抽象,把所有具有会飞,会下蛋,有喙,有羽毛,有两条腿的动物称为鸟类。
鸟类并不是一个具体的事物,它是一个概念性的实体。
当我们说鸟类中羽毛是黑色,喜欢食腐,不吉利的鸟时,此时,便是讲鸟类具体化到一种鸟–乌鸦。

由上例,我们可以做一个简单的小结
1.从各种鸟种找出共有的特征,并把拥有这些共有的特征的实体称为鸟类。
这个过程就是对象抽象处类
1).在现实中确定具体的对象。
2).找到对象共有的特征,即属性和方法。
3).将共有的特征定义成一个类。

2.从鸟类中具有羽毛是黑色,喜欢食腐,看起来不吉利的鸟,明确出鸟类中的这种鸟是乌鸦。
这个过程就是类实例出对象
1).存在定义好的类。
2).通过给属性赋值或者给方法传参数值,使共有的特征越来越具体化和针对性。
3).将类具体化成一个对象。

进一步浓缩:
1.对象抽象出类 == 创建类
2.类实例出对象 == 创建对象


何为实例

名词:实例,即实际的例子。就是具体的对象
动词:实例,即实例化对象,就是将本来不存在的对象,创建出来的过程
一般来说,通过类创建出来的对象,我们都叫该类的一个实例。


面向对象–类实例出对象的过程

类是如何实例出对象

五个关键词:
1.类型(等同于数据类型)
2.对象的引用 (其他的叫法:引用变量)
3.真正的对象
4.引用/指向 (引用对象或者指向对象)
5.引用地址

类实例出对象的语语法:

类型 引用变量 = new 类型();

等同于:

类型 引用变量;
引用变量 = new 类型();

明确:
1.类型 引用变量; 这个表达式创建一个被某个引用数据类型定义的引用变量;
2.new 类型() 这个表达式创建的才是真正的对象;
3.引用变量存放在栈中,引用变量一旦被引用数据类型定义后,默认指向空对象地址(即对象值=null)。
4.真正的对象存放在堆中,并不能直接在栈中被使用
5.因此,调用对象的原理就是通过在栈中的引用变量指向在堆中的对象的地址。

对每个关键词逐一分析:

(一)何为类型:

从严格的意义上区分,类 ≠ 类型

从英文单词:

类:class 类型:type

1.类型是更抽象的概念,用于描述对象拥有什么属性和方法,侧重于描述。

2.类是定义一个对象拥有什么属性和方法,侧重于定义。

从用法上:

类:创建类

//定义一个学生类
public class Students{
    //定义属性
    String name;

    //定义获取名字属性的方法
    public String getName() {
        return name;

    //定义设置名字属性的方法
    public void setName(String name) {
        this.name = name;
    }

    //定义方法
    public void study(){
        system.out.println("学习中...");
    }
}

类型:
1.定义基本数据类型,使基本变量拥有真实的数值
2.定义引用变量的数据类型,使引用变量拥有类中的属性和方法

```
//定义一个基本变量,它的数据类型是基本数据类型int,它具有数值是整数的特征
int a = 5 ;

//定义一个引用变量,它的数据类型是引用数据类型Sttudents
Students student;

//创建一个实例
student = new Students();

//调用set方法,给名字赋值
student.setName() = "xiaoming";

//调用get方法,获取名字属性值
String name = student.getName();

//引用变量student拥有了学习的方法,调用该方法
student.study();

小结

1.类型是一个抽象的概念,描述对象拥有的属性和方法; 而类是通过这个抽象概念,由程序员定义,从而创建对象。

2.类和类型之间的关系:

1).由对象抽象出类型 – – 此时类型只是一个概念,还没存在,不能被使用

2).再由类型定义出类 – – 通过类型了解了需要定义的属性和方法后,就可以创建类。

3).再由类使该类型以数据类型的形式存在 – – 类一旦定义好了,Java中就会存在这个类的数据类型,可以像基本数据类型一样对变量进行定义,使变量拥有类中的属性和方法。

一般来说,不会专门去对类和类型作区分。

(二)何为引用变量

引用变量有好几种称呼,比如:对象的引用,一个引用

Java中有两种数据类型:

1.基本数据类型:

定义:又叫原始数据类型,是内置的数据类型,Java语言已经自身完成定义。共有八大基本数据类型:byte,short,int,long,float,double,char,boolean。

作用:变量的作用是存放数据,而基本数据类型是将定义存放进来的数据指定为真实的数字、字符。

2.引用数据类型:

定义:又叫对象数据类型,针对对象提供的数据类型。该类型通常封装了很多属性和方法,属于复合数据类型,Java自身没有定义,是程序员定义的类或者接口,内部定义了属性和方法。

作用:引用变量的作用是指向引用的对象的地址。该数据类型定义了引用变量指向的地址上存放的对象值是某一类型。

回到变量和引用变量

小结:

1.变量: 也是一个抽象的概念,表示没有固定的值,可以改变的数。定义变量就是为了保存不固定的值。

2.普通变量: 变量的一种分类,被基本数据类型定义,即被要求保存的是不固定的真实的数值。

3.引用变量: 也是变量的一种分类,被引用数据类型定义,即被要求指向某一个对象的地址,使用该变量的时候,会指向对象的地址,对引用变量的操作等同于对对象的操作。

4.普通变量和引用变量的区别:

1) . 变量保存的是一个真实的数值,该数值为定义的基本数据类型

2) . 引用变量并不保存值,它的作用是指向一个对象的地址,该对象为定义的引用数据类型。

(三)为什么创建的真正的对象要借助引用变量才能被调用:

关键点:java数据类型在内存中的分配、栈和堆的区别

1.基本数据类型的变量和引用数据类型的引用变量都是分配在栈内存中;

2.new关键字创建的对象或者数组都是分配在堆内存中;

3.java虚拟机的运行基于堆栈:

堆:存放对象及对象拥有的类变量(全局变量);运行new关键词产生,当没有引用变量指向的时候,会变成垃圾,等待java垃圾机制回收。

栈:执行程序的内存;存放局部变量和引用变量;存放速度快;产生和销毁由java自动分配。

Student student = new Students();

Studetns类创建一个实例的过程:

创建一个实例的内存分配

小结:

1.创建出来的对象存放在堆中,程序方法运行在栈中,故调用对象需要借助引用变量;

2.引用变量相当于对象的一个别名或者替身,在程序中的作用等价于真正的对象。

3.引用变量相当于一个指针,指向了在堆内存中对象的地址。

4.对象一旦创建,只要有引用变量指向它,它就能一直存在堆内存中,能被重复利用。故方法结束时,对象不一定被销毁。

5.只有当没有任何引用变量指向对象在堆内存中的地址的时候,对象才会被视为垃圾,被java垃圾机制在比较合适/随机的时候回首

ps: 存在“引用对象”这个名词,但是个人觉得这个名词概括的有点歧义。有表示是“引用的对象”的意思,又有形容是“引用变量”(把变量比喻为一个通过引用而来的对象)的意思。所以个人建议:把在堆内存中的对象称为 “对象” 或者 一个“实例”,把在栈内存中的引用变量称为 “对象的引用”,一个“引用” 或者 “引用变量” 能最明显的区分,不容易混淆。

代码分析,从定义类到创建一个实例的整个过程。

关键点:
1.类的定义
2.对象的实例化过程
3.使用对象:
1).对象属性的设置和获取
2).对象方法的调用

1.定义一个完整的类

/**
 * 定义学生类,学生可用于登陆学生信息管理系统
 */
public class Students{
    /**
     * 私有化类变量(成员变量/全局变量),封装的思想
     */
    //学生登陆账号
    private int account;
    //学生登陆密码
    private String password;
    //学生姓名
    private String stuName;
    //学生班级
    private String stuClass;
    //学生性别
    private String stuSex;
    //学生手机号码
    private String stuPhone;
    //学生家庭地址
    private String address;
    //学生的注册时间
    private Date registTime;

    /**
     * 定义构造函数(是一个特殊的方法)
     * 作用:用于给对象进行初始化 -- 选择性的给定义了的属性赋值
     * 特点:
     * 1.构造函数的名称和所在的类的名称相同
     * 2.构造函数不需要定义返回值类型
     * 3.构造函数没有具体的返回值
     * 
     * 明确:
     * 所有对象创建时,都需要初始化才可以使用。
     * 
     * 定义构造函数的规则:
     * 1.在定义类的时候,如果没有定义构造函数,则java会隐示的自动生成一个空参数的构造函数(即默认构造函数)
     * 2.定义了非空参数的构造函数,将不会自动生成一个空参数的构造函数。一般来说,这时候选择显示的定义一个空构造函数,方便对象进行空参数的初始化
     * 3.定义类的时候,可以定义多个构造函数,java会根据参数的类型和个数的不同,自动选择匹配构造函数(体现了方法的重载)
     * 4.构造函数在对象创建的时候被调用,且只执行一次
     */

     //显示空参数构造函数
    public Students(){

    }

    //单参数构造函数
    public Students(int account){
        //this关键字的作用:指向本类中的属性和方法
        //this+.指向本类中的属性
        //语义:给本类中的account属性赋值,值为传进来的参数
        this.account = account;
    }

    //两个参数的构造函数
    public Students(int account,String password){
        //this+() 调用本类中的参数个数和类型匹配得上的构造函数
        //语义:参数个数为1,类型为int,调用上面的单参数构造函数
        this(account);
        this.password = password;
    }

    //全参数的够赞函数
    public Students(int account, String password, String stuName, String stuClass, String stuSex, String stuPhone,String address, Date registTime) {

        this(account,password);
        this.stuName = stuName;
        this.stuClass= stuClass;
        this.stuSex = stuSex;
        this.stuPhone = stuPhone;
        this.address = address;
        this.registTime = registTime;
    }

    /**
     * 1.给外界提供公共的获取属性值的方法
     * 2.给外界提供公共的修改属性值的方法(初始化只被执行一次,以便对象创建后修改/设置新的属性值)
     * 一般来说,get方法和set方法都是成对的。
     * set方法和构造函数是完全不冲突的:
     * 构造函数是在对象创建的进行属性的初始化(第一次赋值);
     * 构造函数决定相对应的属性会被赋值,其他属性在初始化后默认属性值为空;
     * set方法是在对象已经存在后对属性进行修改或者设置(有些属性在初始化后仍为空)
     */

    //获取账号属性值的方法
    public int getStuId() {
        return account;
    }
    //设置/修改账号属性值的方法
    public void setStuId(int stuId) {
        this.account = stuId;
    }

    public String getStuPassword() {
        return password;
    }
    public void setStuPassword(String stuPassword) {
        this.password = stuPassword;
    }

    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;

    public String getStuClass() {
        return stuClass;
    }
    public void setStuClass(String stuClass) {
        this.stuClass = stuClass;
    }

    public String getStuSex() {
        return stuSex;
    }
    public void setStuSex(String stuSex) {
        this.stuSex = stuSex;
    }

    public String getStuPhone() {
        return stuPhone;
    }
    public void setStuPhone(String stuPhone) {
        this.stuPhone = stuPhone;
    }

    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }

    public Date getRegistTime() {
        return registTime;
    }
    public void setRegistTime(Date registTime) {
        this.registTime = registTime;
    }
}

2.类实例化对象&对象的使用

//定义一个测试类
public class Test{
    public static void main(String[] args) {

        //创建一个实例,传入参数为空 -- 调用空构造函数进行初始化
        Students stu1 = new Students();

        //创建一个实例,传入一个int参数 -- 调用参数类型为int,个数为1的构造函数
        Students stu2 = new Students(10000);
        //调用get方法,打印该属性值
        System.out.println(stu2.getStuId);
        //调用set方法,给stu2实例的名字属性设置值
        stu2.setStuName = "小明";
        System.out.println(stu2.getStuName);

        //创建一个实例,传入所有参数 -- 调用全参数的构造函数
        Students stu3 = new Students(10001,"小明","1402班","男","18812345678","广东省广州市",new Date());
        //new Date() 创建一个临时日期类型对象,对象值为当前系统时间
    }
}

发现:new 类型( ); – – ( ) 表示了初始化的属性 ,即决定了创建对象时要选择的构造函数。

**小结:**
类实例出对象的整个过程(结合内存):

1.加载.class文件:
在硬盘上把Students.class和Test.class文件加载进内存;

2.开辟栈空间: 
执行main方法,在栈内存中开辟了方法的内存空间,在方法的空间里分配一个空间给引用变量students

3.开辟堆空间:
在堆内存中开辟一个实体空间(用于存放对象),分配一个内存首地址(引用变量指向的地址)

4.分配属性的空间及默认初始化:
在堆中的对象实体空间分配各属性的空间,并进行默认的初始化(系统默认的,为null//系统默认初始化后,对象真正存在,但是不能被外部访问,只能被构造函数访问。

5.调用构造函数初始化:
根据参数的个数和类型,选择匹配的构造函数,对对象进行初始化

6.使引用变量指向对象空间的首地址:
将首地址通过赋值的方式传给引用变量,此时,引用变量指向了该对象。
//指向成功后,此时对象可以被外部访问了(即可以被使用)。

这里写图片描述
一般情况下,创建对象的整个过程如上。

特殊情况如:
匿名对象:又叫临时对象(创建的过程完成了上文的1-5步,不完成第6步)
概念:直接使用对象,而不创建引用变量指向对象。故是一个没有名字的对象。
作用:
1.当对象只使用一次,或者只使用一次对象的方法等时候,从编码简化和内存角度考虑,采用匿名对象。

//设置注册时间,注册时间是唯一的,Date对象只使用一次就可以了,没必要一直存在。
Students stu = new Students();
stu1.setRegistTime(new Date());
//直接返回当前结果的时候
public Date getSystemTime(){
    return new Date();
}
//只调用一次对象的方法的时候
new Students().study();

原理上,匿名对象是有名对象的简化版。
区别在于:
1)因为有分配首地址的步骤,有名对象可以被重复使用,即有引用变量指向,就一直存在堆内存中;
2)匿名对象没有引用变量指向,只能被使用一次,使用一次后由于没有被引用变量指向,会被作为垃圾被回收,所以又叫临时对象。

2.作为实际参数进行传递

//定义一个添加学生信息的方法,此时参数为一个对象
public static void addStudents(Students stu){
    ... 
}

//执行添加信息的方法,当我只添加,没有后续操作,即只使用一次对象,可用匿名对象
addStudents(new Students());

总结:

对象抽象出类,类实例出对象:

1.选取具体实体对象,根据共同特征,抽象出类型 – – 实体 –> 描述性的概念

2.根据类型,定义类 – – 描述性的概念 – > 可实现性的概念

3.根据类,创建对象 – – 可实现性的概念 – > 具体的对象

4.使用对象 – – 操作对象中的属性和方法

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页