面向程序对象
面向对象基础
文章目录
1.面向对象的三大特征
- 封装
- 继承
- 多态
2.类
类的定义:具有相同的状态和相同的行为的一组对象的集合。
类是对象的模板,对象是类的具体实例。
- 组成
类有字段和方法两部分构成的,假如描述猫类,猫的属性包括“颜色”,“品种”。类的方法包括打印动物吃啥,打印动物在干啥。
面向对象设计的过程就是抽象的过程,也是设计类的过程,一般分为三步完成。
- 发现类,类定义了对象将会拥有的特性(字段)和行为(方法)。
- 发现类的字段,对象所拥有的特性在类中的表示称为类的字段。
- 发现类的方法,对象执行的操作称为类的方法。
-
类的定义
定义类就是定义了一个新的数据类型,这个数据类型就是类名。
Java的数据类型有基本数据类型和引用数据类型(类,接口,枚举,数组)
public class Cat{
public String color;//类的字段声明(属性)
public String breed;//类的字段声明(属性)
public void eat(){
System.out.println("猫猫正在吃鱼");
}//类的方法声明(行为)
}
- 访问修饰符如public,private等是可选的,具体可以看后面的文章。
- class是声明类的关键字
- 类名的命名规则使用帕斯卡命名法,类名首字母大写
- 类的字段
字段使用变量表示
访问修饰符 数据类型 字段名;//见上面的表示
- 访问修饰符是可选的。
- 除了访问修饰符外,其他部分与定义变量相同。
3.创建对象
类是一类事物的集合和抽象,代表着这类事物共有的字段和行为。一个对象称为类的一个实例,是类一次实例化的结果。
Cat cat = new Cat();//创建了一个猫类的具体对象
- new是关键字,称为实例化。
- 左边的类名为对象的数据类型。
- 右边的类名( )称为类的构造方法。
- 使用对象
在java中,要引用对象的字段和方法,需要使用成员运算符“ . ”。
对象名.属性 // 引用对象的字段
对象名.方法名() // 引用对象的方法
4.对象在计算机中的执行原理
面向对象的代码执行原理和数组的执行原理非常类似
Cat cat = new Cat();这句话的原理如下
- Cat cat表示的是在栈内存中,创建了一个Cat类型的变量,变量名为cat
- new Cat()在堆内存中创建一个对象,而对象中包含猫的属性名和属性值,同时系统会为这个Cat对象分配一个地址值0x4f5656
- 接着把对象的地址赋值给栈内存中的变量cat,通过cat记录的地址就可以找到这个对象
- 当执行cat.color=“花色”时,其实就是通过cat找到对象的地址,再通过对象找到对象的color属性,再给对象的color属性赋值为花色。
举个例子
5.对象的构造和初始化
在说明了一个引用后,要调用 new 为新对象分配空间,也就是要调用构造函数。在 Java 中,使用构造函数(constructor,也称为构造方法)是生成实例对象的唯一方法。在调用 new 时,既可以带有变量,也可以不带变量,这要视具体的构造方法而定。例如,在程序中可以写:new Button(“Press me”)。这里,Button()就是这个类的构造方法,括号中的字符串是参数值。系统根据所带参数的个数和举型,调用相应的构造方法。调用构造方法时,步骤如下:
(1)分配新对象的空间,并进行默认的初始化。在 Java 中,这两步是不可分的,从可确保不会有没有初值的对象。
(2)执行显式的成员初始化。
(3)执行构造方法,构造方法是一个特殊的方法。
成员变量
-
成员变量的作用域
类中的字段是直接定义在类的内部、方法的外部的变量,称作成员变量。Cat类中的color,breed既不属于eat( )方法,也不属于catchMouse( )方法,而是属于Cat类本身的字段,它们都是Cat类的成员变量,成员变量的作用域是整个类。当定义一个类的成员变量时,可以选择在定义时进行初始化。这样做可以为成员变量指定一个默认值。举个例子,在Java中,你可以在定义一个Cat类时将color成员变量初始化为"花色",以表示颜色默认为"花色“
-
显式成员初始化
如果在成员说明中写有简单的赋值表达式,就可以在构造对象时进行显式的成员初始化。
-
局部变量的作用域
局部变量就是定义在方法内部的变量。eat( )方法中的变量就是局部变量,局部变量只能在方法内部使用。
-
成员变量与局部变量的区别
作用域不同。局部变量的作用域仅限定于定义它的方法,在该方法外无法被访问。成员变量的作用域是在整个类内,所有的成员方法都可以使用它。如果访问权限允许,还可以在类外部使用成员变量。初始值不同。对于成员变量,如果在类定义中没有给它赋予初始值,Java会给它赋一个默认值,byte、short、int、long类型的默认值是0,boolean类型的默认值是false,char类型的默认值是’\u0000’(空字符),float、double类型的默认值0.0,引用类型的默认值是null。但是java不会给局部变量赋初始值,因此变量在使用前必须初始化
6.类和对象的一些注意事项
1.一个代码文件中,可以写多个class类,但是只能有一个是public修
饰,且public修饰的类必须和文件名相同。
//public修饰的类Demo1,和文件名Demo1相同
public class Demo1{
}
class Student{
}
2.对象与对象之间的数据不会相互影响,但是多个变量指向同一个
对象会相互影响。
如下图所示,s1和s2两个变量记录的是同一个对象的地址值,s1修改对象的属性值,再用s2访问这个属性,会发现已经被修改了。
7.构造器
-
什么是构造器?
构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相同。如下图所示:下面有一个Student类,构造器名称也必须叫Student;也有空参数构造器,也可以有有参数构造器。
- 在创建对象时,会调用构造器。也就是说 new Student() 就是在执行构造器,当构造器执行完了,也就意味着对象创建成功
- 当执行 new Student(“播仔”,99) 创建对象时,就是在执行有参数构造器,有参数构造器执行完,就意味着对象创建完毕了。
- 关于构造器的特点,我们记住一句话:new 对象就是在执行构造方法
- 构造器的注意事项
1.在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
2.一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构造器。
1.什么是构造器?
答:构造器其实是一种特殊的方法,但是这个方法没有返回值类型,方法名必须和类名相同。
2.构造器什么时候执行?
答:new 对象就是在执行构造方法;
3.构造方法的应用场景是什么?
答:在创建对象时,可以用构造方法给成员变量赋值
4.构造方法有哪些注意事项?
1)在设计一个类时,如果不写构造器,Java会自动生成一个无参数构造器。
2)一定定义了有参数构造器,Java就不再提供空参数构造器,此时建议自己加一个无参数构 造器
8.this关键字
this就是一个变量,用在方法中,可以拿到当前类的对象。
public class Cat {
private String color;
private String breed;
public void eat(){
System.out.println(color+"的"+breed+"正在吃鱼");
}
public void catchMouse(){
System.out.println(color+"的"+breed+"正在逮老鼠");
}
public Cat(String color,String breed){
this.color=color;
this.breed=breed;
}
}
使用this调用重载的构造方法,只能在构造方法中使用,且必须是构造方法的第一条。
2.区别局部变量和成员变量this.字段名指的是成员变量
3.可以调用成员变量方法
9.static关键字
static关键字是静态的意思,是Java中的一个修饰符,可以修饰成员方法,成员变量
使用
有static修饰的变量叫做类变量(static变量);没有static修饰的变量叫做实例变量(属性)
实例变量不能直接使用类名.属性名调用,static变量可以。
实例变量只能使用对象调用,类变量可以使用类名调用,也可以使用对象调用实例变量各个对象私有,static各个对象共享
实例方法中可以直接使用实例变量和static变量;static方法中不能直接调用实例变量,也不可以使用this
static方法可以使用对象调用,也可以使用类调用;实例方法只能被对象调用
没有static声明的成员是实例成员属于对象,只能对象调用
有static声明的成员都属于类,可以使用类调用,也可以使用对象调用
区别
有static的成员属于类,没有static的成员属于对象(虽然static成员也可以被对象调用,但是不推荐这样使用)
在static方法中不能直接调用实例的成员,反之可以
实例方法中可以使用this关键字,static方法不行
实例方法之间可以直接相互调用,static方法间也可以直接相互调用;实例方法
可以直接调用static方法
static成员的初始化在类被加载的时候;而实例成员在对象创建的时候初始化
代码块
实例代码块
{
}
-
解决构造方法中重复执行代码
-
想要在创建对象时执行的代码都可以写在实例代码块中,每次创建对象都会执行
-
实例代码块在构造方法执行前执行
-
一个类中可以有0个或多个实例代码块
-
多个代码块按照声明顺序执行
static代码块
static{
}
-
和实例代码块类似,只不过static代码块是在类第一次被加载的时候执行一次
-
一个类就可以有多个static代码块
-
多个代码块按照声明顺序执行(谁在前谁先执行)
对象初始化顺序
-
类第一次被加载时,初始化static成员
-
static代码块
-
初始化实例成员
-
实例代码块
-
构造方法
静态成员与实例成员的区别
- 静态成员是类的成员,实例成员是对象的成员。静态成员是在类加载时初始化,只有一个副本,可以被类的所有对象共享;实例成员是在对象创建时初始化,每个对象都有自己的一份。
- 静态成员可以直接通过类名访问,不需要创建对象;实例成员需要通过对象来访 问 。 例 如 , 静 态 变 量 可 以 使 用 类 名 . 变 量 名 的 方 式 访 问 , 例 如ClassName.staticVariable;实例变量需要使用对象名.变量名的方式访问,例如obj.instanceVariable
- 静态成员可以在静态初始化块中初始化,实例成员需要在构造函数中初始化。静态成员适合存储类级别的信息,例如类的常量、类方法、类变量等;实例成员适合存储对象级别的信息,例如对象的状态、对象属性等。在编写Java程序时,需要根据需要选择合适的静态和实例成员,以实现代码的高效和可维护性
对象数组
对象数组的操作和基本数据类型的数组是一样的,区别在于对象数组的每一个元素都是一个对象。
public static void main(String[] args) {
Student stu1 = new Student("万叶", 89, 90, 91);
System.out.println(stu1.sum);
Student stu2 = new Student("魈宝", 97, 81, 81);
Student stu3 = new Student("可莉", 90, 71, 92);
Student stu4 = new Student("琴妈", 68, 89, 78);
Student[] students = {stu1, stu2, stu3, stu4};
// 按照学生的数学成绩降序排序
// int[] arr = {}; arr[0] arr[1]
for (int i = 0; i < students.length - 1; i++) {
for (int j = 0; j < students.length - 1 - i; j++) {
if (students[j].english < students[j + 1].english) {
Student temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
}
for (Student student : students) {
System.out.println(student);
System.out.println(student.info());
}
}
10.包
包的作用
- 存放类:包中能够存放类,易于找到和使用相应的类文件。
- 防止命名冲突:Java中只有在不同的包中的类才能重名。不同的程序员命名同名的类名在所难免,有了包类就容易管理了。A程序员定义了类Sort,封装在a包中,B程序员定义了类Sort,封装在b包中。在使用时,为了区别A程序员和B程序员定义的Sort类,可以通过包名区分开来,如a.Sort和b.Sort分别对应A程序员和B程序员定义的类。
- 包允许在更广的范围内保护类、数据和方法。根据访问规则,包外的代码有可能不能访问该类。
package 包名;
package是关键字
-
包的声明必须是Java源文件中的第一条非注释性的语句,而且一个源文件只能有一个包声明语句,设计的包需要与文件系统结构相对应。因此,在命名包时要遵守以下编码规范。
-
包名一般是公司域名去掉www后倒置+项目名+模块/功能用点.分隔
-
包实际上是一种访问控制机制,通过包来限制和制约类之间的访问关系
-
在一个类中使用非本包中的类或者非java.lang包下的类时需要声明其在哪个包内
-
使用时写类的全限定名:java.util.Scanner,每一处都要写
-
使用import将类导入进来,import java.uti.Scanner
声明包的含义是声明当前类所在的包。
导入包的含义是声明当前类要使用到的其他类所在的包。
使用非同包下的类需要先导包或者使用全限定类名
同包下或子包下的类不需要导包
java.lang包下的类不需要导包
封装
- 合理隐藏,合理暴露。
封装,就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理数据的方法,都设计到一个对象中去。
类和类成员的访问控制
包实际上是一种访问控制机制,通过包来限制和制约类之间的访问关系。访问修饰符也同样可以限制和制约类之间的访问关系。
Java中的封装是通过访问修饰符实现的。访问修饰符有3个(4种),分别是public、protected、package-access(包访问修饰符)、private。
- public访问修饰符
被public修饰的成员变量和成员方法可以在所有类中访问。所谓在某类中访问某成员变量是指在该类的方法中给该成员变量赋值和取值。
- protected访问修饰符
被protected修饰的成员变量和成员方法可以在声明它的类中访问,在该类的子类中访问,也可以在与该类位于同一个包中的类访问,但不能在位于其它包的非子类中访问。
- package-access(包访问修饰符)
缺省指不使用权限修饰符。不使用权限修饰符修饰的成员变量和成员方法可以在声明它的类中访问,也可以在与该类位于同一个包中的类访问,但不能在位于其它包的类中访问。
- private访问修饰符
private修饰的成员变量和成员方法只能在声明它们的类中访问,而不能在其它类(包括子类)中访问。
封装在代码中的体现
Java中封装的实质就是将类的状态信息(成员变量)、方法等隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息(成员变量)的操作和访问。在Java中,可以使用访问修饰符来控制类中的数据和方法的访问级别,从而实现封装。
封装反映了事物相对的独立性,有效避免了外部错误对此对象的影响,并且能对对象使用者由于大意产生的错误操作起到预防作用。同样面向对象编程提倡对象之间实现松耦合关系。
封装的优点包括:
- 防止外部直接访问类的内部数据,可以保护数据的安全性。
- 通过限制外部访问,可以更好地控制数据的正确性和完整性。
- 可以隐藏类的实现细节,使得类的用户不需要了解类的内部实现细节,只需要知道如何使用类提供的接口。
这里需要用到一个修饰符,叫private,被private修饰的变量或者方法,只能在本类
中被访问。
设置getter/setter方法
为字段添加getter/setter方法。在Java中,getter和setter方法是用于访问和修改对象的
私有字段(属性)的常用约定。它们遵循一定的命名规则和编码惯例。以下是常见的
getter和setter方法的规则:
Getter方法
命名规则:使用属性名前加上"get"作为方法名前缀,属性名的首字母通常大写。
返回类型:通常与属性的类型相同。
方法体:直接返回属性的值。
Setter方法
命名规则:使用属性名前加上"set"作为方法名前缀,属性名的首字母通常大写。
参数:通常只有一个参数,参数类型与属性的类型相同。
方法体:将传入的参数值赋给属性。
布尔类型属性的Getter方法:
命名规则:使用属性名前加上"is"作为方法名前缀,属性名的首字母通常大写。
返回类型:通常是布尔类型(boolean)。
方法体:返回属性的值。
成员变量和局部变量的区别
tter/setter方法。在Java中,getter和setter方法是用于访问和修改对象的
私有字段(属性)的常用约定。它们遵循一定的命名规则和编码惯例。以下是常见的
getter和setter方法的规则:
Getter方法
命名规则:使用属性名前加上"get"作为方法名前缀,属性名的首字母通常大写。
返回类型:通常与属性的类型相同。
方法体:直接返回属性的值。
Setter方法
命名规则:使用属性名前加上"set"作为方法名前缀,属性名的首字母通常大写。
参数:通常只有一个参数,参数类型与属性的类型相同。
方法体:将传入的参数值赋给属性。
布尔类型属性的Getter方法:
命名规则:使用属性名前加上"is"作为方法名前缀,属性名的首字母通常大写。
返回类型:通常是布尔类型(boolean)。
方法体:返回属性的值。