文章目录
- 面向对象概述
- 类和对象
- 类定义和使用
- 定义
- 使用
- 对象引用
- 对象的初始化和构造
- 构造方法
- 默认初始化
- 就地初始化
面向对象概述
面向对象是一种现在主流的程序设计方法,现如今的大部分语言都支持面向对象,Java的面向对象是由C++的面向对象衍生而来,去掉了一些复杂的机制,如多继承等,使得Java的语法更加简洁明了。
但是早期,以C语言为代表的语言基本上使用的都是面向过程,而面向过程只是针对”过程“进行的,以实现基本操作,基本上不会进行扩展,并且在“过程”上维护的成本极高。
面向对象采用了模块化的思想,每个模块独立存在,可以被复用和扩展,所以面向对象成为了程序设计的主流模式。
在面向对象定义之中,也规定了一些基本的特性:
- 封装:隐藏类内部的实现细节,对外提供接口进行交互
- 继承:在原有代码基础上进行扩展
- 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
类和对象
类和对象是面向对象编程中的最基本单位。
类:是抽象的概念集合,表示具有某种共性的事物,类之中定义的是属性(成员变量)和行为(成员方法)【人类】
对象:对象是类的具象化,一种个性,是特殊的,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。【你我他】
总结:类是对象的模板,对象是类的实例。先使用类(模板、图纸)实例化出具体的对象(实例、车),才能对使用中的属性和方法。我们通过对象使用类,而类又是依赖于对象而存在的。
类:
类定义和使用
定义
在Java使用关键字class 定义一个类。语法如下:
class 类名 {
属性 (成员变量) ;
行为 (成员方法) ;
}
示例:定义一个Student类
首先抽象出学生的属性和行为:
class Studeng { // 类名使用大驼峰,单词首字母大写
// 属性(成员变量)
String name; // 姓名
String class;// 班级
int number; // 学号
int grade; // 年级
// 行为(成员方法)
public void exam() { //考试
// .......
}
public void doTask(){ // 做作业
// ......
}
public void read(){ // 读书
// ......
System.out.println("阿巴阿巴阿巴");
}
}
类定义完成之后,只是完成了图纸的绘制,想要使用还需要进行加工,实例化出对象。类是一种我们自定义的引用数据类型。示例对象的两种方式:
方式一:声明并实例化对象
类名 对象名 = new 类名 ( );
方式二:先声明,再实例化
类名 对象名 = null;
对象名 = new 类名 ();
总结:
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员
- 类是一种自定义的类型,可以用来定义变量
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
使用
引用数据类型中存储的是类型的地址,需要使用new关键字给这个地址分配内存空间。学生对象中存储的是一个内存地址,指向堆中分配给这个对象的内存空间。
实例化对象之后我们就可以使用 . . . 操作符调用对象的属性和行为。
示例:调用学生类的属性和行为
......
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "张三"; // 调用s1对象的名字属性进行赋值
s1.doTask(); // 调用s1对象的方法,张三做作业
}
如果只创建了类变量,没有引用对象那么会怎样?
......
public static void main(String[] args) {
Student s1;
s1.name;
}
Exception in thread “main” java.lang.NullPointerException 空指针异常,引用变量没有指向任何对象,但却访问了name属性。
对象引用
同一块堆内存空间,可以同时被多个栈内存所指向,不同的栈可以修改同一块堆内存的内容。简单来说,多个对象可以引用同一块内存空间。
此时,这三个对象就都可以访问
0
x
18
0x18
0x18空间内的字段。
例如:
......
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = s1;// 改变引用
Student s3 = s1;
}
此时s1 ,s2 ,s3都同时指向一块内存空间。就像上面图所画一样。
又例如:
......
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1 = s2;// ①
}
当程序执行到①时,s2原来指向的内存空间没有被任何对象所指向,会等待GC的回收。
这里有没有被对象引用,内部是使用"引用计数器"这样的技术实现的,没多一个对象引用该内存空间,计数器就加一,如果计数器为0,那么等待这块内存空间的将是被GC回收。
JVM - Java虚拟机GC,会自动回收垃圾,管理好内存,大大避免了内存泄漏(C++ 投来了羡慕的眼光~~)
垃圾:指的是没有被引用的堆内存空间,这块空间就成为垃圾,所有的垃圾将等待GC(垃圾收集器)不定期的进行回收与空间的释放。
对象的初始化和构造
构造方法
构造方法就是给类的成员进行初始化的,这是一个比较特殊的方法:
- 名字必须与类名相同
- 没有返回值类型,设置为void也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
默认初始化
局部变量不初始化编译器是会报错的,但是成员变量不初始化却并不会报错。
这是因为编译器在替我们负重前行,将类中的成员变量进行了默认初始化。
在程序层面只是简单的一条语句,在JVM层面需要做好多事情:
- 检测对象对应的类是否加载了,如果没有加载则加载
- 为对象分配内存空间
- 处理并发安全问题
比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突 - 初始化所分配的空间
即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,给成员变量对相应类型的0值。
byte | short | int | long | float | double | char | boolean | reference(引用类型) |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0L | 0.0f | 0.0 | ‘\u0000’ | false | null |
就地初始化
就地初始化就是在声明成员变量时,就直接给出了初始值
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
public Date() {
}
public Date(int year, int month, int day) {
}
public static void main(String[] args) {
Date d1 = new Date(2021, 6, 9);
Date d2 = new Date();
}
}
代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中。
本小节到这里就结束了,如果对你有帮助,请点赞,评论,转发,你的支持是我创作的动力。