Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),与C语言不同,C语言是一门面向过程的语言。面向对象程序设计与面向过程的语言在思维方式上存在这很大的差别。
一、什么是面向过程,什么是面向对象
1.面向对象和面向过程的区别
就拿洗衣服来说
传统的方式是这样洗的:
这个方式注重的是洗衣服的过程,一环扣着一环
如果按照这种方式写代码,拓展和维护会成为一个难题。
按照现在的洗衣方式:
现在的洗衣方式注重的是对象与对象之间交互的过程,总共有衣服、洗衣粉、洗衣机三个对象,只要将衣服和洗衣粉到入洗衣机,按下开关即可。
这就是以面向对象的方式进行处理,不关注过程,只关注对象与对象之间的交互。
二、类和对象
1. 类
1.1 什么是类
《Java核心技术》是这样描述类的:
类(class)是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的模具,将对象想象为小甜饼。由类构造(construct)对象的过程为创建类的实例。
在我们以前所学到的,Java中提供了几千个类供我们使用,但是我们还是需要自己创建一些自己的类。
1.2 如何创建自己的类
这是类的模板,类中包含类的成员属性和行为
class ClassName {
fifield ; // 字段 ( 属性 ) 或者 成员变量
method ; // 行为 或者 成员方法
}
依照模板创建一个狗类
class Dog {
public String name;
public int age;// 字段 / 成员变量 / 属性
public void bark() {
System.out.println(name + "汪汪叫!");
}
public void eat() {
System.out.println(name + "正在吃东西");
}// 行为 / 成员方法
}
注意,类名统一采用大驼峰的形式
2. 对象
2.1 类的实例化
定义了一个类之后,要如何去使用它呢?
上面讲到,类就像是一块模板,我们可以通过模板,来实例化出一个对象,就拿上面的狗类来实例化一只狗
Dog dog = new Dog();
我们实例化的狗,拥有自己的属性(姓名、年龄...),拥有自己的行为(叫、吃东西...)
如何定义实例化对象的属性
通过 对象.成员变量 来给成员赋值
dog.name = "小白";
dog.age = 5;
**如何使用成员方法 **
通过 对象.成员方法 来使用
dog.bark();
dog.eat();
就能得到如下结果
注意:上述的成员属性以及成员的方法需要类有公开的接口才能够访问,上面定义的成员属性和变量都是使用public修饰,所以在主函数中能够访问
3. 类和对象之间的关系
类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
类是一种自定义的类型,可以用来定义变量。
一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。
三、this引用
在实际练习的过程中,会开放接口去设置成员变量和得到成员变量,但是有时候往往会出现问题,如下举个例子
public void setName(String name) {
name = name;
}
public void setAge(int age) {
age = age;
}
当我们开放这样的接口去给成员变量去赋值的时候
dog.setName("小白");
dog.setAge(5);
执行如下代码
System.out.println(dog.name);
System.out.println(dog.age);
就会出现以下结果
可以看出,我们明明通过set()方法来给变量赋值,但是变量的值还是初始值
是因为
我们在定义set方法的时候,将形参的命名写成了与成员变量相同,导致了这个函数执行的是将自己的形参赋值给形参,从而不会影响到成员变量
这时,该如何解决问题呢?
Java中提供了 this 引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
this引用的特性:
this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
this只能在"成员方法"中使用
在"成员方法"中,this只能引用当前对象,不能再引用其他对象
this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法 对象的引用传递给该成员方法,this负责来接收
所以我们可以将上述set函数改造一下
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
得到结果
到目前为止,狗类的全部代码如下:
class Dog {
public String name;
public int age;// 字段 / 成员变量
public void bark() {
System.out.println(name + "汪汪叫!");
}
public void eat() {
System.out.println(name + "正在吃东西");
}// 属性 / 成员方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Dog dog = new Dog();
// dog.name = "小白";
// dog.age = 5;
// dog.bark();
// dog.eat();
dog.setName("小白");
dog.setAge(5);
System.out.println(dog.name);
System.out.println(dog.age);
}
}
四、对象的构造及初始化
1. 初始化对象
在Java中,变量未初始化是无法通过编译的
public static void main(String[] args) {
int a;
System.out.println(a);
}
这段代码执行会出现以下结果
那么在上面的狗类中,不初始化成员函数来打印成员函数,会出现什么结果呢?
public static void main(String[] args) {
Dog dog = new Dog();
// dog.name = "小白";
// dog.age = 5;
dog.bark();
dog.eat();
//dog.setName("小白");
//dog.setAge(5);
}
可以看出,类中的成员变量不用初始化也可以进行打印,但是会赋给成员初始值
我们也可以直接给类的成员赋初始值
class Dog {
public String name = "小白";
public int age = 5;
}
需要调用之前写的set方法才可以将具体的值设置到对象中,比较麻烦,那对象该如何初始化?
对象赋值有没有简单的方法?
2. 构造方法
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。如果我们没有给出构造方法,那么编译器会给出一个默认构造方法。
每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。
在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。
我们来写一个简单的构造方法
public class TestDemo {
public int a;
public int b;
//无参的构造方法
TestDemo() {
System.out.println("这是一个无参的构造方法");
}
//有参的构造方法
TestDemo(int a, int b) {
System.out.println("a=" + a + ", b=" + b);
System.out.println("这是一个有参的构造方法");
}
public static void main(String[] args) {
//实例化两个对象
TestDemo testDemo1 = new TestDemo();// 这里会调用无参的构造方法
TestDemo testDemo2 = new TestDemo(1, 2);// 这里会调用有参的构造方法,并给a和b赋上初始值
}
}
运行程序,会得到以下结果
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
名字必须与类名相同
没有返回值类型,设置为void也不行
创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
我们也可以在无参的构造方法中,用this调用有参的构造方法
TestDemo() {
this(1,2);
}
TestDemo(int a, int b) {
System.out.println("a=" + a + ", b=" + b);
}
如果在实例化对象时没有传入参数
TestDemo testDemo1 = new TestDemo();
那么,将会调用无参的构造方法,并且这个构造方法会调用有参的构造方法
3.默认初始化
在上面所提及的初始中,如果没有采用任意一种方式来初始化成员变量的时候,编译器会默认给不同类型的变量来赋初值
五、对象的打印
public class TestDemo {
public int a;
public int b;
//无参的构造方法
TestDemo() {
}
//有参的构造方法
TestDemo(int a, int b) {
System.out.println("a=" + a + ", b=" + b);
}
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
System.out.println(testDemo);
}
}
这段代码将对象进行打印,那么打印出的会是什么呢?
可以看出,我们打印的结果是这样的,那这究竟是什么呢?
我们进入println的源码
经过源码的查看,最终得到:打印的结果是 类名@地址的哈希值
所以,如果想打印对象的初始值,我们可以重写一个toString()方法。
按照这两步,编译器会给我们重写toString,并且给出成员函数的名字和值
@Override
public String toString() {
return "TestDemo{" +
"a=" + a +
", b=" + b +
'}';
}
这时候再打印
当然,我们也可以自己重写一个toString
版权归原作者 Aqua_yyds 所有, 如有侵权,请联系我们删除。