day07_面向对象入门及属性初识

面向过程和面向对象的思想

“面向过程”(Procedure Oriented):是一种以过程为中心的编程思想,简称 OP。“面向过程”也可称之为“面向记录”编程思想,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。所以面向过程的编程方式关注点不在“事物”上,而是做这件事分几步,先做什么,后做什么。例如:早晨起来:起床、穿衣、洗漱、上班,只要按照这个步骤来,就能实现“一天”的功能,整个这个过程中关注的是一步一步怎么做,并没有关注“人”这个事物。再例如:开门、调整座椅、系好安全带、踩离合、启动、挂档、给油,只要按照这个步骤来,车就走了,显然关注点还是在步骤上,只要实现每一步就行,整个过程并没有关注“汽车”这个事物。

“面向对象”(Object Oriented):是一种以对象为中心的编程思想,简称 OO。随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题。一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象。通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,可以像搭积木的一样快速开发出一个全新的系统。面向对象将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

使用面向对象编程思想开发系统,在现代开发中会将面向对象贯穿整个过程,一般包括:OOA/OOD/OOP:

  • OOA:面向对象分析(Object-Oriented Analysis)
  • OOD:面向对象设计(Object-Oriented Design)
  • OOP:面向对象编程(Object-Oriented Programming)

面向过程和面向对象有什么关系呢?

  • 面向过程其实是最为实际的一种思考方式,就算是面向对象的方法也是含有面向过程的思想。可以说面向过程是一种基础的方法。它考虑的是实际地实现。一般的面向过程是从上往下步步求精。面向对象主要是把事物给对象化,对象包括属性与行为。当程序规模不是很大时,面向过程的方法还会体现出一种优势。因为程序的流程很清楚,按着模块与函数的方法可以很好的组织。但对于复杂而庞大的系统来说,面向过程显得就很无力了。面向对象的好处之一就是显著的改善了软件系统的可维护性。对于编程语言来说,基于 C 语言的编程是面向过程的,C++只能说一半面向过程一半面向对象,java 语言就是一门完全面向对象的编程语言。因为 java 底层是 C++语言实现的。当然,除了 java 语言之外,还有很多都是完全面向对象的编程语言,例如:C#、Python 等。

面向对象和面向过程思想的总结

  • 都是解决问题的思维方式,都是代码组织的方式。
  • 面向过程是一种“执行者思维”,解决简单问题可以使用面向过程。
  • 面向对象是一种“设计者思维”,解决复杂、需要协作的问题可以使用面向对象。
  • 面向对象离不开面向过程:
    • 宏观上:通过面向对象进行整体设计
    • 微观上:执行和处理数据,仍然是面向过程。

                                                                                                                                                                                                                                                                  day07_面向对象入门及属性初识

面向对象分析方法分析问题的思路和步骤:

  1. 根据问题需要,选择问题所针对的现实世界中的实体。
  2. 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类。
  3. 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义。即借助某种程序语言,把类构造成计算机能够识别和处理的数据结构。
  4. 将类实例化成计算机世界中的对象。对象是计算机世界中解决问题的最终工具。

面向对象三大特征

  • 封装(Encapsulation)
  • 继承(Inheritance)
  • 多态(Polymorphism)

面向对象的思想概述

软件存在的意义就是为了解决现实世界当中的问题,它必然模拟现实世界,也就是说现实世界中有什么,软件中就对应有什么。类(Class)和对象(Object)是面向对象的核心概念。

那么类和对象分别是什么,它们的区别和联系是什么呢?

  • 类是对一类事物的描述,是抽象的、概念上的定义类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象。我们要造一个汽车,怎么样造?类就是这个图纸,规定了汽车的详细信息,然后根据图纸将汽车造出来。
  • 对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。对象:我们叫做Object,instance(实例)。以后我们说某个类的对象,某个类的实例。是一样的意思。万物皆对象,客观存在的事物皆为对象。

例如:“沈腾”、“赵本山”、“宋丹丹”都是实际存在的对象,他们都属于“笑星”类,类描述事物的共同特征,那么“笑星”类都有哪些共同特征呢?笑星类都有姓名、性别、年龄等状态信息(属性),他们还有一个共同的行为就是“演出”(方法)。但当具体到某个对象上之后,我们发现姓名是不同的,性别是不同的,年龄也是不同的,演出的效果也是不同的。所以我们在访问姓名、性别、年龄的时候,必须先有笑星对象,通过真实存在的笑星对象去访问他的属性,包括“演出”的时候,只有“笑星”类是不行的,必须先有笑星对象,让笑星对象去执行“演出”这个动作。

  • 通过类可以创建对象,对象又被称为实例(instance),这个过程也可以称为实例化
  • 面向对象程序设计的重点是类的设计 
  • 类的设计,其实就是类的成员的设计

通过以上的描述,我们得知:类中最重要就是属性 和方法,而属性描述的是状态,方法描述的是行为动作。行为动作以方法的形式存在,那属性以什么形式存在呢?例如:姓名、性别、年龄,变量用来存储数据。不错,对象的属性以变量形式存在,并且这里所说的变量是我们之前提过的“成员变量当中的实例变量”。为什么是实例变量呢,实例变量就是对象级别的变量,这样的变量要求必须先存在对象,通过对象才能访问。例如:“中国人”这个类,有一个属性是“身份证号”,每一个中国人的“身份证号”都是不一样的,所以身份证号必须使用一个真实存在的“中国人对象”来访问。不能使用“中国人”这个类去访问身份证号。一个类可以实例化 N 多个对象,假设通过“中国人”这个类创建了 100 个“中国人对象”,那么“身份证号”必然会有 100 个实例变量空间去存储。

总结一下常见的类的成员

                                                                                                                                                                                                                                            day07_面向对象入门及属性初识

现实中的属性:对应类中的成员变量。 属性(field 成员变量):属性用于定义该类,对象包含的数据或者说静态特征。属性作用范围是整个类体。在定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的值对其初始化。

现实中的行为:对应类中的成员方法。方法用于定义该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。方法很类似于面向过程中的函数。面向过程中,函数是最基本单位,整个程序由一个个函数调用组成。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。​

类的语法格式

day07_面向对象入门及属性初识

创建Java自定义类步骤如下:

  1. 定义类(考虑修饰符、类名)
  2. 编写类的属性(考虑修饰符、属性类型、属性名、初始化值)
  3. 编写类的方法(考虑修饰符、返回值类型、方法名、形参等)

创建一个Student类

//1.创建类,设计类的成员
class Person{
    
    //属性
    String name;
    int age = 1;
    boolean isMale;
    
    //方法
    public void eat(){
        System.out.println("人可以吃饭");
    }
    
    public void sleep(){
        System.out.println("人可以睡觉");
    }
    
    public void talk(String language){
        System.out.println("人可以说话,使用的是:" + language);
    }
    
}

类的访问机制:

  • 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(例外:static方法访问非static,编译不通过。)
  • 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员。

对象的创建和使用

                                                                                                                                                                                                                                                               day07_面向对象入门及属性初识

类定义之后,就可以使用类这个“模板”来创造“对象”了,一个类是可以创建多个对象的哦!怎么创建呢,语法是什么?其实语法格式很简单:new 类名(),这样就可以完成对象的创建了。俗话说,你想要什么 java 都可以给你,想要啥你就 new啥。创建对象完整语法:

  • 类名 对象名 = new 类名();

使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)

使用上面自定义Student类,创建对象

package demo01;

/*
 * 一、设计类,其实就是设计类的成员
 *
 *  属性 = 成员变量 = field = 域、字段
 *  方法 = 成员方法 = 函数 = method
 *
 *  创建类的对象 = 类的实例化 = 实例化类
 *
 * 二、类和对象的使用(面向对象思想落地的实现):
 *  1.创建类,设计类的成员
 *  2.创建类的对象
 *  3.通过“对象.属性”或“对象.方法”调用对象的结构
 *
 * 三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)
 *   意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。
 *
 */
//测试类
public class PersonTest {
    public static void main(String[] args) {
        //2. 创建Person类的对象
        Person p1 = new Person();

        //给变量赋值
        p1.name = "Tom";
        p1.isMale = true;
        
        //访问属性:“对象.属性”
        System.out.println(p1.name); //Tom
        
        //调用方法:“对象.方法”
        p1.eat(); //人可以吃饭
        p1.sleep(); // 人可以睡觉
        p1.talk("Chinese");  //人可以说话,使用的是:Chinese

        //*******************************
        //再次创建一个对象
        Person p2 = new Person();
        System.out.println(p2.name);//null
        System.out.println(p2.isMale);  // false
        //*******************************
        //将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
        Person p3 = p1;
        System.out.println(p3.name);//Tom

        p3.age = 10;
        System.out.println(p1.age);//10

    }
}

java 语言当中凡是使用 class 关键字定义的类都属于引用数据类型,类名本身就是这种引用数据类型的类型名。

注意:

  • 如果创建了一个类的多个对象,对于类中定义的属性(成员变量),每个对象都拥有各自的一套副本,且互不干扰。
  • 在 java 语言当中,当实例变量没有手动赋值,在创建对象的时候,也就是说在 new 的时候,系统会对实例变量默认赋值

                                                                                                                                                                                                                                                day07_面向对象入门及属性初识

对象创建和使用的深层次解密

为了更好的理解上面的程序,先来看看java 虚拟机是如何管理它的内存的,请看下图:

                                                                                                                                                                    day07_面向对象入门及属性初识

程序计数器:

  • 概念:可以看做当前线程所执行的字节码的行号指示器。
  • 特点:线程私有的内存

java 虚拟机栈(重点):

  • 概念:描述是 java 方法执行的内存模型。(每个方法在执行的时候会创建一个栈帧,用于存储局部变量表,局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char 、 short 、 int 、 float 、 long 、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址操作数栈,动态链接,方法出口等信息。每个方法从调用直至完成的过程,就对应一个栈帧从入栈到出栈的过程。)
  • 特 点 : 线 程 私 有, 生 命 周期 和 线 程 相同 。 这 个 区域 会 出 现 两种 异 常 :*Error 异常: 若线 程请求 的深 度大于 虚拟 机所允 许的 深度 。OutOfMemoryError异常:若虚拟机可以动态扩展,如果扩展是无法申请到足够的内存。

本地方法栈:

  • 概念:它与虚拟机栈所发挥的作用是相似的,区别是 java 虚拟机栈为执行 java 方法服务,而本地方法栈是为本地方法服务。
  • 特点:每个线程都有一个单独的栈,栈内存线程私有,也会抛出两类异常:*Error 和 OutOfMemoryError。

java 堆(重点):

  • 概念:是被所有线程共享的一块区域,在虚拟机启动时创建。
  • 特点:线程共享,存放的是对象实例(所有的对象实例和数组),GC 管理的主要区域。可以处于物理上不连续的内存空间。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

方法区(重点):

  • 概念:存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据。
  • 特点:线程共享的区域,抛出异常 OutOfMemory 异常:当方法区无法满足内存分配需求的时候。

以上所描述内容,有看得懂的,也有看不懂的,例如:线程、本地方法等,这个需要大家在学习后面内容之后,返回来再看一看,那个时候你就全部明白了。针对于目前来说,大家必须要知道 java 虚拟机有三块主要的内存空间,分别是“虚拟机栈(后面简称栈)”、“方法区”、“堆区”,方法区存储类的信息,栈中存储方法执行时的栈帧以及局部变量,堆区中主要存储 new 出来的对象,以及对象内部的实例变量。其中垃圾回收器主要针对的是堆内存,方法区中最先有数据,因为程序执行之前会先进行类加载。栈内存活动最频繁,因为方法不断的执行并结束,不断的进行压栈弹栈操作。将目前阶段需要掌握的内存空间使用一张简单的图表示出来,这个图是大家需要掌握的:

                                                                                                                                                                                                    day07_面向对象入门及属性初识                      大概了解了 java 虚拟机内存分配之后,来看看以下代码在执行过程中,内存是如何变化的:

public class StudentTest {
    public static void main(String[] args) {
            int i = 10;
            Student s1 = new Student();
        } 
}

以上代码在执行过程中内存的变化如下图所示:

第一步:进行类加载                                                                                                                                                                                                                                                                 day07_面向对象入门及属性初识 第二步: main 方法调用,给 main 方法分配栈帧(压栈)                                                                                                                                                                                                                                                                day07_面向对象入门及属性初识 第三步:执行 int i = 10,局部变量                                                                                                                                                                                                                                       day07_面向对象入门及属性初识 第四步:执行 new Student(),在堆中创建对象,同时初始化实例变量                                                                                                                                                                                                                                     day07_面向对象入门及属性初识 第五步:将堆区中学生对象的内存地址赋值给局部变量 s1                                                                                                                                                                                                                day07_面向对象入门及属性初识总结一下:
  • 上图中 i 变量和 s1 变量都是局部变量,都在栈内存当中,只不过 i 变量是基本数据类型 int, 而 s1 变量是引用数据类型 Student。
  • 上图中堆区当中的称为“对象”,该“对象”内部 no、name、age、sex 都是实例变量/属 性,这些变量在 new对象的时候初始化,如果没有手动赋值,系统会赋默认值。
  • 上图堆区中“对象”创建完成之后,该对象在堆区当中的内存地址是:0x1111,程序中的 “=”将 0x1111 这个堆内存地址赋值给 s1 变量,也就是说 s1 变量保存了堆内存对象的内存地 址,我们对于这种变量有一种特殊的称呼,叫做“引用”。
  • 也就是说对于 Student s1 = new Student() 代码来说,s1 不是对象,是一个引用,对象实际上是在堆区当中,s1 变量持有这个对象的内 存地址。

java 中没有指针的概念(指针是 C 语言当中的机制),所以 java 程序员没有权利直接操作 堆内存,只能通过“引用”去访问堆内存中的对象,例如:s1.no、s1.name、s1.sex、s1.age。 访问一个对象的内存,其实就是访问该对象的实例变量,而访问实例变量通常包括两种形式, 要么就是读取数据,要么就是修改数据,例如:System.out.println(s1.no)这就是读取数据,s1.no = 100 这就是修改数据。

类的成员:属性

    day07_面向对象入门及属性初识

代码示例

public class Demo {
    //声明private变量 age
    private int age;
    //声明public变量 name
    public String name = "Lila";
}

变量的分类:

  • 成员变量:在方法体外,类体内声明的变量称为成员变量。
  • 局部变量:在方法体内部声明的变量称为局部变量。局部变量除形参外,均需显式初始化。

                                                                                                                                                                                                                                             day07_面向对象入门及属性初识

成员变量(属性)和局部变量的区别

                                                                                                                                                                                      day07_面向对象入门及属性初识

对象属性的默认初始化赋值 

当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型。

                                                                                                                                                                                                                                               day07_面向对象入门及属性初识

代码示例

package com.atguigu.java;
/*
 * 类中属性的使用
 * 
 * 属性(成员变量)   vs  局部变量
 * 1.相同点:
 *         1.1  定义变量的格式:数据类型  变量名 = 变量值
 *         1.2 先声明,后使用
 *         1.3 变量都有其对应的作用域 
 * 
 * 
 * 2.不同点:
 *         2.1 在类中声明的位置的不同
 *         属性:直接定义在类的一对{}内
 *         局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
 *         
 *         2.2 关于权限修饰符的不同
 *         属性:可以在声明属性时,指明其权限,使用权限修饰符。
 *             常用的权限修饰符:private、public、缺省、protected  --->封装性
 *             目前,大家声明属性时,都使用缺省就可以了。
 *         局部变量:不可以使用权限修饰符。
 * 
 *         2.3 默认初始化值的情况:
 *         属性:类的属性,根据其类型,都有默认初始化值。
 *             整型(byte、short、int、long):0
 *             浮点型(float、double):0.0
 *             字符型(char):0  (或'\u0000')
 *             布尔型(boolean):false
 * 
 *             引用数据类型(类、数组、接口):null
 * 
 *         局部变量:没有默认初始化值。
 *          意味着,我们在调用局部变量之前,一定要显式赋值。
 *             特别地:形参在调用时,我们赋值即可。
 * 
 *         2.4 在内存中加载的位置:
 *         属性:加载到堆空间中   (非static)
 *         局部变量:加载到栈空间
 * 
 */
public class UserTest {
    
    public static void main(String[] args) {
        User u1 = new User();
        System.out.println(u1.name);
        System.out.println(u1.age);
        System.out.println(u1.isMale);
        
        u1.talk("韩语");
        
        u1.eat();
        
    }
}

class User{
    //属性(或成员变量)
    String name;
    public int age;
    boolean isMale;
    
    
    public void talk(String language){//language:形参,也是局部变量
        System.out.println("我们使用" + language + "进行交流");
        
    }
    
    public void eat(){
        String food = "烙饼";//局部变量
        System.out.println("北方人喜欢吃:" + food);
    }
    
}
上一篇:零基础入门学习JAVA课堂笔记 ——DAY07


下一篇:python学习笔记DAY07(编程思想)