一:类和对象
Java 是一门纯面向对象的语言,在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好
1.1 什么是类和对象
那么什么是类,什么是对象呢?通俗一点理解就是,类就是一个模板,用来对一个实体进行描述,限定了对象有哪些属性和行为。我们按照这个模板来实例化出许多个对象,
在 java 中,我们描述一个对象是通过描述这个对象的属性和行为进行描述的,举个例子:当以汽车为例进行描述时,可以将汽车的属性和行为抽象为一个类的属性和方法。
属性:描述了汽车的特征 :
- 品牌:描述汽车的品牌,如“奔驰”、“宝马”等。
- 颜色:描述汽车的外观颜色,如“红色”、“白色”等。
- 型号:描述汽车的型号,如“SUV”、“跑车”等。
行为:描述了汽车能够执行的动作 :
- 加速:描述汽车加速的动作,如“踩油门加速”。
- 刹车:描述汽车刹车的动作,如“踩刹车减速停车”。
- 换挡:描述汽车换挡的动作,如“挂1挡、2挡等”。
通过定义汽车类,并在类中定义相应的属性和方法,就能够对汽车进行描述和操作。这样的描述方式能够更清楚地表示汽车对象的特征和能力,使我们可以更好地理解和模拟现实生活中的汽车行为。
1.2 类的定义格式
下面通过举例来说明类的定义:当我们描述一个狗狗的时候可以通过狗狗的名字和颜色,以及狗狗狗叫和摇尾巴的行为来进行描述,所以我们可以定义一个这样的狗狗类:
class PetDog {
// 狗的属性
public String name;//名字
public String color;//颜色
// 狗的行为
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
在这个狗狗类中:
- 属性主要是用来描述类的,属性称之为成员变量。
- 方法主要说明类具有哪些功能,称为类的成员方法。
1.3 局部变量和成员变量
注意成员变量和局部变量是两个不同的概念,成员变量是定义在类中的变量,局部变量是在方法、代码块或构造函数中定义的变量。
class VariableDemo {
// 成员变量
int memberVariable;//成员变量可以不用进行初始化
public void display() {
// 局部变量
int localVariable = 10;//局部变量则必须要进行初始化
}
}
1.4 类的实例化
我们已经有了类了,那么我们该如何通过类来实例化一个对象呢?
class PetDog {
// 狗的属性
public String name;//名字
public String color;//颜色
// 狗的行为
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
我们可以通过这行代码来完成对类的实例化
PetDog dogh = new PetDog();
new 用来创建一个空间, new PetDog 就是创建一个 PetDog 类型的空间,并且 new PetDog 会返回创建好空间的地址,而 new PetDog 后的括号则是传给构造方法的参数
dogh 是一个引用,我们通过赋值符号 = 将创建好空间的地址赋给了dogh,所以 dogh 指向了这个空间,PetDog dogh 就表示 dogh 这个引用的类型是 PetDog 的。引用的类型标志着这个引用能管理的空间就只有这么大。
下面举一个简单的代码例子来演示一下:
class PetDog {
// 狗的属性
public String name;//名字
public String color;//颜色
// 狗的行为
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
public class Main{
public static void main(String[] args) {
PetDog dogh = new PetDog(); //通过new实例化对象
dogh.name = "阿黄";
dogh.color = "黑黄";
dogh.barks();
dogh.wag();
}
}
这段代码的输出结果是:
阿黄: 旺旺旺~~~
阿黄: 摇尾巴~~~
在 java 中我们使用点号来访问对象中的属性和方法.,并且同一个类可以创建多个实例.
1.5 this 引用
首先我们来思考一下为什么要有 this 引用,下面通过一个代码来引出:
public class Person {
String name;
int age;
public void setPerson(String n, int a) {
name = n;
age = a;
}
public void printDetails() {
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
}
public static void main(String[] args) {
Person person = new Person();
person.setPerson(张三,20);
person.printDetails();
}
}
在这段代码中,我们先实例化了一个 Person 对象,接着通过 person 这个对象中的 setPerson 方法对 name 和 age 进行了初始化,接着通过 person 这个对象中的 printDetails 方法对信息进行打印,运行结果如下:
姓名:张三
年龄:20
程序此时看着没什么问题,但是万一我们不小心将 setPerson 方法错误的写成了:
public void setPerson(String name, int age) {
name = name;
age = age;
}
这样我们就分不清楚我们传入的 name 是哪个了,并且根据局部优先的原则,Java 会首先查找方法参数,然后再查找成员变量,内部的成员变量会优先于外部传入的变量, name = name 会被解析成将成员变量 name 赋值给形参变量 name,这和我们的本意相反,那么我们该如何避免这种情况呢?答案是通过 this。
this 代表着当前对象的引用,它有三个很重要的作用:
- 通过 this 区分局部变量和成员变量
- 在类中通过 this.方法名()来调用本类的成员方法
- 通过 this()来在构造方法中调用其他构造方法,并且这一行代码应该在第一行
所以我们可以对上述的代码进行改进
public class Person {
String name;
int age;
public void setPerson(String name, int age) {
this.name = name;
this.age = age;
}
public void printDetails() {
System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
}
public static void main(String[] args) {
Person person = new Person();
person.setPerson(张三,20);
person.printDetails();
}
}
1.6 构造方法
public class Person {
String name;
int age;
public void setPerson(String name, int age) {
this.name = name;
this.age = age;
}
public void printDetails() {
System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
}
public static void main(String[] args) {
Person person = new Person();
person.setPerson(张三,20);
person.printDetails();
}
}
在这段代码中,我们每创建一个对象都要通过 setPerson 这个方法来对对象进行初始化,而在 java 中,创建对象是一个很频繁的事情,难道我们每创建一个对象就要去调用一次 setPerson 方法?这是不是有点太麻烦了?
为了解决这个问题, java 给我们提供了一个方法,名为构造方法,构造方法每创建一次对象,就会为这个对象自动调用一次构造方法,所以我们就可以通过构造方法来完成对对象的初始化,所以上述代码我们可以改成:
public class Person {
String name;
int age;
public Person(String name, int age) { //构造方法
this.name = name;
this.age = age;
}
public void printDetails() {
System.out.println("姓名:" + this.name);
System.out.println("年龄:" + this.age);
}
public static void main(String[] args) {
Person person = new Person(张三,20);
person.printDetails();
}
}
构造方法的特性:
- 构造方法的名字必须与类名相同
- 没有返回值类型,设置为 void 也不行
- 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
- 构造方法可以重载,用户可以根据自己的需求提供不同参数的构造方法
注意:当一个类实例化了一个对象,那么就一定要调用一次构造方法,如果没有调用则会报错,如果用户没有定义构造方法,那么系统会默认生成一份没有参数的构造方法供我们使用,但是如果我们写了任意一个构造方法,那么系统就不会帮我们生成这个无参的构造方法了