类与对象
3.1 概述
3.1.1 面向过程
面向过程注重过程,强调完成这个过程的具体动作。
其设计理念是自顶向下,逐步求精的。
3.1.2 面向对象
面向对象 (Object-Oriented) 注重对象,当我们拥有这个对象时,我们就拥有了这个对象所具有的一切功能。
面向对象技术最大的三个特征是:封装,继承和多态。
3.2 类和对象
3.2.1 类
类 (Class) 是 Java 程序设计语言的基础。
类似于显示生活中“种类”的概念,Java 中的类也是一种对某类事物进行抽象和归并。
我们对某类事物进行抽象分析,去粗取精,由表及里,判断出这类事物最本质的特征,并用 Java 中预定的手法进行表述,就形成了一个类。
一个类包含两大内容:属性和方法(也称“成员变量”和“成员方法”)。
成员变量和局部变量的区别
定义位置不同:
成员变量是定义在类内方法外
局部变量是定义在方法或者语句内部
作用域不同:
成员变量作用域整个类
局部变量只能在定义的方法或者语句内部使用
内部存储位置不同:
成员变量存在堆内存中,并且在堆内存中自动的赋予默认值
局部变量是存储在栈内存中,不会自动给值
生命周期不同:
成员变量是随着对象的创建而加载到堆内存中,随着对象的回收而释放;
局部变量在方法或者语句执行的时候才会创建,随着方法或者语句的结束而立即移除栈内存
3.2.2 对象
对象 (Object) 是对类的实例化。
我们可以通过某类的具体对象来进行具体操作。
使用new关键字可以创建新的对象,使用.运算符获取并使用该对象所具有的方法。
对象在程序中传递时,传递的是引用地址而不是数据本身。
3.2.3 引用
当我们使用 new 关键字创建一个对象时,这个语句可以被理解为:
Person person = new Person();等号的左边称为引用,person 是 Person 的一个具体对象,这样的一个关系称为对象引用。person 不是对象本身,而是类似一个指针,它存在于栈内存中。
等号右边是使用 new 关键字在堆内存开辟一块新空间,在该空间保存对象的各个内容。
当我们用 = 连接两端时,就是用对象引用指向堆内存中的具体对象。
也就是说,如果内存中存储的是另一块内存的起始地址(对象引用指向堆内存具体对象)就称为一个引用。Java 1.2-
但是在后续版本中, Java 对引用的概念进行了细化,它具体分为四个类型,其引用程度不断减弱:
- 强引用 (Strong Reference)
最普遍的引用。如果一个对象是强引用,则 GC 不会对它进行回收。就算内存空间不足,JVM 会选择抛出OutOfMemoryError使得程序终止而不去对其进行垃圾回收。 - 软引用 (Soft Reference)
当内存空间足够时,GC 不会对其回收。当内存空间不足的时候,GC 就会将其回收。
软引用可以实现内存敏感的高速缓存。
软引用可以和引用队列联合使用。若软引用所引用的对象被垃圾回收,JVM 就会在回收前将软引用加入到与之关联的引用队列中。
可以加速 JVM 对内存的回收速度,维护系统运行安全,防止内存溢出等问题。 - 弱引用 (Weak Reference)
弱引用的对象拥有更短的声明周期。当 GC 在扫描内存时,一旦发现了某对象是弱引用对象,则不管当前内存空间充足与否都会被回收。
弱引用也可以和引用队列联用。若弱引用的对象被垃圾回收, JVM 就会在回收前将弱引用加入到与之关联的引用队列中。 - 虚引用 (Phantom Reference)
虚引用不会决定对象的声明周期,如果一个对象只有虚引用,则它与没有任何引用一样在任何时候都可能被垃圾回收。
虚引用必须与引用队列联用。当 GC 发现一个对象具有虚引用时,就会在回收对象之前将虚引用加入到与之关联的引用队列中。
*引用队列可以提供给程序知晓马上会被回收的对象的信息,这样就可以在对象被回收前采取一些行动。
3.2.4 this
this关键字this关键字可以表述一个对当前对象自身的引用。在本类中使用
this可以调用本类的非静态方法和非静态属性。
this()语句表示在本类的构造方法中调用本类的其他的对应形式的构造函数。
必须放在构造函数的第一行。
3.2.5 super
super关键字super关键字用以表示对父类对象的引用。表示在子类中调用父类中的方法和属性。
super()语句表示子类的构造方法中,调用父类中对应形式的构造方法。
必须写在子类构造函数的第一行。
每一个子类的构造函数都直接或间接的含有
super()语句。如果父类中没有提供无参构造,那么此时子类的构造函数中必须手动添加一个
super()语句。
3.3 方法
方法 (Method) , 也称为函数。
为实现代码复用,需要将代码进行封装。这种封装的形式就是方法。
方法在定义好之后,必须明确返回值类型。若方法有明确的返回值类型,还要确保方法有返回值。
作用:
提高代码复用性。
使代码结构更加清晰。
便于模块化开发。
方法签名:一个方法由其修饰符、返回值类型、方法名和形式参数唯一确定,这一组数据称为方法签名。
定义:修饰符 返回值类型 方法名(形式参数) {...}
例如:public void method(int num1, int num2) {...}
参数传递
Java 的参数传递为值传递。也就是说,当我们传递一个参数时,方法将获得该参数的一个拷贝。
- 基本类型变量的值传递,意味着变量本身被复制,并传递给方法。方法对变量的修改不会影响到原变量。
- 引用的值传递,意味着对象的地址被复制,并传递给方法。方法根据该引用的访问将会影响对象。
3.3.1 构造方法
与类同名且没有返回值类型。
可以被重载。
构造函数中可以存在return语句,用于规避不合理的数据。
作用:用于创建对象(标识对象创建的开始和结束)
3.3.2 方法的使用
方法递归
核心:方法调用自己本身注意
需要控制好结束条件,若递归层数太深,则出现栈溢出错误。
方法重载 (Method Overload)
详见多态。方法覆盖 (Method Override)
详见多态。
注意
在传递参数的时候,对于基本类型而言,传递的实际值;对于引用类型而言,传递的是地址。
例如在传递数组对象时,只要地址不发生改变,方法中的一切变化会作用于原数组。
3.3.3 可变参数
Java 允许方法的参数列表中参数个数是不限定的。本质上是一个数组。
语法:修饰符 返回值类型 方法名(类型... 参数名) {...}
对于可变参数,可以对其传入多个/一个/不传值。
每个方法只允许定义一个可变参数,切必须放在参数列表的末尾。
3.4 代码块
3.4.1 构造代码块
定义在类内。
也称“初始化代码块”,在创建对象时执行构造方法之前先执行。
用于完成一些初始化的操作。
3.4.2 局部代码块
定义在方法或代码块中。
限制变量的生命周期和使用范围。
可以提高内存的利用率。