欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java从零开始 第6讲 类与对象

程序员文章站 2022-03-03 16:09:36
...

什么是面向对象

面向对象(Object Oriented)是一种抽象的思考方法,并不拘泥于计算机技术。

面向过程(C语言就是面对过程的语言),关注的是执行的过程;而面向对象,则是关注具备执行该过程的对象。从面向对象到面向过程,是在思想上从执行者到指挥者的转变。
以上的概念可能不好理解,让我们用一个例子来说明:

小明开了一家杂货铺,这时有人来买东西

面向过程:购买者说想要一包薯片,小明说价格,付钱,小明给他薯片。
面向对象:小明招聘一个收银员,教他如果购买者想要买一包薯片,就说出薯片的价格,付了钱之后给他薯片

此时看来,面向对象似乎比面向过程更复杂,但是当我们更改一下例子,小明开了一家连锁杂货铺,分布在全国各地,开了数百家,这时小明还能面向过程吗?

在代码的世界也是如此,在少量的代码时,面向过程更简单,但是当代码量变大,重复过程变多的时候,面向对象则是更好的选择。

面对对象的思想从概念上可以分为三类:

  • OOA:面对对象分析,Object Oriented Analysis
  • OOD:面对对象设计,Design
  • OOP:面对对象编程,Programming

面对对象也有三个主要特征:封装性,继承性,和多态性(会在以后小节中详细讲解)

类与对象

类(class)表示一个共性的产物,是一个综合特征的集合;而对象(object)则是一个单独的个体,对象的特征是个体的特征。

让我们用一个例子来说明:人类即是一个类,用来描述所有的人,你可以说人类是哺乳动物,是灵长类动物,大多有一双眼睛,两条腿,这些就是人类的特征。而人类中的一个对象就是一个单独的人,小明就是人类的一个对象,小明符合人类的特征,但可能还有自己特殊的特征,例如小明长得很帅,小明身高八尺有余,这些都是小明自己的特征,而不是人类的特征。

一个类必须通过对象才可以使用,但是对象的所有操作都需要在类中定义。类由属性和方法组成,属性就相当于类的特征,方法则相当于对象可以进行的行为。

让我们同样用人类来举例:人类的属性就是人是哺乳动物,是灵长类动物,方法则包括吃饭,说话,睡觉。当你想要使用这些方法时,你不能直接用类,而是需要一个对象,比如小明吃饭,小明说话,而且你创建的对象小明一定会满足人类的属性,即小明一定是哺乳动物,是灵长类动物。

特别提示:其中用类创建对象的过程被称为实例化instantiation,在之前的输入中曾经使用过)

类与对象的创建

class类一般通过如下方式定义


class 类名称{
    成员属性;
    成员方法;
}

让我们看看我们最早写的第一个程序Hello World


public class HelloWorld {

    public static void main(String[] args){

        System.out.println("Hello World!");

    }
}

其中不难发现我们定义了一个类,类的名字叫做HelloWorld,且类的前面有一个public来修饰(目前阶段仅了解,你只需要知道,一个java文件中可以存在若干个类,但只能存在一个public类,且public类的类名需要跟java文件名一样),类中没有成员属性,存在一个成员方法,方法名为main(为程序的入口方法)。

现在让我们目光锁定到方法上,类中的方法通过如下形式定义


返回值类型 方法名称(形式参数列表){
    方法体;
    return 返回值;
}

其中,返回值类型为需要返回的值的类型,方法名称就是调用该方法需要使用的名称,形式参数列表就是该方法需要传入的参数的列表。

让我们用一个简单的类来举例:


class Preson{// 直接放在public类下面

    String name;
    int age;
    int height;// 这里是成员属性

    // 以下是三种方法
    String getName(){
        return name;// 直接返回成员属性name
    }
    
    int getBirthYear(int currentYear){
        return currentYear - age;// 传入的参数可以直接使用
    }
    
    void say(){// void的意思即为不返回任何参数
        System.out.println("我叫" + "name");
    }// 但是在void中可以使用return;意为将此方法结束
}

特别提示:当然你也可以直接在public类中定义方法,这些方法不需要实例化即可直接使用)

注意,想要使用这个类,还需要创建这个类的对象,即实例化。让我们回到public类当中,实现代码如下


public class ObjectOriented {

    public static void main(String[] args) {
        Person person = new Person();// 实例化该对象,命名为person
        // 之后只要与Person类相关,都需要使用person.xxx
        // 可以用此方法创建person1,person2....personN,他们互不干扰
        // 通过Person person2 = person;可以

        person.name = "小明";
        person.age = 8;
        person.height = 158;// 定义成员变量
        
        String name = person.getName();// 调用方法
        System.out.println(name);
        
        System.out.println(person.getBirthYear(2020));// 传入参数2020
        
        person.say();
    }

}



运行结果:
小明
2012
我叫小明

Process finished with exit code 0


类与对象的存储

在Java中,所有数据的存储都是自动的,即你不能手动更改各种数据被存储的位置。

Java中存储数据的位置被分为三块,栈内存,堆内存,和方法区。

其中方法区就是用来存储所有类的信息,以及其中的成员方法,静态的变量(static)和常量(final)也会被储存其中。

栈存储特点是先进后出,内存的区域一般比较小,但是栈的优点是存取速度很快,所以一般基本数据类型的数据和引用数据类型的引用会被存在栈中。

堆存储则是先进先出,内存的区域比较大,一般用于存放类的对象。

(这一部分内容虽然很难,看起来对编程似乎也没有帮助,但是理解之后能够对学习之后的内容很有帮助)

类与对象的更多操作

类的构造方法

构造方法,通常用于对象初始化,在对象被创建时,自动调用,所有类需要包含一个构造方法,构造方法的定义如下:
特别提示:如果没有自行编写一个构造方法,编译器会自动生成一个空的构造方法)


class Person{

    Person(){}
}

构造方法需要和类同名,可以传入参数,也可以在其中加入任何代码(就像一个自动执行的方法)


// 如果你这样定义构造方法
Person(String name){
    System.out.println(name);
}

// 则你在调用时需要
Person person = new Person("小明");

方法的重载

一个类中定义的方法是允许重载的,重载即不同的方法使用相同的方法名称。
但是重载也必须满足以下条件:

  • 方法名称相同
  • 参数列表的长度 参数列表类型 参数顺序不同
    特别提示:与返回值,和方法里面的语句无关)

// 在同一类Person中
    String getName(){
        return name;
    }

    String getName(String name){
        return name;
    }

    String getName(String firstName, String lastName){
        return firstName + lastName;
    }


// 可以通过如下方法依次调用
Person person = new Person();
String name = person.getName();
String name = person.getName("小明");
String name = person.getName("小", "明");


在调用重载的方法时,会根据参数传入的情况自动选择使用的方法。

构造方法也能进行重载

匿名的对象

所谓匿名的对象,即为创建对象时不命名该对象,让我们通过代码来说明


// 使用之前的getName方法
    String getName(){
        return name;
    }
 
 
 // 可以通过如下方式匿名调用getName方法
 new Person();// 匿名对象只会自动调用构造方法
 System.out.println(new Person().getName());// 直接输出
 String name = new Person.getName();// 新建一个变量用于存储
 

匿名调用的优点是节约内存空间,代码看起来也更整洁,缺点就是构建的对象只能使用一次,无法再进行调用。

练习使用

此部分内容比较多,对于初学者来说并不简单,通过小练习能帮助理解这一部分内容

请定义并测试一个代表员工的Employee类。它的属性包括“员工姓名”、 “员工号码”、“员工基本薪水”、“员工薪水增长率”;他的方法包括“构 造方法”、“获取员工姓名”、“获取员工号码”、“获取员工基本薪水”、 “计算薪水增长额”及“计算增长后的工资总额”。

答案代码如下(查看前至少先进行思考):


public class OOPBasic {
    public static void main(String[] args) {
        Employee employee = new Employee();
        employee.name = "大明";
        employee.idNumber = 6666;
        employee.salary = 10000;
        employee.salaryIncreaseRate = 0.01f;

        System.out.println(employee.getName());
        System.out.println(employee.getIdNumber());
        System.out.println(employee.getSalary());
        System.out.println(employee.calculateIncreaseAmount());
        System.out.println(employee.calculateSalary());
    }
}

class Employee{
    String name;
    int idNumber;
    float salary;
    float salaryIncreaseRate;

    Employee(){}

    String getName(){
        return name;
    }

    int getIdNumber(){
        return idNumber;
    }

    float getSalary(){
        return salary;
    }

    float calculateIncreaseAmount(){
        return salary * salaryIncreaseRate;
    }

    float calculateSalary(){
        return salary * (1 + salaryIncreaseRate);
    }
}


运行结果:
大明
6666
10000.0
100.0
10100.0

Process finished with exit code 0

转载请注明出处