初识类和对象

即使是初学者应该对类和对象也不算陌生吧,是不是因为老有些人动不动就:你知道伐,Java是一款面向对象的语言……阿巴阿巴……我的老师告诉我Java难的一部分就是如何把一个对象给抽象出来,那阿涛不才,今天就先来会一会这类和对象

面向过程和面向对象

什么是面向过程,什么是面向对象?
面向过程就是早上你给你的对象打了通电话互道了声早顺便约了个午饭,中午你们在某某餐厅饱餐一顿,然后下午顺道在附近的电影院看了场电影,还没到晚上了,就乖乖地各回各家了……
面向对象就是,你,你的对象,手机,饭店,电影院,共享单车。
怎么说呢,兄弟们你们有没有发现,我们在写C语言的代码的时候,全都是按着逻辑顺序,这一步有哪些人干了哪些事,下一步又怎么怎么样,但是在Java中确实先把需要交互的对象先想好。然后才是慢慢写这些对象之间的互动。
大概就是这么个意思!兄弟们不要问我哪个好,我只能说如果我从事的是面向过程的工作,那面向过程就好,反之就是面向对象好!

类的定义和使用

我们总是说定义一个类,实例化一个对象,在阿涛的认识里面,类就像是一个人的模板,我们程序猿的任务就是把可能用到的这个人的信息和行为抽象出来,转化成代码写进这个类里面,然后我们就可以用这个模板来逐渐勾画出一个活生生的人了。
一个人会有名字,年龄,性别……我们把这类东西叫做是属性/字段。
一个人也会吃饭,也会喜欢打游戏,也耍朋友,我们把这类叫做方法。
可是我们的编译器不像兄弟们这样聪颖啊,它根本理解不了我敲出来的东西,但是兄弟们都是一看都懂得啊!所以我们还是要学习Java语言!

public class Test {
    class dog{
        public String  name;
        public int age;
        public String sex;

        public void eat(){
            System.out.println(name+"恰饭呢");
        }
        public void barks(){
            System.out.println(name+"汪汪汪");
        }

    }

在这里,我们使用class这个 关键字定义了狗这个类,这个类里面包含了狗的一些属性,那么我们就先这个模板给大家讲一讲:
有兄弟是不是会有疑惑,为什么开头还有一个class呢,为什么这个class前面还可以加个public 呢?我们要知道的是,一般情况下我们一个Java文件只会定义一个类,但是我们的工作量并不是很大,以及为了讲解的方便我们就便宜行事了!
但是兄弟们要记住了,一个Java文件中只可以有一个类被public修饰,我们用class关键字来定义一个类,class后面的就是我们的类名,而被public修饰的类名应当和我们的Java文件名一样,没有为什么这就是规定,Java文件创建好了这个public class就出来了,谁知道为什么呢……而且你还不可以随便修改那个类名,你一旦通过代码修改,程序立马给你一片红,但是你可以在左边的工具栏中找到一项可以修改类名的按键。

类的实例化

我们之前就说过了,我们可以把我们创建好的类就看成一个模板,可是再好看的设计图纸,你不真正一砖一瓦去敲去盖,这一辈子都只是一纸空书,我们的Java程序也是非常务实的,他不吃大饼,你光光是一个空架子,我连内存都不给你分配,你就给我老老实实地在代码区呆着!
我们前不久才说过:Java之中一切,皆是对象!我们可以通过new这个关键词new无数个对象,只要是我们new出的对象都是要供在堆区的。关于我们自己写出来的类,我们就可以把类名同int、String等等等同起来,我们就可以使用类名来定义一个引用变量,来存储我们创建出来的这个对象的地址!

        class Dog{
            public String  name;
            public int age;
            public String sex;

            public void eat(){
                System.out.println(name+"恰饭呢");
            }
            public void barks(){
                System.out.println(name+"汪汪汪");
            }

        }

        Dog dog=new Dog();

大致就是这么一个效果。兄弟们有没有注意到阿涛这串代码和上面的有什么区别?兄弟们要注意了:我们的类名是要写成大驼峰的,我们的方法名变量名要写成小驼峰!
那现在我们就是已经在堆上创建好了一个对象Dog,同时我们拿到了这个对象的引用dog!在这里插入图片描述
我知道兄弟们现在会有很多的问题
比如类中的public啊,还有static啊,我知道你很急,但请你现在先不要急!
我们在堆上面的对象之中是有它的属性的,但是类中的方法似乎并不在堆上啊,目前类中的方法是在一块代码区里面呆着呢,当我们想要调用类中的方法的时候,程序自然会帮其创建内存。
那现在我们忙活了这么半天,是为了什么呢?当然是为了构建我们的伟大蓝图啊!
首先兄弟们要明白一点,在Java里面我们是无情的,我们可以随意制造对象以此弥补我们在现实生活中的遗憾,就像现实生活中的对象一样,你的每一任对象都是独立的个体,她们应当有着自己的一些信息,那我们就可以通过我们手上指向对象的引用,访问对象的属性,调用对象的方法:

        Dog dog=new Dog();
        System.out.println(dog.name);
        dog.name="CyT";
        System.out.println(dog.name);
        dog.barks();

在这里插入图片描述
兄弟们看啊,这是不是好像我们真的创建出来的一只小狗一样?我们可以给他起名字,他会对着我们汪汪叫……但是兄弟们还记不记得,我之前好像说过,局部变量在使用之前必须要初始化的,Java不会好心到帮你一个局部变量来赋初始值!那么请问,为什么在我上面这个程序中,并没有见红呢?所以说语言是一门艺术,人习惯性只会听个大概,如果我们的name并不是局部变量,这不就是一个答案吗。我们写在类中的变量,叫做成员变量,当我们没有手动赋初值的时候,程序会帮助我们统统搞好,这才是牌面!
这也就是我让兄弟们看到那个null的用意啊!!
那么接着上面的说,我们是可以使用引用来访问到我们成员的信息的,我们通过dog.name修改了小狗的名字,我们又通过dog.barks让小狗冲我们叫唤了两声。是不是逐渐一个小狗的形象就饱满了起来?
那对于成员变量我们一个一个赋值过去是不是有点太麻烦了?我们不妨写一个方法帮助我们进行赋值!

            public void set(String name,int age,String sex){
                name=name;
                age=age;
                sex=sex;
            }

            @Override
            public String toString() {
                return "Dog{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", sex='" + sex + '\'' +
                        '}';
            }
        }

        Dog dog=new Dog();
        System.out.println(dog.name);
        dog.name="CyT";
        System.out.println(dog.name);
        dog.barks();
        System.out.println(dog);
        dog.set("cyt",20,"man");
        System.out.println(dog);

先给兄弟们打一个预防针:如果我们不做任何处理就试图sout一个引用变量,那我们看到的将会是一串类似于地址的东东,但是因为我们在这里写了一个toString方法,所以一切都变了,这一点之后我专门找一篇博客写一篇!
那我们来看一下效果吧:在这里插入图片描述

This

这不奇怪了吗?我们不是明明给set这个方法提供了三个参数吗?怎么就结果来看,好像我们的成员变量并没有被赋值啊!怎么好像打印的都是默认值啊!其实不管在C语言还是Java中,我们秉持着的是一个局部变量优先的原则,所以此时我们的两个name其实都是形式参数,我们根本就没有对实参进行修改,现在我们可以通过修改形式参数,使得形参与实参不重名,但是那样子似乎指向性不是那么强烈,因此我们可以通过加上一个神奇的this!
在这里插入图片描述
兄弟们看过来,是不是现在我们就进行的是有效赋值?
那我们现在回过头来,再来思考一下,这里的this究竟指的是什么?

            public void eat(){
                System.out.println(name+"恰饭呢");
            }
            public void barks(){
                System.out.println(name+"汪汪汪");
            }
            public void set(String name,int age,String sex){
                this.name=name;
                this.age=age;
                this.sex=sex;
            }

            @Override
            public String toString() {
                return "Dog{" +
                        "name='" + name + '\'' +
                        ", age=" + age +
                        ", sex='" + sex + '\'' +
                        '}';
            }
        }

        Dog dog=new Dog();
        dog.set("Cyt",20,"man");

可以看到,我们的this是写在了Dog这个大类中的非静态方法set 里面的,那此时如果我们想要调用这个set方法,这个依赖对象的方法,我们势必需要实例化一个对象,然后使用这个对象的引用来访问这个方法。所以,哪个引用调用了这个方法,我们的this就相当于哪个引用,就是我们实例化出来的对象的一个引用!
要注意的是,我们的this只能在成员方法里面使用。
具体的原因是,this其实是我们成员方法中被隐藏起来的第一个参数,我们把调用了这个方法的对象的引用赋值给了this,在成员方法外面没有这个机制,怎么能够凭空使用这个this呢?

对象的构造及初始化

提到构造,就不得不提一下我们的构造方法了:

        Dog dog=new Dog();

对于这行代码,我们目前的理解是:
通过关键字new在堆上定义了一个Dog类型的对象,然后把这个对象的引用赋值给栈上的dog这个引用变量。这个理解是完全正确的,只是不太准确而已!
实际上,我们只要是new了一个对象,势必是要调用一下这个类中的构造方法的:

            public Dog(String name, int age, String sex) {
                this.name = name;
                this.age = age;
                this.sex = sex;
            }
        }

        Dog dog=new Dog();

上面那段代码就是我们写在Dog类中构造方法。在这里插入图片描述
可以看到现在我们实例化对象的时候报错了!
这时候我们适时来讲解一下构造方法的组成:
构造方法是写在类当中的,构造方法的方法名必须和类型相同,不然在实例化的时候凭什么调用你这个方法呢……一般来说我们的构造方法都是用public修饰的,还有就是不要给构造方法加上返回类型!!跟void这个返回类型压根不是一回事,是根本不写!!
然后就是给我们的构造方法的参数列表添砖加瓦了:

 public Dog(String name, int age, String sex)

这里的参数是由我们自己在实例化对象时给new后面对象的( )里面写上的,所以不要迷茫,你就是上帝!!
那我们这里为什么还会报错呢?Dog dog=new Dog();
可以看出,我们实例化对象时并没有给这个对象传参,因此在编译的时候,编译器就没有办法找到一个没有参数的构造方法,这时候它懵了,只能通过报错的方式来提醒你!
兄弟们要注意,我们的构造方法在一个对象从创建到销毁短暂的一生当中只会被调用一次,就好比按照法律你一次只能和一个人结婚,但是我们的结婚对象可以有很多啊!!!
也就是说,我们可以自己写好多构造方法啊!

            public Dog(String name, int age, String sex) {
                this.name = name;
                this.age = age;
                this.sex = sex;
            }
            public Dog(){
                
            }
        }

        Dog dog=new Dog();

在这里插入图片描述
这里就没有报错了,但是我们使用构造方法的一大妙用就是在实例化对象的时候给对象的参数进行初始化:
在这里插入图片描述
可以看到我们已经成功给我们的对象进行了初始化!
此时有兄弟开始回味阿涛刚才说过的话了,我们实例化一个对象的时候是一定要进行一次初始化的,可是似乎在一开始,我们并没有自己写一个不带参数的构造方法啊!
要知道的是,当我们没有写任何的构造方法的时候,会默认有一个不带参数的构造方法,但是如果我们自己动手了,那就必须需要我们手写了!
在这里插入图片描述
兄弟们细看,这里有两个方法,这两个方法名称一摸一样,参数列表不同,但是此时我们甚至没有返回类型,也就是说我们对于方法的返回类型并不做任何要求!这不是重载的标准定义?所以我们写的这些构造方法之间也就构成了重载!

此时我i们甚至于可以结合一下this和构造方法,达到一种简化的目的:

            public Dog(){
                this("cyt",20,"man");

            }
        }

        Dog dog=new Dog();
        System.out.println(dog);

在这里插入图片描述
我们调用的是一个不带参数的构造方法,但是在这个构造方法里面我们又调用了有三个参数的构造方法,这样同样完成了我们的初始化目的。那我们之前说的,只有在完成了构造方法之后我们的对象才算正在实例化好,可是我们明明没有完成我们的构造方法,却在构造之中就使用了this,那对象还没有实例化好,这个this从和而来呢?
其实我们实例化对象的时候大体上分为两步,先是给对象分配空间,然后才是调用我们的构造方法,所以再分配完空间之后我们的对象其实上就已经存在了。这里再提一嘴,之前说过的,我们的成员变量是会有一个默认值的,所以不需要我们初始化,那是因为编译器在分配空间的时候就已经帮你初始化过了,所以不是不初始化,只是不需要你来初始化!
如果是在一个构造方法中调用另一个构造方法,那我们this()的这一行必须要写在第一行,不然:
在这里插入图片描述
就会报错,还要注意的是,切记不可一直套娃:
在这里插入图片描述
这样子是不是在两个构造方法之间就会一直循环下去?

最后我们再来想一下,难道我们就不能在定义变量的时候就顺手给它初始化一下?

    class Dog{
        public String  name="cyt";
        public int age=20;
        public String sex="man";

在这里插入图片描述
这个就好比我们给模板上面就刻上了几行字,那么是不是根据模板做出来的对象上面也会有相同的字样啊。但是在实际情况下,我们不同的对象应该是要有不同的信息的,所以我们并不是很推荐就在定义的时候就初始化了。
好的兄弟们,关于类和对象我们目前掌握到这里也足够了,希望兄弟们能够真正学会这个类和对象。
百年大道,你我共勉哦!!!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值