前言
本篇讲解Java类和对象的入门版本。
学习目的:
1.理解什么是类和对象。
2.引入面向对象程序设计的概念
3.学会如何定义类和创建对象。
4.理解this引用。
5.了解构造方法的概念并学会使用考虑到篇幅过长问题,作者决定分多次发布。
面向对象的引入
Java是一门面向对象的程序设计语言。那么面向对象具体是啥意思呢?
面向对象(Object-oriented)更多是一种思维模式,它替换了原有的面向过程的思考方式,转为了面向对象。这种编程思想强调了将问题分解为对象的集合,对象有各自的属性和方法,对象与对象之间又有信息传递和行为协助。
- 总结:解决问题的重心由拆分步骤,改变成拆分成对象,对象和对象的协作上。编程思维模式的转变
面向过程编程
如果你先前学过任何一门面向过程的编程语言,比如C语言。回忆一下,先前解决问题是不是研究解决一个问题的过程是怎样的?
它的重点在于如何完成任务,要实现哪些功能的函数,函数接收参数返回值,执行一系列的逻辑结构过程,然后才是研究数据应该采用什么数据结构存储,最后输出正确的结果。
面向过程首先考虑的是如何处理数据即算法,其次是数据如何存储(数据结构)。
面向对象编程
面向对象编程(Object-Oriented Programming)简称OOP.它是一种以对象为中心的编程范式,对象有自己的状态行为,通过封装,继承,多态实现代码的模块化。实现对象与对象之间的协作和交互。
与面向过程对比,面向对象先考虑的是数据如何存储,将相关联的数据和方法包装成一个对象。其次考虑处理对象与对象之间。可以说先数据结构后算法,与面向过程反着来了。
生活化的示例
传统洗衣服(面向过程)
1.拿脏的衣物。
2.水槽装足够的水
3.加入洗衣粉
4.将脏衣服放入水槽
5.疯狂手搓
6.冲洗衣服
7.换水
8.继续冲洗衣服
9.拧干洗好的衣服
10.晾衣服。
现代洗衣服(面向对象)
确定对象 脏衣物,洗衣粉,洗衣机
我们人为交互
1.将脏衣物放入洗衣机
2.倒入洗衣粉。
3.设定洗衣机的程序。
洗完后,取出晾干就可以了。
整个都是三个对象的交互。洗衣机怎么洗的,内部怎么运作的?I don’t care.
总之我知道按照上面三步衣服就洗好了。
类和对象的概念
举个栗子,人就是一个类。人有姓名,年龄,身高,体重,家庭住址。但人的概念太抽象了,太广泛了。那么张三,小红,李华,你和我,就是具体的人了,我们也有上面的姓名身高年龄。
所以呢,*类是类型,蓝图,模板。*即上面例子中的人。那么后面的张三就是具体的人,就称为一个对象。人有的属性,张三也有。
所以,类可以描述对象,对象是类的实例化。
类
接下来正式介绍类
类(class)是构造( construct ) 对象的模板和蓝图, 由类构造对象的过程称为创建类的实例 ( instance ) 。
现在笼统的阐述类的特点,后面补充实例
类的特点:
1.属性(fileds):类可以定义成员变量。成员变量体现的是对象的属性(状态特征)。每个对象通过各自类的属性有自己的特点状态。
2.方法(methods):类内部可以定义成员方法,简称方法或者函数。方法定义了对象的行为,方法可以让对象执行某种特定的功能,更能完成对象与对象的协作。
3.类的实例化(instance):类本身只是一个模板,类似C中的结构体。只有实例化(构造对象),它内部的属性和方法才有意义。如何创建下面会给出例子。
4.构造方法(construct):这里先不提,往后看下去,后面会讲。
5.封装类,抽象类,继承,接口…………这里不提。其实作者也没懂完
现在可以定义一个类了
类的基本语法(目前掌握以下这些就够了)
class 类名{
//属性:成员变量//成员方法
}
1.class 类的关键字,定义一个类必须有。
2.类名:遵循标识符的命名规则,采用大驼峰命名法。
3.花括号别忘了,别漏了。
4.属性(成员变量):这里可以定义各种类型变量表示类的状态了。
5.成员方法:定义类的行为与操作。
下面定义一个Dog类
public class Dog {
//成员变量
public String name;
public int age;
//成员方法
public void bark(){
System.out.println("Ruff! Ruff!");
}
}
上面我们定义这样一个类,该类有两个成员变量,分别是字符串name和int年龄。还有bark这样一个成员方法表示dog在叫的行为。
这里的public是访问修饰符,表示类,成员变量,成员方法的访问权限。
类的实例化
由类生成对象的过程叫做类的实例化
类在Java中为引用类型。
int double float为内置类型(基本数据类型),Java中与其相对的类型称为引用类型,数组字符串也是引用类型。引用类型也是自定义类型,类是用户自定义出来的类型。
Java中由类创建一个对象,要用到关键字new.
Dog dog=new Dog();
语法:
类名 变量名 = new 类名()
这里Dog就是先前定义的类了。
dog是这个类类型的变量名。
new “给我一个对象” 后面跟上Dog()就创建了一个属于Dog的对象了。
new后面其实跟着的是构造方法,这个稍后再说。
既然创建了对象,我们定然想到如何处理对象呢。
dog.age=1;
dog.name="Bin";
dog.bark();
通过圆点运算符(.)我们就可以访问对象的成员了和方法了。
这里对象继承了类的属性,这个实例化的dog也有了name和age,也能调用bark()方法了。
假设我们不对对象初始化操作,会出现问题吗?
不会,因为局部变量未初始化会被编译器报错警告。而对象的成员变量不在栈上而在堆上,未初始化会有对应的默认值。
Dog dog=new Dog();
System.out.println(dog.name);
System.out.println(dog.age);
对于引用类型,其默认值为null;内置类型就为相应的0值,int对于0,float对应0.0F,double对应0.0,另外boolean对应false。
我这里的dog在main方法内部创建,就是局部变量在栈上开辟一块空间,同时在堆上为这个对象开辟合适的空间保存对象的属性。这里的dog实际存储了对象在堆上的地址,dog就称为一个引用。通过引用,我们访问对象的成员。
对象
其实类那一部分已经说明完大部分对象的内容,这里稍作补充和总结。
对象有状态。这里的状态从代码来看就是成员变量的值不同,反过来就算同一个类的对象成员变量的值不同说明他们之间状态不同。
对象有行为。根据对象的状态,调用成员方法行为上不同,反之根据自身的行为(方法调用)也会影响自身状态。
对象有名字。每个对象应该有独立的标识符来区分不同
对象与对象之间独立。每个对象有自己的状态和行为。
认识this引用
关键字this
先定义如下一个类
里面的setData成员方法中的形参与成员变量名同名还能进行赋值吗?
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year,int month,int day){
year=year;
month=month;
day=day;
}
public void printByString(){
System.out.println("year = "+year+" month = "+ month+" day = "+ day);
}
}
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year,int month,int day){
year=year;
month=month;
day=day;
}
public void printByString(){
System.out.println("year = "+year+" month = "+ month+" day = "+ day);
}
public static void main(String[] args) {
Date date=new Date();
date.setDate(2024,5,13);
date.printByString();
}
}
运行结果是怎样的呢?修改data对象的值了吗?
答案必然是没有!否则这里要说明的this干嘛呢。
很明显,这里setDate里形参和成员变量名重复了,左值的year究竟代表了成员变量还是形参呢?是形参。
所以,这里上述的赋值就是自我娱乐,对成员变量没有影响。因为调用方法时会在栈上开辟空间称作函数栈帧,此时局部变量(函数形参)优先使用。
这个时候就要用上this对setDate函数做出如下修改。
public void setDate(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
}
这里的this相当于原来的date对象,很显然this.成员变量和方法参数区分开了。说明了这里左值同名的year,month,day是引用(data对象)的成员变量。避免出现同名时混淆的情况。
那么this是怎样知道它代表哪个引用呢?
实际上那个对象的引用在某个方法时会将这个引用当作函数参数传递过去。
实际的setDate写成下面这样。只不过我们写的时候省略了第一个参数罢了。
由此我们可以知道那个对象的引用在调用某方法时,这个this就代表谁了。
public void setDate(Date this,int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
}
这里的this由于就是date,它也可以调用自身的成员方法。
public class Date {
public int year;
public int month;
public int day;
public void setDate(Date this,int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
this.printByString();
}
public void printByString(){
System.out.println("year = "+year+" month = "+ month+" day = "+ day);
}
public static void main(String[] args) {
Date date=new Date();
date.setDate(2024,5,13);
}
}
this还有一个用处调用其它构造方法
构造方法
前面提过成员方法,那么构造方法和成员方法有什么区别呢?类比学习一下吧。
一般的成员方法格式:
返回值 方法名(参数列表){
//方法体
}
构造方法可以看作特殊的成员方法
第一,它没有返回值类型。
第二,它的方法名和它的类名一样。
即
构造方法格式:
返回值方法名类名(参数列表){
//方法体
}
public Date(){
}
这就是一个简单的构造方法。
想到前面这个Date date=new Date();
new后面的 Date()不就是一个构造方法吗?哎奇怪,当时我们并没有创建这样的构造方法呀。
事实上,如果定义的类没有构造方法,编译器会默认给你上述的构造方法,这种构造方法是最简单的。没有带任何参数。
需要注意的是,如果你自己创造了一个构造方法,请严格按照你的构造方法创建对象,此时编译器不会在为你默认这么一个构造方法了。
下面给出一个带参数形式的构造方法。
public Date(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
}
这样就可以在创建对象时同时初始化成员变量了。
构造方法同样支持重载。即上面两个构造方法可以同时存在一个Date类中。
public class Date {
public int year;
public int month;
public int day;
public void setDate(Date this,int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
this.printByString();
}
public void printByString(){
System.out.println("year = "+year+" month = "+ month+" day = "+ day);
}
public Date(){
}
public Date(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
}
public static void main(String[] args) {
Date date=new Date(2004,12,8);
date.printByString();
}
}
最后总结一下构造方法:
1.构造方法名与类名相同。
2.无返回值类型,不要理解成返回值类型为void
3.创建对象时调用,且只能调用一次。
4.构造方法可以重载。(比如上面的构造方法在创建对象时可以选择不带参数,还可以选三个参数初始化的)
5.如果没有自定义构造方法,那么编译器默认会构造方法。
结尾
想不出来说什么了,太困了。嗯~
一无所有,或者赢下所有