JavaSE基础知识(十)--Java的this关键字

Java SE 是什么,包括哪些内容(十)?

本文内容参考自Java8标准
前言:可看可不看
当年我决定自学Java的时候,这个this关键字曾经困扰了我很久,我怎么都没有办法理解"当前对象"等,都是"当前"…,后来我理解了,用"当前"表述其实没有什么问题,只是对于初学者来说,理解起来会有很大的问题。
下面的内容可能会有一点啰嗦
还是要从前面我写过的博文中的基础知识说起:
先来回顾一下Java的编程过程:
⑴、首先就是创建新的数据类型:类

// 创建新的数据类型:类
  //创建一个人类(Person):比较通俗易懂
     public class Person{
          //表示人类的姓名:
          private  String  name;
          //表示人类的性别:
          //private  String  sex;
          //表示人类的年龄
          private  int  age;
          //如果有必要,创建构造方法。
          //也可以不创造构造方法,直接使用默认构造方法。
          public Person(){}
          //创建一些与人类行为有关的方法:
          //方法一:
              //...此处省略具体的方法内容。
          //方法二:
              //...此处省略具体的方法内容。
          //...可以有很多的方法
     }  

⑵、利用现成的类创建对象,按需改变变量的值或调用对应的方法来实现功能。
这里有一点很重要,就是能创建很多个对象,所以有很多书中会将this解释为是当前对象。

// 创建对象,改变变量,调用方法。
 //创建对象:
 Person p = new Person()//改变变量:
 p.name = "小王"//调用方法(假设有一个work()方法):
 p.work()//代码直至到这里都没有什么问题。

⑶、执行代码,得出结果。

来,我们再回顾一下:你会发现在中,首先是Person p = new Person(),然后利用p去修改的变量,利用p去调用的方法。那么p是什么呢?p是你创建当前Person对象的时候给这个对象的存储空间取的名称,这个对象的存储空间中拥有Person类中的所有变量和所有方法,所以你可以利用这个存储空间的名称p去修改变量和调用方法。以实现你需要的功能,同时p.name,p.work()正是Java面向对象编程的代码体现。
那么问题来了:

在⑴中,也就是你创建数据类型的过程中,会不会有类似p.name,p.work()这种代码的需要?答案很肯定,绝对会有,但是,你在创建类的时候,并没有创建对象(也就是没有代表对象的名称,例如p),那么,怎么办?Java的创建者想到最后,用this吧。

如果你对上面的解释还是不明白,那我再用另外的方式解释一下:

this的作用就是在你创建对象之前(也就是Person p = new Person()之前)暂时代替p,说白了也就是在类中需要修改变量,需要调用方法的时候,暂时用this代替。待Person p = new Person()执行之后,再用p代替this,这样就达到了要求。如果你创建对象的时候取名是p1:Person p1 = new Person(),那么this代替的就是p1.

如果你对上面的解释还是不明白,那我再再用另外的方式解释一下:

在你创建对象,并为对象引用取了名称之后(Person p = new Person()),你使用的是引用的名称( p ),但是在你还未创建对象,没有对象引用名称来使用的时候,就使用this------因为在你编写类的时候,一样是利用的面向对象思想。所以,在类中,肯定会涉及到对象引用的需要。这个时候就用this。

如果你对上面的解释还是不明白,我再用生活中的一个例子举例:
不能保证完全贴切,但是比较形象:
一家餐饮店很有名,每天都爆满,座位很稀缺,那么肯定会出现占座的情况,于是店主就为先来的人提供了专门占座的东西(为朋友占座)—一个靠枕,那么这个靠枕代表的就是即将要来的这个人(还没有来,也就是没有具体的对象,所以这个靠枕就是this),过了十五分钟,来了一个人,名字叫小王(这个时候通过Person p = new Person()创建了一个具体的对象,代表了小王),那么很显然,这个靠枕代表的就是小王,如果来的是小李,那么这个靠枕代表的就是小李。所以,为什么说this代表的是当前对象了。
最后,再通过代码来解释一下this:

// 代码解释this:
    public class Person{
           //表示人类的姓名:
           private  String  name;
           //表示人类的性别:
           //private  String  sex;
           //表示人类的年龄
           private  int  age;
           //创空建构造方法。
           public Person(){}
           //创建有形式参数的构造方法:
           public Person(String name,String sex,int age){
               //这个方法体要实现的内容就是将实际参数赋值给类变量
               //那么类变量怎么表示?这个时候还没有具体的对象引用名称。
               //如果有就用具体的对象引用名称,问题是现在没有,只能用this暂时代替
               this.name = name;
               this.sex = sex;
               this.age = age;
               //当你创建对象的时候,具体的对象的name,sex,age的值
               //都会是你创建对象时实际输入的值。
               //Person p = new Person("小王","男",25);对象p的name,sex,age
               //分别是"小王","男",25.
               //Person p1 = new Person("小刘","女",23);对象p1的name,sex,age
               //分别是"小刘","女",23.
               //一一对应的。
           }
           //创建一些与人类行为有关的方法:
           //方法eat(),代表吃饭。
              public void eat(){
                 //方法体省略。
              }
           //方法work(),代表工作。
              public void work(){
                 //如果这个时候类中的work()方法想调用eat()方法如何操作呢?
                 //对,用this暂时代替实际的对象引用去调用。
                 this.eat();
                 //其他方法体内容省略...
              }
              
      }  

最后,简单总结一句:因为在创建类的时候,没有具体的对象,也就是没有具体的对象标识符,所以暂时用this代替!在创建类的时候,在你需要使用对象标识符的地方全部使用this!
以下内容为Java编程思想第四版中对this关键字的解释
如果有同一类型的两个对象,分别是a和b,你可能想知道,如何才能让这两个对象调用同一个方法呢(比如下面举例的peel()方法)?
代码举例:

// 代码举例
    class Banana{
        void peel(int i){
            //方法体
        }
    } 
    public class BananaPeel{
       public static void main(String[] args){
          Banana a = new Banana(),
                 b = new Banana();
          a.peel(1);
          b.peel(2);    
       }
    }

如果只有一个peel()方法,它如何知道是被a还是被b所调用的呢?
为了能用简便、面向对象的语法来编写代码--------即"发送消息给对象",编译器做了一些幕后工作,它暗自把"所操作对象的引用"作为第一个参数传递给peel(),所以,在幕后,上述两个方法调用就变成了这样:
Banana.peel(a,1);
Banana.peel(b,2);
提示:个人认为,这是在编译以后,编译器做好的幕后工作。编译以后,编译器将所有的引用分别作为所有方法的第一个参数放进了方法中。
这是内部的表示形式,我们并不能这样书写代码,并试图通过编译。
假设你希望在方法内部获得对当前对象的引用,由于这个引用是由编译期"偷偷"传入的。所以没有标识符可用。但是,为此,有个专门的关键字:this。this关键字只能在方法内部使用,表示对"调用方法的那个对象"的引用。this的用法和其他对象引用并无不同。但要注意,如果在方法的内部调用同一个类的另一个方法,就不必使用this,直接调用既可,当前方法中的this引用会自动引用于同一个类的另一个方法。
代码示例:

// 同一个类中的方法互调
     //类名称Apricot
     public class Apricot{
        //方法pick();
        void pick(){}
        //方法pit()
        void pit(){
           //直接调用方法pick(),不用this.
           pick();
        }
     }

在pit()内部,你可以写this.pick(),但无此必要,编译器能帮你自动添加,只有当需要明确指出对当前对象的引用时,才需要使用this关键字,例如,当需要返回对当前对象的引用时,就常常在return语句里这样写:

// 返回当前对象的引用
     //类名称Leaf
     public class Leaf{
        //int类型变量i,初始化为0.
        int i = 0;
        //方法increment(),返回类型为Leaf.
        Leaf increment(){
           //i值+1.
           i++;
           //返回当前对象的引用.
           return this;
        }
        //方法print()
        void print(){
          //打印i值。
          Syatem.out.print("i="+i);
        }
        //程序执行入口方法main()
        public static void main(String[] args){
             //创建Leaf对象,名称为x。
             Leaf x = new Leaf();
             //多次调用方法increment()。
             //调用一次i值就+1.
             //因为调用increment()方法的结果就是返回当前对象。
             //所以可以进行多次调用.
             //也就是在同一条语句里对同一个对象执行多次操作。
             x.increment().increment().increment().print();
        }
     }

this关键字返回了对当前对象的引用,所以很容易在一条语句里对同一个对象执行多次操作。
this关键字对于将当前对象传递给其他方法也很有用:

// 将当前对象传递给其他方法
     //类Person
     class Person{
        //方法eat,带形式参数Apple类型。
        public void eat(Apple apple){
           //调用方法获得一个对象。
           Apple peeled = apple.getPeeled();
           //打印字符串"Yummy".
           System.out.print("Yummy");
        }
     }
     //类Peeler
     class Peeler{
         //静态类方法peel,带一个形式参数类型Apple.
         static Apple peel(Apple apple){
              //返回当前参数引用,也就是apple。
              return apple;
         }
     }
     //类Apple
     class Apple{
         //方法getPeeled,返回类型为Apple.
         Apple getPeeled(){
             //返回类型为Apple类型,Peeler.peel(this)返回的类型就是Apple。
             //将当前对象的引用作为实际参数传入(this代表的就是当前对象的引用)
             return Peeler.peel(this);
         }
         //Apple调用了外部的方法(Peeler的peel()方法),有的时候你必须这么做,
         //将执行由于某种原因而必须放在Apple外部的操作(比如你不想重复代码,
         //将一个功能专门写在了一个类中),为了将其自身传递给外部方法,
         //必须使用关键字this。
         //如果不懂上面的举例:可能存在一个工具类,专门接受对象的引用,
         //然后执行相应的代码。这种工具类都会是外部类,而并不是每次需要的时候
         //都写一遍。相对于每次写一遍,我们更愿意只传递一个引用。
     }
     //类PassingThis
     public class PassingThis{
         //程序执行入口方法main.
         public static void main(String[] args){
            //创建Person对象,调用eat方法,传入的实际对象是一个Apple对象。
            new Person().eat(new Apple());
            //解析一下执行结果,从这里开始梳理程序执行代码顺序。
            //首先是创建了Person对象,但是Person没有构造方法。
            //而是直接调用了eat()方法。eat()方法需要一个Apple类型的参数。
            //所以直接创建了一个Apple对象,Apple也没有构造方法。
            //直接进入了eat方法体。
            //Apple peeled = apple.getPeeled();通过Apple类型的getPeeled()
            //方法获得了一个Apple对象,引用名称是peeled.
            //进入Apple的getPeeled()方法:return Peeler.peel(this);
            //直接进入的是Peeler类的peel方法,同时传入了一个引用this,这个this
            //实际代表的就是new Person().eat(new Apple());里面的new Apple();
            //这个对象的引用。
            //Peeler的peel方法需要一个Apple类型的对象作为实际参数,
            //返回这个对象的引用。
            //这段代码就是为了演示而创建的。实际到最后就是返回了new 
            //Person().eat(new Apple());中new Apple()创建的这个对象的引用。
            //结果只会打印一个"Yummy"字符串。
         }
     }

结果示例:
JavaSE基础知识(十)--Java的this关键字_第1张图片

PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正!

你可能感兴趣的:(Java,SE)