在学习java的继承的过程中遇到这样的一个分析类题目,比较有意思,在这里做出简要分析:

//请写出以下程序运行结果:

package test;
public class Test {
   public static void main(String[] args) {
      Test t = new Test();
      t.show(new Car(){
         public void run(){
            System.out.println("test run");           
         }
      });
   }
   public void show(Car c){
      c.run();
      c.show();
}}
abstract class Car{
   public void run(){
      System.out.println("car run");     
   }
   public void show(){
       System.out.println(getClass().getName());
}}

那么,我们可以通过断点的分析:

  1. 首先。我们从main函数进入,发现他创建了Test类的一个对象t;

    我们在test类中并没有寻找到Test类的构造函数,所以应该是系统默认的构造器,不进行任何的行为;

  2. 之后,我们注意一下这一步,首先是t.show()方法,在Test的类中有这么一个方法,不过我们看到show方法是需要传入一个car类的对象,所以他new了一个car对象,离奇的是car对象后面接着一对大括号。

  3. 注意到:这里有一个匿名类,用来一次性使用的创建car对象。这样抽象类car才能被以匿名类中的内容实例化。这样,我们就完成了对car类的实例化,得到了一个car类的对象。

    image-20200401173415543

  4. 接着,我们以那个新new的对象作为参数,调用了Test类中的show方法。

    image-20200401174104233

    而show方法的第一条语句是c.show();注意到我们是通过匿名类创建的对象,而我们是通过匿名类中的重新写的run()方法,所以他又跳回了第六行,输出“test run”;

image-20200401174405627

  1. 好的,接下来我们又回到了show方法中,继续调用c.show(),这时,我们回头看匿名类,它里面竟然没有show的方法。。。所以他就只能调用car类的show()方法。

    image-20200401174506855

  1. 注意到了右侧返回的getName()是”test.Test$1”,好吧,test是包名,Test是类名,可以理解!

    但是$1就使得不少同学迷惑了。

    image-20200401174856777

  2. 好的,我们这次打开文件管理系统,找到我们编译的文件所在,发现.java编译后多出了Test$1.class的文件,这个.class是怎么来的呢?对了是匿名类!这里的Test$1这个类名是编译器给它的名字(匿名类没有名字,但是java编译器要给他起个名,才好分辨)而命名的格式就是第一个Test类下面的匿名类的话就叫$1,第二个就是$2。

    image-20200401175322331

image-20200401175322331

这样就可以了,程序就结束了!主要涉及了匿名成员类。大家有兴趣(最好可以了解一下)