5、面向对象基础
重点:
1、类的设计与对象的实例化
2、成员访问
3、构造方法
难点:
1、类是一个引用数据类型
2、类与类之间的相互引用
5.1、面向对象的简介
5.1.1、面向对象与面向过程
面向过程:是一种看待问题、解决问题的思维方式。着眼点在于问题是如何解决的,然后亲力亲为的解决问题。
面向对象:是一种看待问题、解决问题的思维方式。着眼点在于找到一个能够帮助解决问题的实体,然后委托这个实体来解决问题。
Java是一个面向对象的编程语言。
使用Java这门编程语言,可以更加容易的写出具有面向对象编程思想的代码。
判断题:使用面向对象的编程语言,写出的代码,一定是面向对象的代码。
错!面向对象是一种编程思想,很多新手是在用面向对象的语言,写面向过程的代码。也有很多大牛,用面向过程的语言,写面向对象的代码。
5.1.2、案例分析
把大象装冰箱。
面向过程:
1、打开冰箱门 - 我
2、把大象装进去 - 我
3、关上冰箱门 - 我
面向对象:
1、打开冰箱门 - 冰箱
2、把大象装进去 - 大象
3、关上冰箱门 - 冰箱
5.1.3、类和对象
面向对象的编程的思想,着眼点在于找到一个能够帮助解决问题的实体,然后委托这个实体来解决问题。
这里,所谓的“实体”,其实就是一个对象。
由若干个具有相同的属性和行为的对象组成的集合,称为是一个类。
类和对象的关系:
类是对象的集合,对象是类的个体。
顺丰、圆通、中通、韵达。。。。 快递类
张三、李四、王五、赵六。。。。 人类
超级英雄: 绿巨人、小蜘蛛、黑猫警长、奥特曼、葫芦娃、孙悟空
5.2、类的设计
5.2.1、类的定义
定义一个类,需要使用关键字 class
class 类名 {
// 类体
}
特殊说明:
1、一个java文件中,可以定义多个类。但是只有和文件名相同的那个类可以使用public修饰。
每一个类在编译后,都会生成一个.class字节码文件。
2、类名:是一个标识符,遵循大驼峰命名法。
3、类中是可以嵌套类,叫做内部类。
5.2.2、类中的成员定义
类中可以写什么?
使用类,来描述这个类的所有的对象共有的特征和行为。
特征:全局变量来表示,称为属性。
行为:方法来表示。
关于属性
类中的属性定义,可以赋初始值,也可以不赋值。
属性,不同于局部变量。如果没有赋初始值,有一个默认值的。
/**
* 希望使用这个类来描述人类
*/
class Person {
// 用属性来描述每一个人的特征
public String name;
public int age;
public char gender;
// 用方法来描述一个类的每一个对象的功能
public void eat() {}
public void sleep() {}
public void beat() {}
}
5.3、对象的实例化
5.3.1、对象实例化的方式
实例化对象,需要使用关键字 new
// 实例化了一个Person对象
Person xiaoming = new Person();
5.3.2、对象的内存分析
new: 在堆上开辟的空间。
Person xiaoming = new Person()
是在堆上开辟了空间,并且把这块空间的地址给xiaoming
赋值。xiaoming指向了堆空间中的某一块内存。
5.4、成员访问
在类中定义了若干个成员:包括属性和方法。所谓的成员访问,其实就是访问类中的每一个属性和方法。
成员分为静态成员和非静态成员:
使用关键字static修饰的成员,就是静态成员。静态成员,也称为 类成员。
没有使用关键字static修饰的成员,就是非静态成员。非静态成员,也称为 实例成员。
成员访问:
都需要使用 .
来访问。
5.4.1、非静态成员的访问
非静态成员,是在实例化对象的同时,开辟的空间。需要用对象访问。
5.4.2、静态成员的访问
静态成员,是在类第一次被加载到jvm内存中的时候执行,当第一次使用到这个类的时候开辟空间。静态成员访问,需要用类访问。
总结:
静态成员,属于类,需要使用类访问。
非静态成员,属于对象,需要使用对象访问。
5.4.3、当前类中的成员互相调用
- 非静态方法中,可以直接访问当前类中的静态和非静态的属性和方法。
- 静态方法中,只能直接访问当前类中的静态成员。
public class Person {
// 全局变量:有一个默认值的
public String name = null;
public int age = 0;
public static int count; // 静态属性
public void eat() {
System.out.println(name);
System.out.println(age);
System.out.println(count);
}
public void sleep() {
// 直接调用本类中的方法
eat();
show();
}
public static void show() {
System.out.println("hello world");
System.out.println(count);
}
}
在进行类的设计的时候,属性、方法到底该设置为静态还是非静态?
使用类来描述现实生活的情况,希望体现出不同对象的不同点。在进行类的设计的时候,绝大部分情况下,属性和方法都设计为非静态的。
- 静态属性:如果希望每一个对象的这个属性值都相同,可以将其设置为静态。
- 静态方法:一般情况下,设计工具类会设计为静态方法。
5.5、this关键字
5.5.1、this的基本使用
this: 用在非静态方法中和构造方法中,表示对当前对象的引用。
一个类中定义的方法的形参,名字可以和类中的属性重名。如果重名了,在这个方法中,直接使用这个标识符,访问的是形参。
这里遵循了一个“就近原则”,离谁近,访问的就是谁。而这里的就近原则指的是内存上的近。
当前对象:
- 实例方法中:谁调用这个方法,this就是谁。
5.5.2、this的省略原则
如果省略掉this之后,对于成员访问没有任何的歧义,则此时的this可以省略。
如果在一个方法中进行属性的访问,没有和属性同名的局部变量,此时访问属性的时候this就可以省略。
如果搞不清楚能不能省略,那么就不要省略。
5.6、对象的生命周期
生命周期:
一个对象从最开始的实例化完成(空间开辟完成),到最后的销毁(空间销毁),中间经历的过程,就是一个对象的声明周期。
5.6.1、构造方法的简介
也是一个方法,只不过这个方法和普通的方法有区别。
-
书写上的区别
1、构造方法没有返回值,这里的没有返回值不是指的void,而是返回值类型都不要写。
2、构造方法没有其他的修饰符。
3、构造方法的方法名必须和类名相同。
-
调用时机
构造方法,是在一个对象实例化的同时调用的。是一个对象的生命周期的开始。
5.6.2、构造方法的调用
在实例化对象的时候被调用的。
/**
* 这个就是一个构造方法
* 由于这个构造方法没有参数,因此这个方法称为无参构造
*/
public Person() {
System.out.println("无参构造执行了");
}
5.6.3、构造方法的重载
构造方法是可以重载的,只需要保证参数不通即可。区分调用不同的构造方法,通过实参来区分。
注意事项
- 如果一个类中没有写无参构造,这个类会包含一个默认的public权限的无参的构造方法,来实例化对象。
- 如果一个类中写构造方法了,则这个类将不再提供默认的构造方法。
有参构造的意义:
-
使用有参构造,大部分情况下,都是希望在实例化一个对象的同时,给这个对象的某些属性进行赋值。
this用在构造方法中,this表示要实例化的对象。
public Person(String name, int age) {
this.name = name;
this.age = age;
}
5.6.4、构造方法中调用其他的构造方法
使用this()
调用当前类中的其他的构造方法。
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String gender) {
// 调用两个参数的构造方法,给name和age赋值
this(name, age);
this.gender = gender;
}
public Person(String name, int age, String gender, int height, int weight) {
// 调用三个参数的构造方法,给name、age和gender赋值
this(name, age, gender);
this.height = height;
this.weight = weight;
}
注意事项
this()调用当前类中的构造方法,需要保证两点:
1、this()这一句话必须是方法中的第一句,前面不允许有任何的语句。
2、不允许出现循环调用
5.6.5、构造代码段(了解)
在类中,直接写一对大括号,里面的内容就是一个代码段。
非静态代码段的执行,是发生在实例化对象的时候,因此这样的代码段,被称为构造代码段。
构造代码段中的代码执行在构造方法之前。
在构造代码段中,对某些属性进行初始化的赋值,但是这个功能,和构造方法重复了。因此后面我们基本不用构造代码段,如果需要在实例化对象的同时,给某些属性进行初始化的赋值操作,更多的使用的还是构造方法。
5.6.6、静态代码段
当类第一次被加载到内存中的时候执行。
在工具类中,如果有静态的属性需要进行初始化,可以使用静态代码段。
5.6.7、析构方法(了解)
是一个对象被销毁之前,执行的最后一个方法。
@Override
protected void finalize() throws Throwable {
super.finalize();
}
5.7、类与类之间的关系
类是一种自定义的引用数据类型。可以将一个类用在另外一个类中,作为属性、参数、返回值。。。
public class Program1 {
public static void main(String[] args) {
Person xiaoming = new Person();
xiaoming.name = "xiaoming";
xiaoming.age = 20;
Dog xiaohei = new Dog();
xiaohei.name = "xiaohei";
xiaohei.age = 10;
xiaoming.pet = xiaohei;
// 设置小明的pet的信息
xiaoming.pet.name = "xiaobai";
xiaoming.pet.age = 1;
System.out.println(xiaoming.pet.name); // xiaobai
System.out.println(xiaoming.pet.age); // 1
System.out.println(xiaohei.name); // xiaobai
System.out.println(xiaohei.age); // 1
}
}
class Person {
public String name;
public int age;
public Dog pet;
public void show() {
System.out.println(this.name); // null
System.out.println(this.age); // 0
System.out.println(this.pet); // null
}
}
class Dog {
public String name;
public int age;
}
public class Program2 {
public static void main(String[] args) {
// 案例:上课了,老师让某位同学做课前分享。
Teacher t = new Teacher();
Student s = new Student();
s.name = "xiaoming";
// 老师让学生做课前分享
t.choiseStudent(s);
}
}
class Teacher {
/**
* 让某一个学生做课前分享
* @param student
*/
public void choiseStudent(Student student) {
// 学生做课前分享
student.makeShare();
}
}
class Student {
public String name;
public void makeShare() {
System.out.println("做课前分享");
}
}
2 {
public static void main(String[] args) {
// 案例:上课了,老师让某位同学做课前分享。
Teacher t = new Teacher();
Student s = new Student();
s.name = "xiaoming";
// 老师让学生做课前分享
t.choiseStudent(s);
}
}
class Teacher {
/**
* 让某一个学生做课前分享
* @param student
*/
public void choiseStudent(Student student) {
// 学生做课前分享
student.makeShare();
}
}
class Student {
public String name;
public void makeShare() {
System.out.println("做课前分享");
}
}