目录
1. 面向对象和面向过程
面向对象和面向过程是面对问题的不同解决思路和方法。
面向过程是将问题拆解成一个个步骤,用函数详细的描述每一步骤要做什么,依次按顺序调用每个步骤去解决问题。
面向过程更注重于过程,每个步骤依次进行解决问题,处理一些简单的,线性的问题。
例如把大象放进冰箱,1.打开冰箱门,2,把大象放进去,3,关上门。这里就是三个步骤对应三个函数。
面向对象是将问题中的事物看作对象,每个对象都是唯一的,给每个对象定义属性和行为,通过对不同对象的行为进行调用,通过对象间的相互协作去解决问题。
面向对象更注重于对象,将问题的不同类型按对象进行划分,通过对象间的协作解决问题,处理一些复杂的,逻辑性强的问题。
例如把大象放进冰箱,这个问题有两个属性,1.大象,2.冰箱,这里就可以定义两个类,大象类包含一些名字,种类等属性,冰箱类包含一些开门,放东西,关门等属性和方法。通过调用冰箱类里面的方法和大象类里面的属性去解决问题。
面向对象解决问题:1.找到对象,2.创建对象,3.使用对象
2. 类与对象
2.1 什么是对象
对象就是我们平常所能看到的实际东西,都可以被描述成对象,例如说人,猫,洗衣粉等东西。
2.2 什么是类
类是用来描述对象的属性和行为的一种自定义数据类型,比如说定义一个猫类:
猫类里面包含猫的名字,年龄,品种等属性,
吃,跑,叫等行为。
一个类可以创建多个对象,比如说猫类可以创建波斯猫,花猫等对象。
2.3 类的定义
定义类需要用到一个关键字class,class是专门用来定义类的关键字。
定义类的基本格式:
class 类名{
成员变量;
成员方法;
}
类里面的内容被称为成员,又细分为成员变量和成员方法。
成员变量又叫属性,又叫字段,是定义对象的属性的。定义的位置是在类里面,方法外面,跟局部变量不同,成员变量定义的时候不需要初始化。
成员方法又叫行为,是定义对象的行为的。
注意:
- 定义类名时采用大驼峰的形式(即每个单词首字母大写)。
- public修饰的类的类名要与文件名相同,一个文件里面只能有一个public类。
下面定义一个猫类来说明:
class Cat {
//成员变量
public String catName;
public int catAge;
public String catKind;
//成员方法
public void eat() {
System.out.println("吃");
}
public void run() {
System.out.println("跑");
}
}
注意:
- 一般一个Java文件中只定义一个类。
- main方法所在的类要用public修饰。
- public修饰的类,类名要与Java文件名相同。
- 不要轻易修改public修饰类的类名。也有改的方法
修改类名的教程:
找到自己创建的Java文件右击找到Refactor,里面会有Rename和Rename File两个选项。
Rename:如果Java文件里面只有一个类,会显示这个选项,点击后可以修改创建的Java文件名和文件中的类名,两者同时修改,如下图:
Rename File:如果Java文件中有很多类,就不会显示Rename选项,只会显示Rename File选项,这个选项可以修改Java文件的名字,如下图:
2.4 类的实例化
类的实例化就是用类创建对象的过程,这里会用到new关键字来实例化对象。
//创建的猫类
class Cat {
//成员变量
public String catName;
public int catAge;
public String catKind;
//成员方法
public void eat() {
System.out.println("吃");
}
public void run() {
System.out.println("跑");
}
}
public class Test1 {
public static void main(String[] args) {
//类的实例化,创建类的对象
Cat cat = new Cat();
}
}
类也相当于一种自定义的数据类型,可以定义局部变量,定义的局部变量也是引用变量,会在堆区开辟一块空间去创建对象,里面存放的是类里面的成员变量。如下图:
接下来我们就可以用创建的引用变量去调用对象里面的成员变量和成员方法了。
通过引用变量.成员变量名 的办法来访问成员变量了,用引用变量.成员方法名 的办法来访问成员方法了。
//创建的猫类
class Cat {
//成员变量
public String catName;
public int catAge;
public String catKind;
//成员方法
public void eat() {
System.out.println("吃");
}
public void run() {
System.out.println("跑");
}
}
public class Test1 {
public static void main(String[] args) {
//类的实例化,创建类的对象
Cat cat = new Cat();
//访问成员变量
System.out.println(cat.catName);
System.out.println(cat.catAge);
System.out.println(cat.catKind);
//访问成员方法
cat.run();
}
}
这里发现成员变量没有初始化,但是编译器没有报错,为什么?
因为只有在局部变量没有初始化的时候,才会报错,而在方法里面定义的变量才被称为局部变量,成员变量定义在类里面,方法外面,不属于局部变量,未初始化不会报错,编译器对不同类型默认值为:
引用数据类型的默认值为 :null 。
注意:
- new关键字用来创建对象的实例,也就是通过类的定义来创建对象。
- 通过 . 来访问对象里成员变量和类里面的方法的。
- 同一个类可以创建多个方法。
3. this引用
this使用于成员方法里面,为了区分成员变量和局部变量,以及区分是用类实例化的哪一个对象调用了该成员方法:
//创建的猫类
class Cat {
//成员变量
public String catName;
public int catAge;
public String catKind;
//成员方法
public void setCat(String catName,int catAge,String catKind) {
catName = catName;
catAge = catAge;
catKind = catKind;
}
public void printCat() {
System.out.println(catName + " " + catAge + " " + catKind);
}
public void eat() {
System.out.println("吃");
}
public void run() {
System.out.println("跑");
}
}
public class Test1 {
public static void main(String[] args) {
//类的实例化,创建类的对象
Cat cat = new Cat();
Cat cat1 = new Cat();
//调用成员方法
cat.setCat("小花",7,"花猫");
cat.printCat();
cat1.setCat("小白",6,"波斯猫");
cat1.printCat();
}
}
上面代码中printCar成员方法中形参与实参值相同,在方法内局部变量优先,所以定义的变量被当成局部变量,没有对成员变量进行赋值,这时候就要用到this关键字。
修改代码为:
//创建的猫类
class Cat {
//成员变量
public String catName;
public int catAge;
public String catKind;
//成员方法
public void setCat(String catName,int catAge,String catKind) {
this.catName = catName;
this.catAge = catAge;
this.catKind = catKind;
}
public void printCat() {
System.out.println(this.catName + " " + this.catAge + " " + this.catKind);
}
public void eat() {
System.out.println("吃");
}
public void run() {
System.out.println("跑");
}
}
public class Test1 {
public static void main(String[] args) {
//类的实例化,创建类的对象
Cat cat = new Cat();
Cat cat1 = new Cat();
//调用成员方法
cat.setCat("小花",7,"花猫");
cat.printCat();
cat1.setCat("小白",6,"波斯猫");
cat1.printCat();
}
}
这里this的作用是:this引用的是调用该成员方法的引用变量指向的对象的地址,因此这里this也就相当于cat和cat1,引用的是创建的对象的地址,里面存放着成员变量,这样就区分了成员变量和局部变量。
上面代码main方法里面通过类创建了两个对象,调用了两次setCat和两次printCat成员方法,那编译器又是如何区分是那个对象进行的调用呢,这里也是用到了this关键字的。
其实在调用成员方法时候,编译器会隐藏的在第一个位置传一个参数,就是创建的引用变量,传过去的是引用变量里面存的对象的地址,这样编译器就可以区分是哪个引用变量使用的成员方法了。
如下代码书写也可以,因为编译器隐藏将调用该成员方法的引用变量当作参数传给this。
public void setCat(Cat this,String catName,int catAge,String catKind) {
this.catName = catName;
this.catAge = catAge;
this.catKind = catKind;
}
总结:
- this的类型是:哪个引用变量调用的成员方法的这个引用变量的类型。
- this只能在成员方法中使用。
- 在成员方法中this只能引用当前引用变量指向的对象,不能再引用其他对象。
- this是成员方法的第一个隐藏参数,接收的是使用该成员方法的引用变量存的对象的地址。
this的三种用法:
- 可以访问当前对象的成员变量。
- 可以访问当前对象的非静态的成员方法。通过 . 成员方法名();调用
- 可以访问当前对象的构造方法。通过this();调用,在调用时候需要将调用构造方法的语句放在方法中的第一行。
4. 构造方法
构造方法是一种特殊的成员方法,它不能有返回值,方法名必须跟所在的类的类名相同,构造方法支持方法的重载,分为带参数的和不带参数的构造方法。
作用:是在实例化对象的时候初始化对象里的成员变量。
下面代码创建了两个构造方法,两个都是对成员对象进行初始化。
class Cat {
public String catName;
public int catAge;
public String catKind;
//构造方法
public Cat() {
this.catName = "小花";
this.catAge = 7;
this.catKind = "花猫";
}
public Cat(String catName,int catAge,String catKind) {
this.catName = catName;
this.catAge = catAge;
this.catKind = catKind;
}
}
而构造方法在执行下面这条语句时进行调用。下面是实例化对象的语句。
Cat cat = new Cat("小花",7,"花猫");
如果没有编写构造方法,编译器会自己隐藏设置一个构造方法进行调用,如下:
public Cat() {
}
在构造方法中可以使用this关键字调用其他的构造方法:
public Cat() {
this("小花",7,"花猫");
}
public Cat(String catName,int catAge,String catKind) {
this.catName = catName;
this.catAge = catAge;
this.catKind = catKind;
}
idea继承开发环境支持快捷创建构造方法 ,方法如下:
最后创建成功下面的构造方法:
5. 成员变量的初始化
5.1 默认初始化
默认初始化就是在创建成员变量时没有对成员变量初始化,则编译器会默认初始化值,如下图:
不同的类型初始化不同的值。
那为什么成员变量不初始化不会报错呢?
这里就需要分析一下类的实例化这条语句了:
Car car = new Car();
这条语句是为一个Cat类实例化成对象的语句,这条语句做了一下几件事:
1. 检测对象对应的类是否被加载,没有加载则需要加载。
意思是:.java文件是源代码文件,经过javac命令编译成.class文件是字节码文件,再经过java命令将.class文件放到JVM中解析成class对象。而将.class文件通过Java命令放到JVM中的过程称为 加载。
也就是检测.class文件是否放到JVM中。
2. 为对象分配内存空间
意思是:为解析成的class对象,在堆区分配内存空间。
3. 处理并发安全问题
意思是:多个线程同时为对象申请空间时,防止申请的是同一块空间。
4. 初始化所分配的空间
意思是:申请好对象空间后,为空间里的成员变量对应类型的值。也就是默认初始化。
5. 设置对象头信息
6. 调用构造方法,为每个成员变量赋值。
如果自己没有写构造方法,则编译器会隐藏生成一个无参数的空的构造方法。
5.2 就地初始化
就地初始化就是在创建成员变量时,直接对成员变量进行初始化。如图:
class Cat {
String name = "小花";
int age = 8;
String kind = "花猫";
}
5.4 构造方法初始化
构造方法的作用就是为成员变量进行初始化。