【问题标题】:Difference between new Test() and new Test() { }new Test() 和 new Test() { } 的区别
【发布时间】:2014-03-04 05:53:04
【问题描述】:

这两种实例化类的新对象的方式有什么区别如下:

Test t1=new Test();
Test t2=new Test(){ };

当我尝试以下代码时,我可以看到两个对象都可以访问方法foo(),但是t2无法访问variable xvariable x无法解析):

public class Test
{ 
    int x=0;
    public void foo(){ }

    public static void main (String args[])
    {
        Test t1=new Test();
        Test t2=new Test(){ };
        t1.x=10;
        t2.x=20;
        t1.foo();
        t2.foo();
        System.out.println(t1.x+" "t2.x);
    }
}

【问题讨论】:

  • 我会说没有,除此之外,第二种方式让您有机会覆盖父类中的方法,而无需创建专门的子类
  • 如果您通过将t1.x+" "t2.x 转换为t1.x+" "+t2.x 使其可编译,则可以正常编译。
  • @Ankur Shanbhag 这是一个无效的编辑。
  • @AnkurShanbhag 只是分享。在我早期进行编辑时,我什至收到了 Mod 的警告;)
  • 另外可以说第二种方法不是“实例化新对象的方式”。它特定于 Java,即您不能在 C# 中执行此操作。

标签: java anonymous-inner-class


【解决方案1】:

Test t2=new Test(); 将创建 Test 类的对象。

Test t2=new Test(){ }; 会创建一个测试子类的对象(即本例中的匿名内部类)。

您可以为那里的任何方法提供实现,例如

Test t2=new Test(){ 
public void foo(){ System.out.println("This is foo");}
};

这样当从对象t2 调用foo() 方法时,它将打印This is foo

加法

代码中的编译时错误是由于缺少连接运算符

System.out.println(t1.x+" "+t2.x);
                          ###

【讨论】:

  • @eatSleepCode 好吧,t2 instanceof Test 将返回true,但这并不意味着new Test() { } 创建了Test 的对象。不,它没有。子类对象始终是 instanceof 所有它的超类。
  • @Solace 不,一点也不。尝试编译类,你会看到生成了两个类文件。一个名称为Test$1
  • 您可能想通过我的thisthisthis 回答。
  • 您想将t2.getClass() 的输出添加到您的答案中吗?它可能会更清楚(而不是关于正在生成两个.class 文件的评论)。
  • @eatSleepCode 要完成答案,您可能需要解释为什么无法从子类访问 x 以及如何使其可访问。
【解决方案2】:

两个引用的运行时类型会不同。试试:

System.out.println(t1.getClass());  // class Test
System.out.println(t2.getClass());  // class Test$1

你会看到不同的输出。原因是,new Test() { } 表达式创建了Test 的匿名子类的实例。所以,Test$1Test 的子类。

现在,您收到该错误的原因是,您缺少 + 符号:

System.out.println(t1.x + " " + t2.x);
                              ^

您可以在this postthis post 上找到更多详细信息

【讨论】:

  • 如果x 是私有的,那么t2 就不能合法地看到它?
  • @Cruncher 是的,它不会。在当前代码中,由于 main 方法在类本身中,因此它似乎可以访问,但如果将其移到类外,t1t2 都无法访问 @987654335 @.
  • 你是对的。在这种情况下,我不认为提及 x 具有默认修饰符这一事实是相关的。对于任何修饰符,t1t2 都可以看到,或者都不能。
【解决方案3】:
test t1=new test();

这将创建一个类test的新实例

test t2=new test(){ };  

这是一个匿名内部类,它扩展类test

【讨论】:

    【解决方案4】:
    Test t1=new Test();
    

    在这里,您正在创建Test 类的实例并将其分配给t1

    Test t2=new Test(){ };
    

    在这里,您创建了Test 的匿名子类并将其实例化并分配给t2

    而且,你在下面的行中犯了一个错误,更正它,你错过了+

    System.out.println(t1.x + " " + t2.x);
    

    【讨论】:

      【解决方案5】:

      一)

       Test t1=new Test();
      

      通过这样做,您可以通过调用默认构造函数来创建 Test 类的对象

      b)

      Test t2=new Test(){ };
      

      通过这样做,您正在创建一个扩展 Test 类的类的对象,这个类没有名称,因此它被称为“匿名内部类” 例如。

           Test t2=new Test(){ 
      // this is the body of the anonymous(un-named) class 
      //you can overide the method foo() here
      // you can write more methods here but you will not be able to call them 
      // for example
      public void doSomething(){}
      };
      

      doSomething() 无法在外部访问,因为 t2 即对该对象(扩展 Test 的匿名内部类的对象)的引用(指针)只理解 foo() 方法,因为它是父类的引用

      只有当你这样做时才能调用doSomething()

        Test t2=   new Test(){
                  public void foo()
                  {
                    doSomething();
      
      
                  }
                  public void doSomething(){
                        System.out.println("Do Something");
                  }
      
              };
      

      即在 foo() 中显式调用 doSomething() 并且 foo() 可以在外部访问

      t2.foo();
      

      注意:请正确填写班级名称,班级首字母必须大写

      public class Test{}
      

      当您开始编写大量代码时,它将帮助您和其他人,因为它使您的代码可读。

      【讨论】:

      • 是的,我知道类名总是以大写字母开头。这只是为了测试两种方法之间的差异而创建的。无论如何,感谢您的详细回答。
      【解决方案6】:

      你错过了下面一行中的 + 运算符试试这个

      System.out.println(t1.x+" "t2.x);
      

      使用这个

      System.out.println(t1.x+" "+t2.x);
      

      【讨论】:

        【解决方案7】:
        Test t2=new Test();` 
        

        将创建 Test 类的对象。

        Test t2=new Test(){ };
        

        将创建一个测试子类的对象 (即本例中的匿名内部类)。

        Test t2=new Test(){ 
        public void foo(){ System.out.println("foo");}
        };
        

        当从对象 t2 调用 foo() 方法时, 它将打印 foo。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-01
          • 2019-11-03
          • 2018-08-02
          • 1970-01-01
          • 2011-03-25
          • 2011-07-26
          • 2011-11-22
          • 2018-03-20
          相关资源
          最近更新 更多