202402150774
目录
3.1面向对象的概念
3.1.1什么是面向对象
面向对象程序设计的思维方式是一种更符合人们思考习惯的方式。 面向对象分析问题涉及到的事物或对象,创建对应的类,分析事物的属性和行为,将这些属性和行为定义到类中,在解决问题的过程中按需创建对象,通过对象调用类中的行为,最终解决问题。
3.1.2类和对象
万物皆对象,现实中存在的任何一个具体的事物都是一个对象,比如一张桌子、一台电脑、一个人、一支笔。
将现实中一类事物抽象化,提取出这一类事物共有的属性和行为,就形成了类。类是抽象的概念,对象是具体的概念。“桌子”“椅子”“电脑”就是类,“某张桌子”“某把椅子”“某台电脑”就是对象。
再比如班上的每一位同学都是一个对象,都具备姓名、年龄、学号属性,都拥有学习、睡觉行为。而把班上的同学进行抽象,就是一个学生类。
3.1.3面向对象的特性
面向对象具有封装、继承、多态的特性,更符合程序设计中“高内聚、低耦合”的主旨,其编写的代码的可维护性、可读性、复用性、可扩展性远比面向过程思想编写的代码高,但是性能相比面向过程要偏低一些。
1.封装
指隐藏对象的属性和实现细节,仅对外提供公共的访问方式
2.继承
子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为
3.多态
指的是同一个方法调用,由于对象不同可能会有不同的行为
3.2面向对象编程
3.2.1类的定义
Java使用class关键字来定义一个类。
一个Java文件中可以有多个类,但最多只能有一个public修饰的类,并且这个类的类名必须与文件名完全一致。
类名需要符合标识符规则,并且遵循大写字母开头的驼峰规则。
类主要由变量(字段)和方法组成。
变量(字段field):
其定义格式:修饰符 变量类型 变量名 = [默认值] ;
方法(行为action):
其定义格式:修饰符 返回值类型 方法名(形参列表) {}
创建一个Student类,拥有name和age变量,以及eat()和study()方法,并且这两个方法也称作成员方法。
3.2.2对象的创建与使用
要创建一个对象,必须先有一个类,然后通过new关键字来创建一个对象。对象创建语法如下。
成员变量和成员方法隶属于对象,不同对象之间的成员变量占用不同的地址空间,互不影响。
3.2.3成员变量默认值
为一个类定义成员变量时,可以显式地为其初始化。如果不为成员变量初始化,Java虚拟机也会默认给成员变量进行初始化。下表为Java虚拟机为每种数据类型的成员变量赋予的默认值。
成员变量与上一章的局部变量不同。局部变量必须要赋值才可以使用,而成员变量即使不赋值,Java虚拟机也会默认为其赋值。
3.2.4匿名对象
通过使用new关键字来创建对象,这种对象分为两种:匿名对象与非匿名对象。何为匿名对象,何为非匿名对象呢? 匿名对象就是没有名字的对象,是定义对象的一种简写方式。
当方法的参数只需要一个对象,或者仅仅想调用一下某个对象的成员方法时,大可不必为这个对象单独创建一个变量,此时就可以使用匿名对象。
3.2.5对象内存分析
Java对象在内存中的存储
成员变量和局部变量的存储位置是不同的。尽管成员变量也可能是基本数据类型,但它的生命周期是跟随对象的,也会随着对象一并存储到堆内存中,而局部变量的基本数据类型只会存储到栈内存中。
3.3构造方法
3.3.1什么是构造方法
构造方法也称作构造器(constructor),用于给对象进行初始化操作,即为对象成员变量赋初始值。
构造方法名称必须与类名相同,并且不能定义返回值,不能出现return关键字。
Java中要求每一个类必须要有构造方法。 构造方法的调用必须通过new关键字调用,语法格式如下所示。
3.3.2构造方法的使用
当不在类中定义构造方法时,编译器会自动为类提供一个默认的无参数构造方法,一般简称为“无参构造方法”。前面通过new关键字创建Student对象时,就是在调用它默认的无参构造方法。可以在out文件夹中找到Student.class文件,在这里打开命令行执行 javap Student.class 命令,对字节码文件反编译,如图所示:反编译Student。
可以看到,Student类中有一个名为Student的方法,该方法就是编译器默认提供的空参构造方法。 而如果手动为其提供了构造方法,那么编译器就不会再为该类提供默认构造方法了。接下来给Student分别提供无参构造方法和有参构造方法,代码如下所示。
当程序没有为类定义任何一个构造方法时,只能使用系统默认的无参构造方法来创建对象;
当程序为类定义了构造方法,则只能使用定义的构造方法,不能再使用系统默认的无参构造方法。
3.3.3构造方法的重载
在 Java 中,构造方法也可以重载,构造方法重载是方法重载中的一个典型特例。当创建一个对象时,JVM 会自动根据当前对方法的调用形式在类的定义中匹配形式相符合的构造方法,匹配成功后执行该构造方法。
给Student创建多个构造方法。 演示示例代码如下图所示:
注意:当局部变量和成员变量的变量名相同时,此时编译器无法区分,应当将其中一处的变量名进行改名或者显式使用this关键字调用成员变量。
3.4this关键字
3.4.1this关键字介绍
当创建一个对象成功后,Java虚拟机(JVM)会动态地分配一个引用,该引用指向的就是当前对象,该引用称作this。用更直白地说,this关键字就是在成员方法或者构造方法中使用,用来调用当前对象的成员变量、成员方法或构造方法,它代表当前对象。
比如创建两个Student对象,分别为stu1和stu2。当stu1调用eat()方法时,eat()方法中的this就代表stu1这个对象;当stu2调用eat()方法时,eat()方法中的this就代表stu2这个对象。
3.4.2this关键字的使用
this关键字可以调用成员变量、成员方法、构造方法。
需要注意的是,成员方法中不能使用this关键字调用构造方法,只能在构造方法中使用this关键字调用其它构造方法,并且它必须在构造方法的第一行。
编写程序,定义一个坐标类(Point),用于表示二维空间中的一个坐标位置。通过坐标类的方法,实现计算两个坐标位置之间的距离。 首先定义坐标类:
3.5static关键字
3.5.1static关键字
static关键字可以用来修饰成员变量、成员方法和构造代码块。
在类中用大括号包裹起来的代码叫称作构造代码块。举例:
{
System.out.println(“构造代码块被执行了”);
}
用static关键字修饰的成员变量叫静态变量;用static关键字修饰的成员方法叫静态方法;用static关键字修饰的构造代码块叫静态代码块。
3.5.2静态变量
在类中,将与成员变量同级的用static修饰的变量称为静态变量或类变量。
静态变量优先于对象存在,随着类的加载就已经存在了,该类的所有实例共用这个静态变量,即共用同一份地址空间。
当想调用静态变量时,可以使用对象名.变量名进行调用,但不推荐,建议使用类名.变量名进行调用。
给Student类加上一个静态变量,如下所示。
3.5.3静态方法
static关键字也可以修饰方法,用static修饰的方法称之为静态方法或类方法。
静态方法同样是属于类的,优先于对象存在,调用方式与静态变量相同,也是建议使用类名.方法名进行调用。
在Student类中定义一个静态方法,如下所示。
由于静态方法是属于类的,优先于对象存在,也就是说,当调用静态方法时可能程序并没有创建这个类的对象,因此在静态方法中不存在this引用,不能使用this关键字,也不能调用成员变量和成员方法。
当一个类中几乎所有的核心方法都是静态方法时,称之为工具类。工具类中的方法都是工具性质的方法,它们的调用结果应当与对象无关,因此对于工具类,一般使用private关键字修饰它的空参构造方法,让其他类无法创建工具类的对象。
3.5.4静态代码块
在类中,与成员变量和静态变量同级,使用大括号包裹起来的代码块称作构造代码块,当构造代码块使用static关键字修饰时,称作静态代码块。
构造代码块和静态代码块都只能定义在类中,与成员变量和静态变量平级,并且可以定义多个。不同的是,构造代码块随着对象的创建而加载,每创建一个对象就会执行一次;而静态代码块随着类的加载而加载,每个类中的静态代码块只会执行一次。
当一个类中存在静态代码块、构造代码块、构造方法时,如果创建这个类的对象,它们三者的执行顺序应该是什么样的? 创建一个对象前,首先JVM会将这个类加载到方法区,当类被加载后,就会创建出它的静态变量,并执行静态代码块。之后,对象创建成功,初始化成员变量,并执行构造代码块。需要注意的是,对象其实并不是构造方法创建出来的,而是new关键字创建的。当创建了构造方法后,首先就会创建出对象,之后才会调用这个对象的构造方法。
编写一个简单的代码演示一下它们的执行流程,在此之间,在Student类中分别添加两个静态代码块和构造代码块,如下所示。
3.5.5结论
(1)同一个类中,成员变量不能赋值给静态变量,静态变量可以赋值给成员变量和静态变量。
(2)同一个类中,静态方法不能调用成员变量和成员方法,成员方法可以调用静态或非静态的方法和变量。
(3)同一个类中,静态代码块不能调用成员变量和成员方法,构造代码块可以调用静态或非静态的方法和变量。
简言之,静态的只能调用静态的,非静态的可随意调用。
3.6包
3.6.1包的概念
- 包在Java中用来管理类。开发中会遇到大量同名的类,通过包给类加上一个命名空间,很容易就能解决类重名的问题。
- 包对于类,相当于,文件夹对于文件的作用。
- Java通过package关键字声明一个包,之后根据功能模块将对应的类放到对应的包中即可。
- 包的命名遵循标识符命名规则,并且要求全部字母小写。 在企业中一般以反着写企业域名的方式命名,比如com.baidu和com.jd,需 要注意的一点是,包名不能以java开头。
- 5. 声明一个包的语法格式;
3.6.2类的访问与导包
- 一般来说,定义的类都需要定义在包下。当要使用一个类时,这个类与当前程序在同一个包中。
- 如果定义的类和当前程序不在同一个包时,使用这个类时需要导包。
- 使用import关键字导入java中的包,语法格式如下:
- 特殊情况,使用java.lang包下的类时可以省略导包。
- 通过import关键字指定要导入哪个包下的哪个类,比如import java.util.Scanner就导入了java.util包下的Scanner类,而其它包中的Scanner类则不受影响。 此外,前面使用到了String类,而该类在java.lang包下,因此可以省略导包。而上面的案例中,Student类与Demo类都是在同一个包下,也可以省略导包。 当要使用到两个名称一样的类时,就需要以包名.类名的方式使用了,包名.类名的形式也称之为一个类的全类名。