Java是一门面向对象的语言,在Java中一切都是对象。
目录
一、类与对象的介绍
Java是一门面向对象的语言,在Java中一切都是对象。
如何来形容对象和类呢?
我们来以素描举例,像我们吃的苹果它是真实存在的东西就是对象,而以苹果当对象进行绘画的素描就是描述它的类。
1.对象:
是实际存在的个体,如:人,动物,植物,水杯……他们都是真实存在的。
2.类:
是对多个或一个实体)对象进行的描述,是一种抽象的数据类型。主要描述该对象具有哪些属性(外观尺寸),哪些功能(能干啥)。
比如:手机,它是一个大类,在Java中可以看成一个类别
属性:产品的品牌、处理器、屏幕、厚度……
功能:聊天、听歌、打游戏……
再来解释一下吧,就相当于学校有它的校名、王牌专业、师生、食堂,学校在寒暑假会放假,学校不让学生不上课。而这其中学校就是类,校名、王牌专业、师生、食堂是它的属性,学校寒暑假放假,学校不让学生不上课是它的行为。
一、面向对象编程
1.面向过程编程
面向过程编程就是注重每一步的步骤,注重过程一步步的来,将问题分解成一系列的步骤,按照顺序依次执行这些步骤完成任务。像C语言就是面向过程编程。
像解一道题也是在面向过程编程。像这一篇文章Java数组的练习
都是根据题目要求第一步定义数组,第二步干啥干啥,第三步干啥干啥……
具体就拿数组交换举例吧
第一步我们定义了两个数组
第二步我们进行了交换
第三步我们输出交换后的数组
这个就是面向过程编程,通过一系列的步骤解决问题。
2.面向对象编程
面向对象编程就是几个对象相互协作(交互)解决问题。
例如:洗衣服,我们只需要人把衣服放入洗衣机倒入洗衣液点击开始,后面人再去晾干衣服就能完成这个任务。而这其中就是人、洗衣机、洗衣液三个对象交互解决了洗衣服这个问题。
这个就是面向对象编程,通过对象交互解决问题。
三、类定义与使用
在Java中定义一个类需要用到class关键字
class 类名 {
成员属性/字段(成员变量);
成员功能/行为(成员方法);//所有的对象都具有该行为
}
类名一般采用大驼峰命名。这篇文章也提到过(就是我弄得太长了)1.初识Java(Java的定义、结构、注释、标识符、关键字以及数据类型、输出、类型转换、字符串类型)
驼峰命名法:
1.小驼峰命名法:
第一个单词首字母小写余下的单词首字母大写 例如 basicStructure,常用于变量名、函数名等
2.大驼峰命名法(帕斯卡命名法PascalCase):
每个单词首字母都要大写 如 BasicStructure, 常用于类名、枚举名等
属性/字段 是成员变量,与局部变量定义在main方法中不同,其定义在方法的外部,类的内部。
功能/行为 是成员方法。
例:我们来定义一个猫类吧
成员方法和成员变量可以分为两种:
1.静态的如果是静态的只需要加上static就行,但是比较复杂目前来看(后面讲)
2.非静态的
定义一个类,就相当于在计算机中定义了一种新的类型,之前我们不是讲过Java的基本数据类型(int byte double float String…… )他们是Java语言中自带的内置类型,而类是用户自定义的一个新的类型。
你们有注意到吗?我并未将Cat类中的成员变量初始化,却没有报错,这是为什么呢?
原因是对于类的成员变量来说,每一个成员变量都有一个默认的值,引用类型 默认为null, 基本类型默认为对应的默认值。
int→0
double→0.0
float→0.0f
boolean→false
注意:
1.一般建议一个Java文件中只写一个类
why?
因为一个Java文件中只能有一个被public修饰的类,假如你在一个文件中定义了两个类且两个类都是公共的public就会出现问题。
就算不用public修饰,我们会发现它在该类的.Java文件中。而不是 Dog.java文件,从而使得一个Java文件中有多个类。
2.main方法所在的类一般用public修饰,但是不是必须的。main可以不用public修饰
在一个Java文件中可以存在多个main,但是要在不同的类里面。
3.public修饰的类必须与文件名相同
如果不相同就会报错。
4.不要去轻易修改public修饰的类的名称,如果要修改,通过开发工具修改(这个修改也只适用于一个Java文件中只有一个类)。
例如:我们要将Cat类修改成Animal类,首先鼠标点击项目Project中的src包中的Cat,然后按照图中操作
点击Refactor
就更改完成了。
但是如果一个Java文件中有两个类则不能完成更改。
我们来尝试一下将它改为Test
可以看见出现了问题,更改了.Java文件的名字,但是代码中的类名没有得到修改,因为它有两个类。
四、类的实例化
用类类型创建的对象就叫做类的实例化。也就是说在我们定义的类中new一个具体的对象。
怎么解释呢?
就像我们都是人类,这里的人类就是一个类,而每个人都不一样独具一格,是独立且唯一的一个个体,我们有不同的名字,不同的身高,不同的肤色,不同的民族,这个名字、身高、肤色、民族就是属性。但是我们也有相同的行为,我们要吃饭,要睡觉,要洗澡,这个就是行为。而人类繁衍(new创建)了我就是一个具体的对象,我叫小杨,我身高XXX,肤色不白,汉族。我就是人类的其中一个对象,我们每个人都是人类的实例化,也同样是人类的对象。这个就是类的实例化。
就像之前所举例的猫类我们给它来实例化一下。
我们给它new创建一个具体对象就像加菲猫,它的颜色是黄色,体重不清楚乱写一个,品种是红虎斑异国短毛猫。
Cat cat = new Cat( ); 这个呢,就是创建了一个具体的Cat对象,因为我们是用户自定义的类,其变量名一般与类型名一致,就是注意变量名第一个字母小写后面大写,当然在定义时IDEA也会给予我们提示
注意:
1.new关键字是用于创建对象的实例
2.使用.来访问对象中的属性和方法。
3.同一个类可以创建多个实例
让我在举个小小的例子猫,是我们学校的猫,它真的很势利眼,所以就叫势利眼,因为没有吃的就不搭理你,一摸它它还生气,可一有吃的可热情了。
public class Cat {
/*属性*/
public String name;/*名字*/
public String color;/*猫咪颜色*/
public double weight;/*猫咪的体重*/
public String species;/*猫咪的种类*/
/*行为*/
public void mimi() {
System.out.println(name+"咪咪叫");
}
public void wag() {
System.out.println(name+"摇尾巴");
}
public static void main(String[] args) {
Cat cat1 = new Cat();
Cat cat2 = new Cat();
cat1.name = "加菲猫";/*使用.访问属性和方法*/
cat1.color = "黄色";
cat1.weight = 17.2;
cat1.species = "红虎斑异国短毛猫";
cat1.wag();/*调用方法使用.*/
cat1.mimi();
cat2.name = "势利眼";
cat2.color = "黄白色";
cat2.weight = 17.3;
cat2.species = "橘猫";
cat2.wag();
cat2.mimi();
}
}
类与数组也有很相似的地方,都是对象在堆区开辟了空间存储,局部变量都在栈区中。
如举个类中多个实例化的例子学生1(张三男年龄10岁考试成绩99)和学生2(王五男年龄11岁考试成绩15)
具体的图来看一下栈区是定义的类1和类2与堆区 是属性
那么如何输出Cat类的两个猫(加菲猫和势利眼)的所有信息呢?
我们是不是在可以构造一个printCat方法专门进行输出属性信息,这样就不用如此重复的写相同的代码,就像这样。
但实际上也是不用的,因为IDEA中有生成该输出的快捷方法键
直接也是在Cat类里面的空白行中鼠标右击一下,然后点击Generate,选择toString,全部勾选或者只选你要输出的就可以了,然后在main方法中输出中调用它,就会是下面这样啦
①
如果下载了中文插件就是生成那个键或者直接按快捷键alt+insert
②下载了中文插件操作方法
如果你们想用中文版本的IDEA或者想删除中文插件,直接区豆包中搜索该如何做,我们应该多多利用AI,我觉得真的很快捷也会学到东西的。
五、set方法和get方法
1.set方法(赋值方法)
用于设置和修改对象属性值。
2.get方法(取值方法)
用于获取对象的属性值。
这两种都是由系统可以生成的
鼠标右击
public class Student {
public String name;
public int age;
public void DoHomework(){
System.out.println("正在写作业");
}
/*Setter设置name的值*/
public void setName(String name) {
this.name = name;
/*this.name表示类的属性,参数name是外部传入的值*/
}
/*Getter获取name的值*/
public String getName() {
return name;
}
public static void main(String[] args) {
Student student = new Student();
student.setName("小小");/*通过Setter赋值*/
System.out.printf(student.getName());/*通过Getter取值*/
student.DoHomework();
}
}
五、this的引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问的。
Question1.为什么要有this引用?
举个例子我们定义了一个日期Date类,我们想要一次性传入三个参数,我们是不是会构造一个方法进行传参。就像这样
public class Date {
public int year;
public int month;
public int day;
public void setDate(int y,int m,int d) {
year = y;
month = m;
day = d;
}
@Override
public String toString() {
return "Date{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
}
错误举例:
如果我们想就把参数写成year,是不是会跟成员变量重名从而导致出错,就像这样
虽然编译器没有报错,但是它实际是0年0月0日,因为局部变量优先,所以是形参自己给自己赋值
因此这个时候我们就需要用到 this. 了,因为this.year是当前对象的引用,也就是成员变量year,就成功的输出了。
我把它结合给你们完整的代码
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year,int month,int day) {
this.year = year;/*前面的year指的是Date类里面的成员变量*/
this.month = month;
this.day = day;
}
@Override
public String toString() {
return "Date{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
public static void main(String[] args) {
Date date = new Date();
date.setDate(2025,3,37);
System.out.println(date.toString());
}
}
Question2.当我们实例化了多个日期,每个方法只有一个,该方法是怎么知道给哪个对象成员进行赋值呢?
public class Date {
public int year;
public int month;
public int day;
public void setDate(int year,int month,int day) {
this.year = year;/*前面的year指的是Date类里面的成员变量*/
this.month = month;
this.day = day;
}
public void printDate() {
System.out.println("Date="+year+"-"+month+"-"+day);
}
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
Date date3 = new Date();
date1.setDate(2025,3,27);
date2.setDate(2025,3,28);
date3.setDate(2025,3,29);
date1.printDate();
date2.printDate();
date3.printDate();
}
}
(这里我们构造了一个输出方法,可以更直观的看见其地址) 我们用Debug调试逐步来看一下。
当执行date1.setDate(2025,3,27)时,setDat方法被date1对象调用,此时方法内的this就指向date1。this.year = year; 这一行代码就是将传入的参数year的值域给date1对象的成员变量,同理month和day也是如此。
就相当于setDate构造方法中隐藏着Date this的 这个参数
这就是为什么类实例化多个对象,一个方法可如何知道给哪个赋值。
this的特性
1.this的类型:对应类类型引用,即哪个对象调用就是哪个对象 的引用类型,代表当前对象的引用this.date
2.this只能在“成员方法”中使用
3.在“成员方法”中,this只能引用当前对象,不能再引用其他对象
4.this是“成员方法”的第一个隐藏参数,编译器会自动传递
六、构造方法
构造方法(也称为构造器)是一个特殊的成员方法用于对象的初始化,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
基本特点
1.与类同名:构造方法必须与类名完全相同
2.没有返回类型:构造方法和类名一样不用写void
3.自动调用:在new对象 时自动执行
4.初始化对象:主要用于初始化对象的状态
5.一般情况用public修饰
6.构造方法可以重载构造
7.当一个类没有写任何的构造方法时,此时默认会存在一个不带参数的构造方法。无参(编译器提供的)
只不过这个构造方法里面什么都没有做。
构造方法类型
1.默认构造方法(无参构造)
2.带参数的构造方法(有参构造)
直接可以由系统生成
也是右击鼠标键
再点击
最后就跟set方法和get方法一样的操作
当你已经创建了带参数的构造方法时,编译器则不会提供无参默认构造方法,毕竟鱼与熊掌不可兼得,既要又要不可取。人都是救急不救穷的。
正确的带参构造方法
public class Date {
public int year;
public int month;
public int date;
public Date(int year, int month, int date) {
this.year = year;
this.month = month;
this.date = date;
System.out.println("带三个参数的构造方法");
}
public void printDate(){
System.out.println(year+"年"+month+"月"+date+"日");
}
public static void main(String[] args) {
Date date2 = new Date(2025,7,16);
date2.printDate();
}
}
3.构造方法重载
构造方法是可以重载的。
构造方法中,可以通过this调用其他构造方法来简化代码。
注意:this()语句必须是构造方法中的第一条语句。不然会报错
Question:以下是生成什么日期?(这个代码不标准,只是突发奇想)
猜猜答案是2025年7月16日还是2025年7月15日呢?
答案是2025年7月15日。
为什么呢?我们来看看调试
从图中我们可以看见因为我们new创建的对象date2调用的是有参构造,是用传入的值初始化。而没有执行到无参构造Date( )。
让我们来看看无参构造吧。举一反三,我们可以知道无参构造的答案就是this这的2025年7月16日。
public class Date {
public int year;
public int month;
public int date;
public Date(){
this(2025,7,16);
}
public Date(int year, int month, int date) {
this.year = year;
this.month = month;
this.date = date;
}
public void printDate(){
System.out.println(year+"年"+month+"月"+date+"日");
}
public static void main(String[] args) {
Date date2 = new Date();
date2.printDate();
}
}
看看他的调试
所以我们知道了
1、构造方法重载靠的是参数列表的区分(个数、类型、顺序),即是否有参;
参数个数相同,至少一个参数类型不同;参数的个数和类型都相同,至少顺序不同。
含参已经讲了,接下来我们看看参数个数相同的情况,
①如果个数相同的前提下,你的类型也是相同的就会报错
正确的是类型不同的两个构造方法
public class Clothes {
public String color;
public String Type;
public int price;
public Clothes(String color, int price) {
this.color = color;
this.price = price;
}
public Clothes(String color, String type) {
this.color = color;
Type = type;
}
public static void main(String[] args) {
Clothes clothes = new Clothes("黄色",189);
}
}
②参数顺序 ,参数个数和类型都相同,但是参数的排列顺序不一样
2、想用哪个构造方法,就new类名(对应参数)调用。也就是刚刚的问题。
OK啦,构造方法的重载就讲完了。
下一讲:继承与多态。