大家先来看看一段代码然后来猜测一下输出的值是什么
大神请绕过1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package yp.JavaSE.Review_07;
/**
* @author RickYinPeng
* @ClassName Test_04
* @Description
* @date 2019/1/18/14:06
*/
public class Test_04 {
public static void main(String[] args) {
HttpServlet httpServlet = new MyHttpServlet();
httpServlet.service();
}
}
class HttpServlet {
public void service(){
System.out.println("调用HttpServlet的service方法");
doGet();
}
public void doGet(){
System.out.println("调用HttpServlet的doGet方法");
}
}
class MyHttpServlet extends HttpServlet{
@Override
public void doGet() {
System.out.println("调用MyHttpServlet的doGet方法");
}
}
输出结果:
1 | 调用HttpServlet的service方法 |
我们来分析一波
按照之前的逻辑,我们肯定会认为结果如下:
1 | 调用HttpServlet的service方法 |
那么这是为什么呢?
其实大家可以参考一下Java编程思想中的第84页的this关键字,这里我不在叙述了,后面会讲。
当我们在方法执行之时,比如有相同的两个对象调用相同的方法,那么编译器是如何知道具体是哪个对象呢?
这个时候为了能区分到底是哪个对象调用的方法,编译器帮我们偷偷的将当前调用这个方法的对象引用传了进去,这样就可以区分了。如下
1 | User u1 = new User(1,"张三"); |
两个对象u1和u2同时调用了login对象,那编译器是如何知道到底哪个对象调用了方法呢?于是编译器做了以下手脚
1 | User u1 = new User(1,"张三"); |
编译器帮我们将这个对象的引用偷偷传了进去,这样就可以识别了,Java为我们专门设置了这一代表谁调用方法的关键字—–this,那我们来看看我们之前的那个代码
1 | package yp.JavaSE.Review_07; |
我们可以将其转换为如下
1 | package yp.JavaSE.Review_07; |
分析:
- 首先我们自己的MyHttpServlet调用service方法
- 由于我们自己写的类MyHttpServlet没有重写service方法,所以它就去调用我们父类HttpServlet的service方法
- 并且在调用的时候编译器将this(就是MyHttpServlet对象的引用)偷偷传入进去
- 当我们执行父类的service方法时,父类的service方法又调用doGet()方法
- 编译器给我们加了this,而当前this代表的是MyHttpServlet对象的引用,所以执行的doGet()方法也是MyHttpServlet的doGet()方法。