day06_面向对象(成员变量丶方法)

面向对象思想概述

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

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

  • 面向过程:以函数(方法)为最小单位,数据独立于函数之外,以过程,步骤为主,考虑怎么做...。注重的是过程,必须清楚每一个步骤,按照步骤一步一步去实现
  • 面向对象:以类/对象为最小单位,类包括:数据+方法,以对象(谁)为主,考虑谁来做,谁能做 。注重的是对象,无须清楚每一个步骤,只需要使用对象调用行为来完成需求

面向对象仍然包含面向过程,只不过关注点变了,关注谁来做

类和对象的关系

类的概述

类是用来描述一类具有共同属性和行为事物的统称。所以其实类在客观世界里是不存在的,是抽象的,只是用来描述数据信息的。

类的组成

  • 类的属性:就是该事物的状态信息。例如:手机类的属性,品牌、价格...
  • 类的行为:就是该事物能够做什么。例如:手机类的行为,打电话、发短信...

对象的概述

对象是类的一个实例,具体存在的,看得见摸得着的,并且具备该类事物的属性和行为

  • 对象的属性:对象的属性具有特定的值。例如:手机对象的属性,品牌华为、价格1999。 对象的属性具体的值,类中的属性没有具体的值
  • 对象的行为:对象可以操作的行为。例如:手机对象的行为,使用打电话功能,使用发短信功能。对象可以使用行为

类和对象的关系

  • 类是对一类具有共同属性和行为的事物的统称,是抽象的
  • 对象是一类事物的具体实例,看得见,摸的着的,真实存在的实体,是具体的
  • 类是对象的抽象,对象是类的实体
  • 对象是根据类来创建的,类中有什么,对象就有什么,可以把类看成是对象的数据类型

类的定义和对象的创建

现实世界的一类事物:

  • 属性:事物的状态信息。
  • 行为:事物能够做什么。

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

  • 成员变量:对应事物的属性
  • 成员方法:对应事物的行为

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

类的定义

 day06_面向对象(成员变量丶方法)

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

成员方法:和以前写的main方法格式类似。只不过功能和形式更丰富了。在类中,方法外。

Java自定义类,步骤一般如下所示:

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

代码示例

public class Student {
    // 成员变量: 属性
    /**
     * 姓名
     */
    String name;
    /**
     * 年龄
     */
    int age;

    // 成员方法: 行为
    /**
     * 学习的功能
     */
    public void study(){
        System.out.println("学生正在学习Java...");
    }

    /**
     * 做作业的功能
     */
    public void doHomeWork(){
        System.out.println("学生正在做作业敲代码...");
    }
}

对象的创建

java类的实例化,即创建类的对象,格式如下

day06_面向对象(成员变量丶方法)        

 现在我们创建Student类的对象

public class Test {
    public static void main(String[] args) {
        // 需求:首先定义一个学生类,然后定义一个学生测试类,在学生测试类中通过对象完成成员变量和成员方法的使用
        // 创建学生对象
        Student stu = new Student();

        // 访问成员变量
        stu.name = "冰冰";
        stu.age = 18;
        System.out.println(stu.name + "," + stu.age);// 冰冰,18

        // 访问成员方法
        stu.study();
        stu.doHomeWork();

    }
}

总结:

  • 使用new +构造器创建一个新的对象
  • 使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)
  • 同一个类中的方法可以直接访问类中的成员变量。(特殊情况:static方法访问非static,编译不通过。)
  • 在不同类中:要先创建要访问类的对象,再用对象访问类中定义的成员。

类的成员之一:成员变量(属性)

成员变量的分类

  • 实例变量:没有static修饰,也叫对象属性,属于某个对象的,通过对象来使用
  • 类变量:有static修饰,也叫类变量,属于整个类的,不是属于某个实例

day06_面向对象(成员变量丶方法)

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

day06_面向对象(成员变量丶方法)

成员变量(属性)和局部变量的区别 有很多,主要有以下几点

  • 类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
  • 内存中位置不同:成员变量(堆内存)局部变量(栈内存)
  • 生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,随着方法的调用完毕而消失)
  • 初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)

如何声明成员变量

day06_面向对象(成员变量丶方法)

例如:声明一个中国人的类

class Chinese{
    static String country;
    String name;
    char gender = '男';//显式赋值
}

如何在类外面访问类变量

day06_面向对象(成员变量丶方法)

如何在类外面访问实例变量

day06_面向对象(成员变量丶方法)

代码示例

class Chinese{
    static String country;//静态变量,未赋值
    String name;//类变量,未赋值
    char gender = '男';//类变量,显示赋值
}
public class TestChinese {
    public static void main(String[] args) {
        //类名.静态成员变量
        System.out.println(Chinese.country);
        //	System.out.println(Chinese.name);错误,非静态成员变量必须通过对象.进行访问
        
        //创建对象
        Chinese c1 = new Chinese();
        
        //对象名.非静态成员变量
        System.out.println(c1.name);
        
        //静态的成员变量也可以通过对象.进行访问
        //对象名.非静态成员变量
        System.out.println(c1.country);
        System.out.println(c1.gender);
    }
}

成员变量有默认值

day06_面向对象(成员变量丶方法)

代码示例

class Student {
    /**
     * 姓名
     */
    String name;
    /**
     * 年龄
     */
    int age;
    /**
     * 分数
     */
    double score;
    char c;
}

public class Test {
    public static void main(String[] args) {
        /*
            成员变量的默认值:
                整数类型: 默认值是0
                小数类型: 默认值是0.0
                布尔类型: 默认值是false
                字符类型: 默认值是不可见字符 '\u0000'
                引用类型: 默认值是null
         */
        // 创建Student对象
        Student stu = new Student();
        // 访问成员变量
        System.out.println(stu.name);// null
        System.out.println(stu.age);// 0
        System.out.println(stu.score);// 0.0
        System.out.println("="+stu.c+"=");
    }
}

类变量的值是所有对象共享的,而实例变量的值是每个对象独立的

class Chinese {
    static String country;
    String name;
    char gender;
}
public class TestChinese {
    public static void main(String[] args) {
        //创建对象
        Chinese c1 = new Chinese();
        Chinese c2 = new Chinese();
        //实例变量的值是每个对象独立的
        c1.name = "张三";
        c2.name = "李四";
        c1.gender='男';
        c2.gender = '女';
        //给类变量赋值,该类的所有对象,皆共享
        Chinese.country = "中国";//推荐

        System.out.println(c1.country + "\t" + c1.name + "\t" + c1.gender);//中国	张三 	男
        System.out.println(c2.country + "\t" + c2.name + "\t" + c2.gender);//中国	李四 	女
    }
}

类的成员之二:方  法

方法:就是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。Java里的方法不能独立存在,所有的方法必须定义在类里。

成员方法分为两类:

  • 实例方法:没有static修饰的方法,必须通过实例对象来调用。
  • 静态方法:有static修饰的方法,也叫类方法,可以由类名来调用。

如何声明方法

方法声明的位置必须在类中方法外

语法格式:

day06_面向对象(成员变量丶方法)

格式详解:

  • 修饰符:  对方法的访问权限,状态进行修饰的关键字,例如:public static 
  • 返回值类型: 表示方法运行的结果的数据类型,可以是任意的数据类型。方法执行后将结果返回到调用者。例如:如果方法内部返回整数数字100,返回值类型写为int。方法内部没有返回值返还给调用者,返回值类型必须固定写为void
  • 方法名:给方法起一个名字(符合标识符的命名规范,小驼峰原则(第一个单词首字母小写,其它单词首字母大写)),见名知意,能准确代表该方法功能的名字
  • 参数列表:方法内部需要用到其他方法中的数据,需要通过参数传递的形式将数据传递过来,可以是基本数据类型、引用数据类型、也可以没有参数,什么都不写。方法没有参数,不用写参数列表,但是必须保留小括号()
  • 功能代码: 完成特殊功能的一行/多行代码
  • return 返回值:结束方法,并将方法的结果返回去,
    • 如果返回值类型不是void,方法体中必须保证一定有return 返回值;语句,并且要求该返回值结果的类型与声明的返回值类型一致或兼容
    • 如果返回值类型为void时,return 后面不用跟返回值,甚至也可以没有return语句。
    • return语句后面就不能再写其他代码了,否则会报错:Unreachable code

代码示例


public class Test {
    public static void main(String[] args) {
        System.out.println("main...start...");

        //调用方法: 传递的是常量
        int result = getMax(100, 200);
        System.out.println("100和200的最大值: " + result);

        //调用方法方法: 传递变量
        int a = 10, b = 20;
        int max = getMax(a, b);
        System.out.println(a + "和" + b + "的最大值: " + max);

        System.out.println("main...end...");

    }

    //设计一个方法可以获取两个int数的较大值,数据来自于参数
    public static int getMax(int a, int b) {
        int max = (a > b) ? a : b;
        return max;//结束方法,并且把max中的数据,返还给方法的调用处/者
    }
}

图解分析

day06_面向对象(成员变量丶方法)

如何在其他类中调用方法

实例方法

day06_面向对象(成员变量丶方法)

类方法

 day06_面向对象(成员变量丶方法)

形式参数和实际参数的区别

  • 形参:在定义方法时方法名后面括号中声明的变量称为形式参数(简称形参)即形参出现在方法定义时。
  • 实参:调用方法时方法名后面括号中的使用的值/变量/表达式称为实际参数(简称实参)即实参出现在方法调用时。

总结:

  • 调用时,需要传“实参”,实参的个数、类型、顺序顺序要与形参列表一一对应。如果方法没有形参,就不需要也不能传实参。
  • 调用时,如果方法有返回值,可以接受或处理返回值结果,当然也可以不接收,那么此时返回值就丢失了。如果方法的返回值类型是void,不需要也不能接收和处理返回值结果。

代码示例

/*
    形式参数和实际参数的区别
        1.形式参数:
            (1)概念: 定义方法时()中定义的参数(定义变量),叫做形式参数
            (2)特点:
                a.定义形式参数的时候,是没有值的
                b.当调用该方法时,形式参数才会有值

        2.实际参数:
            (1)概念: 调用方法时()中给出的参数(常量/变量),叫做实际参数
            (2)特点:
                a.调用方法时,()中写的数据(常量/变量)
                b.必须要有值才可以
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println("main...start...");
        /*
            2.实际参数:
                (1)概念: 调用方法时()中给出的参数(常量/变量),叫做实际参数
                (2)特点:
                    a.调用方法时,()中写的数据(常量/变量)
                    b.必须要有值才可以
         */
        //调用方法: 传递常量
        printSum(10,20);//10,20叫做实际参数

        //调用方法: 传递变量
        int m = 100,n = 200;

        printSum(m,n);//m,n叫做实际参数

        System.out.println("main...end...");
    }

    /*
        1.形式参数:
            (1)概念: 定义方法时()中定义的参数(定义变量),叫做形式参数
            (2)特点:
                a.定义形式参数的时候,是没有值的
                b.当调用该方法时,形式参数才会有值
     */
    //定义方法,打印2个int数字之和
    public static void printSum(int a, int b) {
        int sum = a + b;
        System.out.println("和: "+sum);
        return ;//结束方法,返回到方法的调用处,注意没有带回任何数据
    }
}

方法的注意事项

  • 方法不能嵌套定义(在定义方法的内部又定义了其它方法),可以调用其它方法
  • 方法可以嵌套调用
  • 返回值类型,必须要和 return 语句返回的数据的类型要匹配,否则编译失败 。
  • 不能在 return 后面写代码, return 意味着方法结束,所有后面的代码永远不会执行,属于无效代码。
  • void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据
  • 类,变量,方法等都要先声明后使用。 
  • 方法不调用不执行,调用一次执行一次,每次调用会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值,当方法执行结束后,会释放该内存,称为出栈,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。

方法的参数传递机制

参数传递:可以理解当我们要调用一个方法时,我们会把指定的数值,传递给方法中的参数这样方法中的参数就拥有了这个指定的值,可以使用该值,在方法中运算了。这种传递方式,我们称为参数传递。

基本类型作为方法参数传递

public class Test1 {
    /*
         方法参数传递为基本数据类型 :

                传入方法中的, 是具体的数值.
     */
    public static void main(String[] args) {
        int number = 100;
        System.out.println("调用change方法前:" + number);
        change(number);
        System.out.println("调用change方法后:" + number);
    }

    public static void change(int number) {
        number = 200;
    }
}

结论:

  • 基本数据类型的参数,形式参数的改变,不影响实际参数

结论依据:

  • 每个方法在栈内存中,都会有独立的栈空间,方法运行结束后就会弹栈消失

引用类型作为方法参数传递

public class Test {
    /*
         方法参数传递为引用数据类型 :

                传入方法中的, 是内存地址.
     */
    public static void main(String[] args) {
        int[] arr = {10, 20, 30};
        System.out.println("调用change方法前:" + arr[1]);
        change(arr);
        System.out.println("调用change方法后:" + arr[1]);
    }

    public static void change(int[] arr) {
        arr[1] = 200;
    }
}

结论:

  • 对于引用类型的参数,形式参数的改变,影响实际参数的值

结论依据:

  • 引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法弹栈,堆内存中的数据也已经是改变后的结果

方法重载

方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。

方法重载中参数列表不同有哪些情况

  • 参数数量不同
  • 参数类型不同
  • 多个类型,顺序不同

方法重载与哪些因素无关

  • 与参数的名称无关
  • 与返回值类型无关
  • 与修饰符无关

重载方法调用:JVM通过方法的参数列表,调用不同的方法。

  • 根据名称找到对应的方法
  • 根据参数的数量找到对应的方法
  • 根据参数的类型确定最终要调用的方法(首先: 做类型完全匹配 其次: 完全匹配的找不到,再做自动类型提升的匹配)

代码示例

// 使用方法重载的思想,设计比较两个数据是否相等的方法,兼容全整数类型(byte,short,int,long)
public class Test {
    public static void main(String[] args) {
        //5.分别调用以上四个方法
        System.out.println(compare(10,20));
        System.out.println(compare((byte)10,(byte)20));
        System.out.println(compare((short)10,(short)20));
        System.out.println(compare(10L,20L));
    }

    //1.使用方法重载的思想,定义比较两个byte数据的方法compare
    public static boolean compare(byte a, byte b) {
        System.out.println("...两个byte...");
        return a == b;
    }

    //2.使用方法重载的思想,定义比较两个short数据的方法compare
    public static boolean compare(short a, short b) {
        System.out.println("...两个short...");
        return a == b;
    }

    //3.使用方法重载的思想,定义比较两个int数据的方法compare
    public static boolean compare(int a, int b) {
        System.out.println("...两个int...");
        return a == b;
    }

    //4.使用方法重载的思想,定义比较两个long数据的方法compare
    public static boolean compare(long a, long b) {
        System.out.println("...两个long...");
        return a == b;
    }
}

对象内存图

内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。Java虚拟机要运行程序,必须要对内存进行空间的分配和管理,每一片区域都有特定的处理数据方式和内存管理方式。

day06_面向对象(成员变量丶方法)

 详解

day06_面向对象(成员变量丶方法)

 查看下面代码

class Student {
    
    String name;
    int age;
    
    public void study(){
        System.out.println("学生正在学习Java...");
    }
    
    public void doHomeWork(){
        System.out.println("学生正在做作业敲代码...");
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建Student对象
        Student stu = new Student();
        System.out.println(stu);// 十六进制数地址值

        // 访问成员变量
        stu.name = "冰冰";
        stu.age = 18;
        System.out.println(stu.name+","+stu.age);

        // 访问成员方法
        stu.study();
        stu.doHomeWork();
    }
}

内存分析:如下图所示

day06_面向对象(成员变量丶方法)

 结论:

  • 只要创建对象,就会在堆区开辟一块空间(凡是new就会在堆区开辟一块新的空间),对象和对象之间的关系是相互独立的
  • 只要调用方法,就会在栈区开辟一块空间,用来执行该方法
  • 多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自对象的内存区域中,成员方法多个对象共用的一份
  • 当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的) 。只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。
上一篇:CGBTN2108-DAY06总结复习


下一篇:004、python 运算符 和 字符串操作