5.Java类与对象

发布于:2025-07-17 ⋅ 阅读:(15) ⋅ 点赞:(0)

Java是一门面向对象的语言,在Java中一切都是对象。 


目录

一、面向对象编程

1.面向过程编程

2.面向对象编程

二、类与对象的介绍

如何来形容对象和类呢?

1.对象:

2.类: 

三、类定义与使用


一、类与对象的介绍

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啦,构造方法的重载就讲完了。 

下一讲:继承与多态。


 


网站公告

今日签到

点亮在社区的每一天
去签到