【Java编程】面向对象程序设计--类与对象

目录

一、如何定义类

二、成员变量与成员函数

2.1 函数是通过.运算符来调用某个对象的函数

2.2 在成员函数内部直接调用自己(this) 的成员变量和其他函数

2.3 对象初始化

三、对象交互

四、封装(访问属性)

五、包

六、类变量和类函数

6.1 类变量

6.2 类函数


一、如何定义类

与C语言明显的区别在于,Java类是“对客观世界的建模方法”。

一个类由两种东西组成:表示对象“有什么的成员变量“和表示对象“能做什么的成员函数“

类定义了对象长什么样,对象则是按照类的定义所制造出来的实体,一个类可以创建很多对象,每个对象有自己的数据。

类的定义与实例化

对象变量是对象的管理者而非所有者,所以涉及到赋值、函数参数传递和比较都与普通变量有所不同。


二、成员变量与成员函数

在没有引入类之前,变量是跟着代码走的。代码写到哪儿,变量写在哪里,那么运行的时候变量就在那儿。

现在,写在类里的成员变量,只是一个声明,变量并不在那里,变量不在类里,变量在每一个对象里。

2.1 函数是通过.运算符来调用某个对象的函数

对象名称.方法()
vm.insertMoney()

这次调用临时建立方法 insertMoney() 与 vm 之间的关系,让 insertMoney()方法内部的成员变量指的是 vm 的成员变量。

2.2 在成员函数内部直接调用自己(this) 的成员变量和其他函数

  • 函数中可以直接写成员变量的名字来访问成员变量,需要通过 this 来实现。如果调用其他函数不用加 this。
public class test {
    int price = 80;   //price1

    void setPrice(int price) {      
            this.price = price;    // 调用自己的成员变量 price,将传进去的100通过this.price赋给price1    
            System.out.println(price);
        }

    public static void main(String[] args) {
        test myTest001 = new test();
        myTest001.setPrice(100);
        }
}

this 是成员函数的一个特殊的固有的本地变量。它表达了调用这个函数的那个对象(自己知道调用哪个对象)。

定义在函数内部的变量是本地变量,定义在函数外部的变量叫成员变量

本地变量的生存期和作用域都是函数内部。成员变量的生存期是 new出一个对象后才存在。之前类只是规范。至于什么时候消失,Java有自动垃圾回收机制。成员变量的作用域是类内部(类里的成员函数可以去使用这些成员变量、成员变量初始化也会使用这些变量。

2.3 对象初始化

变量的初始化是程序安全很重要的一环。

Java提供了多种手段来保障对象创建时的初始化,包括给每个成员变量默认的“0”值、定义初始化和构造函数。

2.3.1 成员变量定义初始化

1. 成员变量在定义的地方就可以给出初始值。

2. 没有给出初始值的成员变量会自动获得 0 值,对象变量的 0 值表示没有管理任何对象,也可以主动给null。

3. 定义初始化可以调用函数,甚至可以使用已经定义的成员变量。

public class test {
    int price = 80;
    int number = f();
    float object;


    public test (int price) {
         this.price = price;
         System.out.println(price);
        }

    int f() {
        return number = 10;
    }

   int object(){
        System.out.println("object"+object);
        return 54;
    }



    public static void main(String[] args) {
        test myTest001 = new test(9);
        myTest001.object();
        System.out.println(myTest001.object());
    }
}
// 结果
9
object 0.0
object 0.0
54

一旦创建了一个对象:

a. 【构造函数 test() 】会被自动调用,记录一个参数 parameter price=9,但不进入构造函数内部。

同时,本地变量this里,会自动生成所有的成员变量 (price, number, object),并先初始化为0。

b. 程序进入【构造函数外的定义初始化】(本地变量this管理的成员变量),开始赋值。不会进入一般成员函数

除非,成员变量定义的初始化调用了其他成员函数 f(),程序才会往下进入这个普通成员函数。

c. 然后,程序【进入构造函数】将传进去的 int 9,通过 this.price 传给成员变量price,置成9。

d. 最后返回到创建对象的 new ,我们才有了【对象myTest001】(price=9, number=10, object=0.0)。

e. 程序下行一步到【调用函数】myTest001.object(),进行了打印 object 的动作。object 0.0。

f. 最后,打印 myTest001.object(),除了54的 return值外,还会有一次 object 0.0的打印。

2.3.2 构造函数

如果有一个成员函数的名字和类的名字完全相同,则在创建这个类的每一个对象的时候会自动调用这个函数-->构造函数。这个函数不能有返回类型,也不能有void。

构造函数是对象一建立就运行,给对象初始化,就包括属性,执行方法中的语句。而一般函数是对象调用才执行,用“.方法名”的方式,给对象添加功能。一个对象建立,构造函数只运行一次,而一般函数可以被该对象调用多次。

构造函数的特点:

  • 函数名与类名相同
  • 不用定义返回类型(不同于void类型返回值,void是没有具体返回值类型,构造函数是连类型都没有
  • 不可以写 return 语句(返回值类型都没有,不需要return语句)
  • 构造方法在类创建对象时,执行。普通函数不执行,除非成员变量调用了它

注意:一般函数是不能调用构造函数,只有构造函数才能调用构造函数

2.3.3 函数重载

  • 一个类可以有多个构造函数,只要他们的参数表不同。创建对象的时候给出不同的参数值(有参或无参),就会自动调用不同的构造函数。
  • 通过this()还可以调用其他构造函数,一个类里的同名但参数表不同的函数构成了重载关系

三、对象交互

面向对象程序设计的第一步,就是在问题领域中识别出有效的对象,然后从识别出的对象中抽象出类来。

一个对象可以由其他类的对象来组成,就像一个人体里面有心脏、肠胃一样。对象是由其他对象组成的,而类定义了这样的组合关系。

当一个对象里有多个对象的时候,对象和对象之间的联系紧密程度叫做耦合。对象和对象的耦合程度越紧,表现在源代码上,就是它们的代码是互相依赖、互相牵制的。

例如:创建一个类似数字时钟的程序,可以记录时间流逝。

// 画出表达两位的计数器
package Clock;

public  class Display {
    private int value = 0;
    private int limit = 0;

    public Display(int limit) {
        this.limit = limit;
    }

    public void increase() {      //这里没有循环
            value++;
            if (value == limit) {
                value = 0;
            }
        }

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        Display hour = new Display(24);
        hour.increase();
        hour.getValue();
        Display minute = new Display(60);
        minute.increase();
        minute.getValue();

    }
}

我们理想的模型,是对象和对象之间的耦合要尽可能的松,平行的对象要尽量减少直接联系,让更高层次的对象来提供通信服务。

package Clock;

public class clock {
    Display hour = new Display(24);
    Display minute = new Display(60);
//一旦我们制造出1个clock对象,我们就会制造出两个Display对象(hour,minute)
// “定义变量“,步骤和第一个类“调用“一样


    public void start (){
        while(true){
            minute.increase();
            if (minute.getValue() == 0){
                hour.increase();
            }
            System.out.printf("%02d:%02d\n",hour.getValue(),minute.getValue());
        }
    }

    public static void main(String[] args) {
        clock clock = new clock();
        clock.start();
    }
}

题目:如何做直接交互?

表示分钟的对象和表示小时的对象没有直接交互。如果想要做直接交互,让表示分钟的对象在翻转的时候直接调用表示小时的对象的那个increase函数,代码需要怎样修改?

我改了两个面向过程的方式

1. 直接用循环如下:

public class DigitalClock {

    public static void main(String[] args) {
        int hours =0;
        int minutes = 0;

        while (true) {
            System.out.printf("%02d:%02d\n", hours, minutes);
            // 每隔一分钟更新时间
            minutes++;
            if (minutes == 60) {
                minutes = 0;
                hours ++;
                if (hours == 24) {
                    hours = 0;
                }
            }
        }
    }
}

2. 弄一个 increase() 函数,调用一下。

public class DigitalClock {

        public static int increase(int hours) {
            hours++;
            if (hours == 24) {
                hours = 0;
            }
            return hours;
        }

        public static void main(String[] args) {
        int hours = 0;
        int minutes = 0;

        while (true) {
            System.out.printf("%02d:%02d\n", hours, minutes);
            minutes++;
            if (minutes == 60) {
                minutes = 0;
                hours = increase(hours);
            }
        }
    }
}

但好像总不是那么回事,题目的如何做交互,好像是在面向对象的设计方法上改的。初学还不太理解“直接交互“的意思。如果未来有大神可以指点下,或许可以醍醐灌顶一回。

    public  class DigitalClock {
    private int value = 0;
    private int limit = 0;

    public DigitalClock(int limit) {
        this.limit = limit;
    }
    public int getValue() {
        return value;
    }
    public void increase() {
        value++;
        if (value == limit) {
            value = 0;
        }
    }


    public static void main(String[] args) {
        DigitalClock hour = new DigitalClock(24);
        DigitalClock minute = new DigitalClock(60);

        while(true){
            minute.value ++;
            if (minute.getValue() == minute.limit){
                hour.increase();
                minute.value=0;
            }
            System.out.printf("%02d:%02d\n",hour.getValue(),minute.getValue());
        }
    }
}

四、封装(访问属性)

封装,就是把数据和对这些数据的操作放在一起,并且用这些操作数据掩盖起来。

数据:属性或状态

操作:函数

保证在类的设计的时候做到封装

  1. 所有的成员变量必须是private的,这样就避免别人任意使用你的内部数据;
  2. 所有public的函数,只是用来实现这个类的对象或类自己要提供的服务的而不是用来直接访问数据的。除非对数据的访问就是这个类及对象的服务。简单地说,给每个成员变量提供一对用于读写的 get/set 函数也是不合适的设计。

private 只有这个类内部可以访问:

  • 类内部指类的成员函数和定义初始化(只能用于成员变量或成员函数,成员函数里面的变量不可以)
  • 这个限制是对类的而不是对对象的(一个类的所有对象之间,可以互相访问别人的私有成员)

public 任何人都可以访问:

  • 任何人指的是在任何类的函数或定义初始化中可以使用
  • 使用指的是调用、访问定义变量

friendly / default 不带其他 public / private等:

  • 和它位于同一个包的可以访问

如果一个类前面是 public 代表任何人都可以用这个类的定义来定义变量。而且这个类必须处于一个源代码文件中,这个源代码文件的文件名是和这个类的名字相同。

编译单元(compilation unit) 一个 java文件就是一个编译单元,一个编译单元里可以有很多Java类。

当一个编译单元有不止一个类的时候,只有一个类可以是 public。即一个源代码文件里面还可以有其他类,只要不是 public ,可以不写(代表 package-private)。


五、包

当程序越来越大的时候,就会需要有一个机制帮助管理一个工程中众多的类。包(package)就是Java的类库管理机制,它借助文件系统的目录来管理类库。一个包就是一个目录,一个包内的所有的类必须放在一个目录下,那个目录的名字必须是包的名字。

5.1 创建包 project - src -new (package)

创建包的时候,包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

5.2 使用其他包内成员的方法

为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 "import" 语句可完成此功能。在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:

import package1[.package2…].(classname|*);

如果在一个包中,一个类想要使引用其他包中的类,可以使用的方法有:

  • 使用 import 关键字引入 Employee 类:import payroll.Employee
  • 使用类全名描述,例如:payroll.Employee
  • 用 import 关键字引入,使用通配符 *:import payroll.* (不推荐)

使用别人的类库部署自己的程序的时候,包的使用显得尤为重要。


六、类变量和类函数

6.1 类变量

类是描述,对象是实体。在类里所描述的成员变量,是位于这个类的每一个对象中的。

而如果某个成员有 static(静态)关键字做修饰,就可以通过类的名字或者每个对象来访问到这些类变量和类函数。它属于属于整个类,但不再属于每一个对象(对象之所以可以调用,是因为对象知道自己属于这个类)。

如果用 对象.成员变量 / 成员函数 修改了类变量,那么其他对象或者类本身调用的时候,均改变。

6.2 类函数

类函数由于不属于任何对象,因此也没有办法建立与调用它们的对象的关系,就不能访问任何非static的成员变量和成员函数了(static函数 可以调用其他 static 函数)。

static 这些成员变量,只会在类的装载(程序进入到类里面去的时候)时被初始化。static 这些成员,他们的初始化与对象的创建是没有关系的。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种面向对象编程语言,它支持面向对象程序设计(Object-Oriented Programming,简称OOP)。面向对象程序设计是一种编程范式,它将程序中的数据和操作数据的方法组织在一起,形成对象,并通过对象之间的交互来实现程序的功能。 在Java中,一切都是对象。每个对象都有自己的属性(数据)和方法(操作)。通过定义类(Class),我们可以创建多个对象,并使用这些对象来完成各种任务。 Java面向对象程序设计有以下几个核心概念: 1. 类(Class):类是对象的模板,它定义了对象的属性和方法。通过类可以创建多个具有相同属性和方法的对象。 2. 对象(Object):对象是类的实例化结果,它具有类定义的属性和方法。通过创建对象,我们可以使用类中定义的方法来操作对象的属性。 3. 封装(Encapsulation):封装是将数据和操作数据的方法封装在一起,形成一个独立的单元。通过封装,我们可以隐藏对象的内部实现细节,只暴露必要的接口给外部使用。 4. 继承(Inheritance):继承是一种机制,允许一个类继承另一个类的属性和方法。通过继承,子类可以重用父类的代码,并且可以在不修改父类的情况下扩展父类的功能。 5. 多态(Polymorphism):多态是指同一种类型的对象,在不同的情况下可以表现出不同的行为。通过多态,我们可以编写更加灵活和可扩展的代码。 Java面向对象程序设计使得代码更加模块化、可维护和可扩展。它提供了丰富的语法和特性,使得开发者可以更加方便地进行面向对象编程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值