【问题标题】:Why not Constructor in Anonymous class in java?Its contradicting OOPs rule [closed]为什么不在 java 中的匿名类中使用构造函数?它与 OOP 规则相矛盾 [关闭]
【发布时间】:2014-01-24 05:39:13
【问题描述】:

oops 规则是“没有构造函数就不能存在类”。没关系。但是在 java 中,匿名类永远不会有它的构造函数。因为它没有任何名称。所以它与 OOPS 规则相矛盾..我真的很困惑。它是否违反了 OOPS 规则?请帮助

【问题讨论】:

  • 也许你会在programmers.stackexchange中得到更好的回应
  • 规则被打破;-)
  • 提示:匿名类实际上是一个对象。 :)
  • 我刚刚在 Google 上搜索了“OOPS 规则”,并没有找到任何类似于“没有构造函数就不能存在类”的规则。所以你可能要考虑你的来源。 . .

标签: java oop constructor core anonymous-class


【解决方案1】:

实际上,它们有一个隐式构造函数。假设你有:

class A {
    A (B b, C b) {
        //constructor code
    }
}

因此,当您通过new A(b,c) {...} 创建 A 的匿名子类时,它有一个主体为 super(b,c) 的隐式构造函数。我猜匿名类不能有自己的显式函数的原因是构造函数名称必须与类名匹配的java命名约定。假设匿名类没有名字,所以你不能为它指定构造函数。

【讨论】:

  • 我认为你是对的。他们有一个隐含的构造器。我可以用javap工具检查一下
【解决方案2】:

在匿名类中

Foo foo = new Foo(x) {};

(x) 指定传递给超类构造函数的实际参数。

整个匿名类语法是syntactic-sugar,编译器将其翻译成更基本的语法结构的缩写语法。

所以匿名类并不是真正的匿名。上面的示例类被分配了一个自动生成的名称,例如Foo$1,它有一个隐含的构造函数,格式为

Foo$1(T x) { super(x); }

其中 T 取自最具体的超类构造函数,其签名可以接受参数 (x),这是基于 Java 在基于静态类型的重写签名中进行选择的常规规则。

【讨论】:

  • 谢谢迈克。它真的很有帮助。
【解决方案3】:

每个 Java 类都有一个构造函数。您不能指定它,但您的 Anonymous 类会获得一个默认构造函数。没有什么会强迫您使用匿名类,您可以改用内部类。

【讨论】:

  • 但每个构造函数的名称必须与类名相同。但是任何匿名类都没有任何名称;
  • @user3230692 你仍然得到一个默认的构造函数。否则无法实例化。
【解决方案4】:

来自 Java 文档:

Anonymous class

匿名类是一个表达式。匿名类的语法 表达式就像调用构造函数,除了那里 是包含在代码块中的类定义。

包含构造函数参数的括号,就像 普通类实例创建表达式。注意:当您实施 接口,没有构造函数,所以你使用一对空的 括号

示例

class Emp{  
  public static void main(String args[]){  
    Person p=new Person(){  
       void eat(){System.out.println("nice fruits");}  
    };  

    p.eat();  
  }  
}  

内部实现:

static class Emp$1 extends Person  
{  
   Emp$1(){}  

   void eat()  
    {  
        System.out.println("nice fruits");  
    }  
}

参考:Example of Anonymous Class

【讨论】:

    【解决方案5】:

    来自Java Language Specification

    15.9.5。匿名类声明

    匿名类声明自动从类派生 Java 编译器的实例创建表达式。

    匿名类永远不是抽象的(第 8.1.1.1 节)。

    匿名类总是隐式最终的(第 8.1.1.2 节)。

    匿名类始终是内部类(第 8.1.3 节);它永远不会 静态(第 8.1.1 节、第 8.5.1 节)。

    15.9.5.1。匿名构造函数

    匿名类不能有显式声明的构造函数。 相反,Java 编译器必须自动提供一个匿名的 匿名类的构造函数。匿名的形式 具有直接超类 S 的匿名类 C 的构造函数为 如下:

    A. 如果 S 不是内部类,或者如果 S 是出现在静态上下文中的本地类,则匿名构造函数有一个正式的 类实例创建的每个实际参数的参数 声明 C 的表达式。

    类实例创建表达式的实际参数用于确定 S 的构造函数 cs,使用与 for 相同的规则 方法调用(第 15.12 节)。

    匿名构造函数的每个形参的类型必须与cs对应的形参相同。

    构造函数的主体由 super(...) 形式的显式构造函数调用(第 8.8.7.1 节)组成,其中实际的 arguments 是构造函数的形参,按顺序排列 他们被宣布了。

    B. 否则,C 的构造函数的第一个形参表示 i 的直接封闭实例的值 相对于 S。这个参数的类型是类类型 立即附上 S 的声明。

    构造函数有一个额外的形式参数,用于声明类实例创建表达式的每个实际参数 匿名类。第 n 个形参 e 对应于第 n-1 个 实际论证。

    类实例创建表达式的实际参数用于确定 S 的构造函数 cs,使用与 for 相同的规则 方法调用(第 15.12 节)。

    匿名构造函数的每个形参的类型必须与cs对应的形参相同。

    构造函数的主体由 o.super(...) 形式的显式构造函数调用(第 8.8.7.1 节)组成,其中 o 是第一个 构造函数的形式参数,实际参数是 构造函数的后续形式参数,按照它们的顺序 被宣布了。

    在所有情况下,匿名构造函数的 throws 子句必须列出 显式超类抛出的所有检查异常 匿名中包含的构造函数调用语句 构造函数,以及任何实例抛出的所有检查异常 匿名类的初始化器或实例变量初始化器。

    请注意,匿名签名是可能的 构造函数来引用不可访问的类型(例如,如果这样的 type 出现在超类构造函数 cs) 的签名中。这 本身不会在编译时或 运行时。

    【讨论】:

      【解决方案6】:

      即使是匿名类也有构造函数,只是你不能给它,而是编译器会自动为你提供。

      【讨论】:

        猜你喜欢
        • 2016-10-06
        • 2013-11-08
        • 1970-01-01
        • 1970-01-01
        • 2014-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        相关资源
        最近更新 更多