ClassAndObject -类与对象 - java(万字篇)

在这里插入图片描述


代码样本4(由图12得出的结论,修改样本3)



class Person{

    // 普通成员变量 都是属于对象的

    public String name;// 引用类型(存的字符串首字符地址),默认值为null

    public int age;// 默认值为 0



    public static int count;

}



public class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();// 没意义,静态成员变量属于类,所以实不实例化一个对象。没有影响

        Person.count++;

        System.out.println(Person.count);

        System.out.println("======================");

        //Person person2 = new Person(); 没意义



        Person.count++;

        System.out.println(Person.count);

    }

}// 图 13



图13

在这里插入图片描述


代码样本5 (调用【静态成员方法/类方法】)



class Person{

  // 静态成员方法/类方法

    public static  void staticFunc(){

        System.out.println("static::func()");

    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        Person.staticFunc();

    }

}// 图 14



图14

在这里插入图片描述


注意事项 1(能不能在方法中 创建一个 被 static修饰的变量)



class Person{

    // 普通成员办法

    public void eat(){

        static int size = 0;// 该写法是错的

    }



    // 静态成员方法/类方法

    public static  void staticFunc(){

       static int size2 = 0;// 该写法是错了

    }

}// 图 15



图15


在这里插入图片描述

总结:



    无论是 普通成员方法还是静态成员方法,都不能在其内部创建一个被static修饰的变量

因为 被static修饰了的变量,该变量就属于类了(类变量/静态变量)。

 而你把一个(类变量/静态成员变量)写在方法里,就意味着属于方法(是一个局部变量,不再是 类变量了),而不属于类

 所以冲突了,不合适,导致编译器报错。



还有一个原因

拿eat来说, eat是普通成员方法,是需要对应的引用来调用的。但是如果可以定义static的变量, 通过 类名Person 就能调用。

 一个需要对象,不需要类;另一个需要类,不要有对象,两者就像在这里卡bug一样存在冲突。所以这种写法是错的



而静态成员方法中,之所以不能创建一个被 static修饰的变量,是因为,你是在内部定义的。在内部定义,就意味着属于方法,而不属于类,所以错的



 总得来说: 只要是被 static 修饰的变量/方法,都是属于类的。




注意事项 2(能不能在方法中调用方法)


普通成员方法 调用动态成员方法


class Person{

    public String name = "author";



    public void eat(){

        staticFunc();// 可以这样写,没有警告

        System.out.println(name+"正在吃饭.");

    }



    public static  void staticFunc(){

        System.out.println("static::func()");

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person p = new Person();

        p.eat();// 图 16

    }

}由图得知,普通成员方法 可以调用 动态成员方法 ,因为普通成员方法是依赖对象的,静态成员方法 不依赖对象

 所以 调用普通成员方法,new一个对象,对于静态成员方法来说没有任何影响,你用你的引用,我用我的类



图16

在这里插入图片描述

&****

静态成员方法/类方法 调用 普通成员方法


class Person{

    public String name = "author";



    public void eat(){

        System.out.println(name+"正在吃饭.");

    }



    public static  void staticFunc(){

        eat();// error  图17

        System.out.println("static::func()");

    }

}



图17

在这里插入图片描述

由图17得知,静态成员方法 是无法调用 普通成员方法的

原因也很简单,静态成员方法不需要对象,而普通成员方法需要对象

静态成员通过类名来调用,因此不需要new对象,那么 eat() 谁调?

没有对象。不能调,所以编译器会报错。

当然硬要调用也行, 在 eat()前面 new一个对象,用该对象的引用 来调用 普通成员方法 eat()


总结



普通成员方法(有对象) 能调用 静态成员方法(单身贵族)

而 静态成员方法(单身贵族) 不能调用 普通成员方法(没对象)



 现在知道前面博客的一些例题,使用方法的时候,为什么都用static, 因为被static修饰的方法是可以直接调用的,不需要new对象

 不是new对象麻烦,而是当时知识储备有限,明白了吧。




这里讲一个dan疼的面试题

============================================================================

main 函数为什么是静态的?

首先 main 函数 是不是静态都可以!!!

这个东西取决于 JVM 的规则。

main 之所以 是 静态的,是因为 在设计 JVM的时候,就这么设计的

所以 main 只有被static 修饰的时候,JVM才认为它是main函数

举个例子:

你去超市买东西,要付钱吧。你总不能拿东西不给钱,给警察抓吧?

买东西要给钱 和 在Java中 main方法需要 static 修饰 是一样的

是默认的规则,是你必须要遵循的。 当然 你非要 不使用用 static修饰main函数

没关系,问题就在于怎么new一个对象 辅助 编译器 在编译器 进入main函数,

而且,还没考虑 main函数 是程序运行一开始就要进入,因为main函数是程序的入口

想想就麻烦,我是做不出来。

总之做一个安分守己的好公民,买东西要给钱;写main方法 使用 static来修饰


在这里们再稳固一下知识

==========================================================================


class Person{

    public String name = "author";



    public void eat(){

        staticFunc();

        System.out.println(name+"正在吃饭.");

    }



    public static  void staticFunc(){

        System.out.println("static::func()");

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person p = null;// 这个引用 不指向 任何的对象



      // 两个引用指向同一个对象

        Person p2 = new Person();

        Person p3 = p2;// p3 这个引用 指向 p2 指向的对象



        // 一个引用能不能指向多个对象?

        Person person = new Person();

         person = new Person();

         person = new Person();// 这个是person真正指向的对象

        // 答案是不能,person 此时指向的对象是最后一次 new的对象



    }

}




引用 一定是在栈上吗?

==========================================================================


 答案是 不是



代码实例



class Person{

    public String name = "author";



    public void eat(){

        staticFunc();

        System.out.println(name+"正在吃饭.");

    }



    public static  void staticFunc(){

        System.out.println("static::func()");

    }

}

public class ClassAndObject {

    Person person = new Person();

    public static void main(String[] args) {

        ClassAndObject classAndObject = new ClassAndObject();

    }

}// 图 18



图18

在这里插入图片描述


总结 static 关键字

============================================================================


    1、修饰属性

     修饰属性,Java静态属性和类相关, 和具体的实例无关. 换句话说, 同一个类的不同实例共用同一个静态属性



    2、修饰方法

    如果在任何方法上应用 static 关键字,此方法称为静态方法。

    静态方法属于类,而不属于类的对象。

    可以直接调用静态方法,而无需创建类的实例。

    静态方法可以访问静态数据成员,并可以更改静态数据成员的值。



注意事项1: 静态方法和实例无关, 而是和类相关. 因此这导致了两个情况:



    1. 静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的).

    2. this和super两个关键字不能在静态上下文中使用(this 是当前实例的引用, super是当前实例父类实例的引用, 也

    是和当前实例相关).



注意事项2



    1. 我们曾经写的方法为了简单(不用new对象), 都统一加上了 static. 但实际上一个方法具体要不要带 static, 都需要是情形而定.

    2. main 方法为 static 方法.



注意事项3



 1。  被final(使其具有常量属性)修饰的成员变量,与成员变量是不是存储在方法区或者堆上是无关的

           简单来说: 一个对象存储到哪里 和 你是否被final修饰无关

   还是那句话,凡是被 static 修饰的成员变量或者成员方法(又称静态成员变量和静态成员方法),都是存储在方法区中

 没有被static修饰的成员变量 或者 方法(又称:普通成员变量 和 普通成员方法)

都需要通过new对象,来实体化对象,通过指向对象的引用来调用我们普通成员变量和方法。



注意事项4



 以后在工作中,遇到被static修饰的成员变量和方法,意味着只有成员方法和变量一份,不能轻易动,因为你不知谁使用了它。不知道它涉及范围有多广

 能在不使用 static 的情况,完成程序的编程,就尽量不要使用。(就像C语言的全局变量一样,多了不安全,牵扯太多,又不能随便动)

 反正以后只要遇到static修饰的,你就当祖宗供着就行了。




在这里大家想想如果我们的类体中,字段/属性/成员变量,越来越多, 如果我们想打印一下内容,要写很多方法,很麻烦

======================================================================================================================

先来看看下面的代码,我们一步步来看


代码样本1


class Person{

    public String name;

    public int age;



    public static int count;



    public void eat(){

        System.out.println(name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名"+name+"年龄"+age);

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

       Person person = new Person();

        System.out.println(person);// 图 19

    }

}



图19

在这里插入图片描述


程序结果图解流程图
点击 println 》 Ctrl+点击,进入println函数,得图20
图20

在这里插入图片描述


点击 valueOf 》 Ctrl+点击,进入valueOf函数,得图21
图21

在这里插入图片描述


点击 toString 》 Ctrl+点击,进入toString函数,得图22
图22

在这里插入图片描述


通过我们层层解析,我发现它最后是通过 toString 来转换



  那么我们可不可以 自己写一个 toString 方法  

   答案是可以的



代码样本2


class Person{

    public String name;

    public int age;



    public static int count;



    public void eat(){

        System.out.println(name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名"+name+"年龄"+age);

    }

    public String toString(){// 这里我们写的toString 方法 ,返回一个字符串

        return "author";

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        System.out.println(person);// 图 23

    }

}



图23

在这里插入图片描述

由图23得知,结果很有意思 输出的是我们自己写 toString 返回值

这里涉及到 动态绑定,这个后面讲到相应的内容,我们再来讲这个

**你只需要知道,我们在打印数据时,如果我们写了一个toString的方法

编译器,就会执行我们所写的 toString 方法,而不是系统默认的toString**

执行我们所写的 toString方法 的 前提是 toString 方法 的名字不能变,是定死了的,缺胳膊少腿 或者 画蛇添足都是不行的


 例如 

 public String toString1(){

   return "author";

 }



 public String toStrin(){

   return "author";     

 }



 你可以仔细去看看图23 , 我们的写法是与编译器默认的toString 写法是相同的




也就是说我们可以不用调用方法,就能输出一样的效果


代码样本(打印成员变量的值)


class Person{

    public String name;

    public int age;



    public static int count;



    public void eat(){

        System.out.println(name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名:"+name+" 年龄:"+age);

    }

    public String toString(){// 这里我们写的toString 方法 ,返回一个字符串

        return"姓名:"+name+" 年龄:"+age;

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        System.out.println(person);// 图 24

    }

}



图24

在这里插入图片描述


代码样本1~3,只是来说明 println 函数 是通过 调用 toString 方法来实现的



有的人可能会说,这跟我们 通过对象去调用成员方法,有什么区别?



 都是自己手敲的。

 

 区别就在于 toString函数 可以 通过快捷键和鼠标来让编译器自动生成

操作流程图: 图25 》 图26 》 图27 》 图 28



图25

在这里插入图片描述


图26

在这里插入图片描述


图27

在这里插入图片描述


图28

在这里插入图片描述


代码如下


class Person{

    public String name;

    public int age;



    public static int count;



    public void eat(){

        System.out.println(name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名:"+name+" 年龄:"+age);

    }



    @Override// 这个类似一个检查功能,检查我们要重写的东西,与原来的一不一样

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", age=" + age +

                '}';

    }// 这个功能 涉及 我们后面的内容 "重写", 这里暂时不讲,有个概念就行

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        System.out.println(person);// 图 29

    }

}




图29

在这里插入图片描述


总结:


toString 方法会在 println 的时候被自动调用.

将对象转成字符串这样的操作我们称为序列化(把一个对象转换成字符串). 反序列化(把字符串转换成对象)

toString 是 Object 类提供的方法, 我们自己创建的 Person 类默认继承自 Object 类, 可以重写 toString 方法

我们自己写的转换字符串方法. (关于继承和重写这样的概念, 我们后面会重点介绍).

@Override 在 Java 中称为 “注解”, 此处的 @Override 表示下面实现的 toString 方法是重写了父类的方法. 关于注解后面的课程会详细介绍…

IDEA快速生成Object的toString方法快捷键:alt + f12 / 0 (insert)


但是现在有一个问题


上代码


class Person{

    // 如果有人 在某天,改变了 Person 类中 成员变量名

// name 》 myName

    public String  myName;

    public int age;



    public static int count;



    // 然后就 只把 Person 类 中的 name 都改 myName

    // 虽然这样做 在自己的类中,不影响 person类中的程序运行



    public void eat(){

        System.out.println( myName+"正在吃放");

    }



    public void print(){

        System.out.println("姓名:"+ myName+" 年龄:"+age);

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" +  myName + '\'' +

                ", age=" + age +

                '}';

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        person.name = "bit";//图30

        // 但是 如果有其他类,在类体中调用 或者 访问 该成员变量,就存在着问题

        // 因为 别人调用语法: 引用.成员变量名, 而你改名了,别人不知道啊

// 所以 别人也要改,但是如果调用它的类有很多,那么一个个改名,就不现实



    }

}



图30

在这里插入图片描述


在这里引入一个概念 封装

===========================================================================

什么叫封装?



    <<代码大全>> 开篇就在讨论一个问题: 软件开发的本质就是对程序复杂程度的管理. 如果一个软件代码复杂程

    度太高, 那么就无法继续维护. 如何管理复杂程度? 封装就是最基本的方法.

    在我们写代码的时候经常会涉及两种角色: 类的实现者和类的调用者.

    封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了.

    这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度



private实现封装



 private/ public 这两个关键字表示 "访问权限控制" .

被 public 修饰的成员变量或者成员方法, 可以直接被其他类的调用者使用.

被 private 修饰的成员变量或者成员方法, 不能被其他类的调用者使用.

换句话说, 类的使用者根本不需要知道, 也不需要关注一个类都有哪些 private 的成员. 从而让类调用者以更低的成本来使用类.




代码实例


class Person{



    private String  name;// 此时 name 被 private 所修饰(被private包装了)

    // 普通成员变量 name,非本类内部,不可调用

    // 图31,由图得知 name已经不能 其他类的调用者所调用



    public int age;



    public static int count;



    private void eat(){

        System.out.println( name+"正在吃放");

    }  // 普通成员方法 eat,非本类内部,不可调用

    // 图31,由图得知 eat已经不能 其他类的调用者所调用



    public void print(){

        System.out.println("姓名:"+ name+" 年龄:"+age);

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" +  name + '\'' +

                ", age=" + age +

                '}';

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        person.name = "bit";

        person.age = 10;

        person.eat();

    }

}



图31

在这里插入图片描述


总结



    private 不光能修饰字段, 也能修饰方法

    通常情况下我们会把字段设为 private 属性, 但是方法是否需要设为 public, 

    就需要视具体情形而定. 一般我们希望一个类只提供 "必要的" public 方法, 而不应该是把所有的方法都无脑设为 public.




那么这样写的好出在哪?虽然说安全性很强,但是我要用里面的东西,怎么办?


这时就需要 getter和setter方法 来创建公开的2个接口,用来输出和输入

=======================================================================================================

代码实例



class Person{



    private String  name;// null

    public int age;// 0

    public static int count; // 0



    public String getName(){

        // 读取 Person 类中的 普通成员变量存储的数据,将其返回(输出)

        return name;

    }

    public void setName(String myName){

        //  输入 一个 字符串 来修改 Person 类中 name 的 值

        this.name = myName;

    }



    public void eat(){

        System.out.println( name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名:"+ name+" 年龄:"+age);

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" +  name + '\'' +

                ", age=" + age +

                '}';

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        person.setName("author");

        System.out.println(person.getName());

        // 图 32,由图可知 赋值 和 读值 成功了,没问题

    }

}



图32

在这里插入图片描述

由 图 32 ,得出结论 private 和 (setter,getter)结合使用 是没问题的,成功解决了 类的实现者,被修改成员变量的名称,而无法进行访问的问题。

然而还是存在某种问题,如果你修改 setter 和 getter的方法名,一样会出现问题

但是一般人不会去改,人家要改你也防不住

所以做人要厚道 不要去改。 这是默认的道德规则。


setter 和 getter 方法 和 前面 toString 一样,有快捷的方法,让编译器自动为我们添加



 跟 toString方法一样的流程,仔细 观察 图 26 的选项中 有 Getter and Setter 选项

 选择它,之后就图 27 一样,自己去选择成员变量  去生成对应   Getter and Setter 的方法

 这里我就不再说明




当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this, 相当于自赋值. this 表示当前实例的引用.



class Person{



    private String  name;// null

    private int age;// 0

    public static int count; // 0



    public String getName(){

        return name;

    }

    public void setName(String name){

        name = name;

    }



    public int getAge() {

        return age;

    }



    public void setAge(int age) {

        this.age = age;

    }



    public void eat(){

        System.out.println( name+"正在吃放");

    }



    public void print(){

        System.out.println("姓名:"+ name+" 年龄:"+age);

    }



    @Override

    public String toString() {

        return "Person{" +

                "name='" +  name + '\'' +

                ", age=" + age +

                '}';

    }

}



public  class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

        person.setName("author");

        System.out.println(person.getName());

        person.setAge(10);

        System.out.println(person.getAge());

    }

}// 图 33



图33

在这里插入图片描述


总结



 getName 即为 getter 方法, 表示获取这个成员的值.

setName 即为 setter 方法, 表示设置这个成员的值

当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this, 相当于自赋值. this 表示当前实例的引用.

不是所有的字段都一定要提供 setter / getter 方法, 而是要根据实际情况决定提供哪种方法.




构造方法

===================================================================


 构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作




语法规则



    1.方法名称必须与类名称相同

    2.构造方法没有返回值

    3.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)



那么构造方法是干嘛的?在了解构造方法是干嘛的之前,需要了解一个对象的产生(也就是说对象的实例化/new的执行过程)


new 执行过程



 1.为对象分配内存空间

 2.调用合适的构造方法



上面这两步完成之后,我们的对象才真正产生了。(意味着调用完构造方法之后,我们的对象才真正产生了

注意 合适 这两个字,意味着构造方法不止一个。就好比鞋子很多,但要挑合适的


现在我们来写一个构造方法,代码如下



class Person{

    private String name;

    private  int age;



    public Person(){// 构造方法

        System.out.println("Person()::不带参数的构造方法");

    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        // 前面我们也说了,构造方法 是在实例化对象(new对象)的过程中,会调用合适的构造方法

        // 所以 我们想要调用 构造方法时,只需要new对象就行了。

      Person person = new Person();// 图34

    }

}



图34

在这里插入图片描述

很多人可能会问,你有输出,怎么说是不带参数的构造方法?这只是让你理解 在new对象的过程中,会调用构造方法。


再来看看这个程序



class Person{

    private String name;

    private  int age;



//    public Person(){// 构造方法

//        System.out.println("Person()::不带参数的构造方法");

//    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();// 图35

        // 由图得知,当我们将自己写构造方法屏蔽时,照理说 是不能 new 对象的

        //因为 new 需要调用构造方法,才能实现的

        // 而现在代码执行完成,那么就意味着编译器在编译 执行new对象语句时,发现我们没有写构造方法

        // 会自动帮我们生成一个无参数参数的构造方法,如下所示,所以才没有任何的输出结果

        例如

              public Person(){

            }

    

    }

}



图35

在这里插入图片描述


得出结论:


  如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数

  也就是说一个类至少有一个构造方法,就算你没有写。




另外注意一点 如果我们写的 类中构造方法被private所修饰,那么其他类中 是不可使用 该类 去new 对象



 当然 构造方法 所处类的内部是可以被调用的,因为 private 就是 将 所修饰部分 私有化,只有内部才能使用。外者不能使用

   既然 构造方法 可以私有化,肯定由它的作用: 实现 单例模式 的 大前提,现在不讲,还不会



代码如下


class Person{

    private String name;

    private Person(){

        System.out.println("不带参数的构造方法");

    }

    Person p = new Person();

}



public class ClassAndObject {

    public static void main(String[] args) {

        Person person = new Person();

    }// 图 36

}



图36

在这里插入图片描述


现在我们来写一写 多个构造方法,加深对 “合适” 的理解



class Person{

    private String name;



    public Person(){

        System.out.println("不带参数的构造方法");

    }



    public Person(String name){

       this.name = name;// 给Person类中 成员变量传参,类似 Setter 方法

        System.out.println("Person(String)::带一个String类型参数的构造方法");

    }

注意 this 代表当前的对象 这种说法是错误的

 因为 如果你要调用当前对象的前提是产生一个对象(调用完合适的构造方法才能实例化对象)

 而我们现在这个程序,构造方法里就用this了,说明此时的 this 就不能代表当前的对象了

 只能说完成 new的执行过程的第一步: 为对象分配内存,有了内存就有了地址,this此时代表当前对象的引用

}



public class ClassAndObject {

    public static void main(String[] args) {

        // 调用不带参数构造方法

        Person person = new Person();

        System.out.println("=================");

        // 调用 带一个 参数的构造方法

        Person person1 = new Person("author");

    }// 图 37

}



图37

在这里插入图片描述

你们有没有发现 构造方法支持重载. 规则和普通方法的重载一致

构造方法重载规则:类名相同,参数的类型和个数,两者中,至少有一个不同项。

调用构造方法时,编译器会自动筛选调用合适的构造方法


注意: 若类中定义了构造方法,则默认的无参构造将不再生成.



class Person{

    private String name;



//    public Person(){

//        System.out.println("不带参数的构造方法");

//    }



    public Person(String name){

        this.name = name;// 给Person类中 成员变量传参,类似 Setter 方法

        System.out.println("Person(String)::带一个String类型参数的构造方法");

    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        // 调用不带参数构造方法

        Person person = new Person();

        System.out.println("=================");

        // 调用 带一个 参数的构造方法

        Person person1 = new Person("author");

    }// 图 38

}



图38

在这里插入图片描述

总得来说 构造方法的意义是:用来构造对象的。

之前我们写的程序都没有写构造方法,但是现在我刚才讲了编译器会自动帮我们生成一个无参数的构造方法

你只需要要明白,没有构造方法 是无法 实例化一个对象的。


在我们这篇博客代码中 this 频繁出现。现在我们就来讲解一下this的用法

=====================================================================================================


 1.this.data  调用当前的对象的 属性/字段/成员变量

 2.this.func() 调用当前的对象的方法

 3.this()      调用当前对象的其他构造方法




第一种我就不说了,前面已经见过它的应用了,我来讲第二种



class Person{

    private String name;



    public void eat(){

        System.out.println(name + "正在吃饭");

    }

    public void print(){

        this.eat();// 调用当前对象的eat方法,这里重复强调一个问题 静态成员方法中不能使用this

        // 写错也没关系,编译器会提示你写错了(红色警告波浪线)

        System.out.println("姓名:" + name);

    }

}




&ensp;

第三种 this() 调用当前对象的构造方法



class Person{

    private String name;



    public Person(){

        this();

        // 注意不能这么去写,因为 this() 表示调用当前对象的构造方法

        // 而现在Person 就是当前的构造方法,两者嵌套使用,会造成死循环

        // Person(){} 调用 this(), this() 调用 Person(){}

        // 而且编译器也出现 红色波浪线警告 图39

        System.out.println("不带参数的构造方法");

   }

}



图39

在这里插入图片描述


那么 this() 在上述情况下 该怎么使用?



 调用 其他 有参数的构造方法就可以了



代码如下:


class Person{

    private String name;



    public Person(){

        this("author");

        System.out.println("不带参数的构造方法");

    }

    public Person(String name){

        System.out.println("带有一个参数的构造方法");

    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        // 现在我们来通过new对象,来调用无参数的构造方法

        // 在进入无参数的方法后,执行第一条语句,就是this("author")

        // 意思是 调用带有一个参数的构造方法

        // 调用完成之后,再执行 无参数的构造方法 的 输出语句

        // 也就是说 先打印 "带有一个参数的构造方法" , 后打印 "不带参数的构造方法"

        Person person = new Person();// 图40



    }

}



图40

在这里插入图片描述


但是 注意一点 this()在构造方法中 去调用 其他构造方法时,只能放在该构造方法的第一句的位置,this()才能使用( 图41 )。而且 this() 这种方法,只能用于构造方法中。


图41

在这里插入图片描述


代码块

==================================================================


本地代码块

实例代码块

静态代码块

同步代码块



# 如何快速更新自己的技术积累?

*   在现有的项目里,深挖技术,比如用到netty可以把相关底层代码和要点都看起来。
*   如果不知道目前的努力方向,就看自己的领导或公司里技术强的人在学什么。
*   知道努力方向后不知道该怎么学,就到处去找相关资料然后练习。
*   学习以后不知道有没有学成,则可以通过面试去检验。

**我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!**

**以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目**

![八年CRUD,疫情备战三个月,三面头条、四面阿里拿offer面经分享](https://img-blog.csdnimg.cn/img_convert/ca451f44280157580c6d5b33a5f165ae.webp?x-oss-process=image/format,png)

![八年CRUD,疫情备战三个月,三面头条、四面阿里拿offer面经分享](https://img-blog.csdnimg.cn/img_convert/92934aa5989aa79dee2489b9157b9c2c.webp?x-oss-process=image/format,png)


Person 就是当前的构造方法,两者嵌套使用,会造成死循环

        // Person(){} 调用 this(), this() 调用 Person(){}

        // 而且编译器也出现 红色波浪线警告 图39

        System.out.println("不带参数的构造方法");

   }

}



图39

在这里插入图片描述


那么 this() 在上述情况下 该怎么使用?



 调用 其他 有参数的构造方法就可以了



代码如下:


class Person{

    private String name;



    public Person(){

        this("author");

        System.out.println("不带参数的构造方法");

    }

    public Person(String name){

        System.out.println("带有一个参数的构造方法");

    }

}



public class ClassAndObject {

    public static void main(String[] args) {

        // 现在我们来通过new对象,来调用无参数的构造方法

        // 在进入无参数的方法后,执行第一条语句,就是this("author")

        // 意思是 调用带有一个参数的构造方法

        // 调用完成之后,再执行 无参数的构造方法 的 输出语句

        // 也就是说 先打印 "带有一个参数的构造方法" , 后打印 "不带参数的构造方法"

        Person person = new Person();// 图40



    }

}



图40

在这里插入图片描述


但是 注意一点 this()在构造方法中 去调用 其他构造方法时,只能放在该构造方法的第一句的位置,this()才能使用( 图41 )。而且 this() 这种方法,只能用于构造方法中。


图41

在这里插入图片描述


代码块

==================================================================


本地代码块

实例代码块

静态代码块

同步代码块



# 如何快速更新自己的技术积累?

*   在现有的项目里,深挖技术,比如用到netty可以把相关底层代码和要点都看起来。
*   如果不知道目前的努力方向,就看自己的领导或公司里技术强的人在学什么。
*   知道努力方向后不知道该怎么学,就到处去找相关资料然后练习。
*   学习以后不知道有没有学成,则可以通过面试去检验。

**我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!**

**以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目**

[外链图片转存中...(img-hD2QMe2Y-1719251871661)]

[外链图片转存中...(img-5PqJdFCx-1719251871662)]


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值