考虑具有 InnerClass 的类 OuterClass
public class OuterClass {
class InnerClass {
}
}
第二个类,它试图扩展 OuterClass 的 InnerClass
public class Clazz extends OuterClass.InnerClass {
public Clazz(OuterClass outerClass) {
outerClass.super();
}
}
到目前为止一切顺利,这段代码可以工作,编译器应该不会发出警告。
但我想了解 - 为什么有必要将其传递给 OuterClass 的构造函数引用?为什么有必要调用它的 super 构造函数?
我想了解为什么必须这样精确?
此外,考虑这个类(与之前的类无关),其中类 Apartments 和 Hall 是 Building 类的内部类,它是Solution 内部(innerception)。
public class Solution {
public class Building {
public class Hall {
private BigDecimal square;
public Hall(BigDecimal square) {
this.square = square;
}
}
public class Apartments {
}
}
}
然后是top-level class试图扩展inner inner class Hall
class BigHall extends Solution.Building.Hall {
public BigHall(Solution.Building building, BigDecimal square)
{
building.super(square);
}
}
看看这个烂摊子。最后两个类也应该编译,但是你能帮我弄清楚吗,为什么 BigHall 类在扩展内部内部类 Hall 时确实需要传递给构造函数对 Building 对象的引用而不是解决方案对象?
如果您能提供 JLS 的报价,那就太好了!
最佳答案
你的 InnerClass 是一个 inner class .
An inner class is a nested class that is not explicitly or implicitly declared
static.
内部类可能有封闭的实例
An instance
iof a direct inner classC[yourInnerClass] of a class or interfaceO[yourOuterClass] is associated with an instance ofO, known as the immediately enclosing instance ofi.
只有在静态上下文中声明的内部类没有封闭实例。
An instance of an inner class
Iwhose declaration occurs in a static context has no lexically enclosing instances.
您的示例的内部类不在静态上下文中,因此需要一个封闭实例。
Java Language Specification然后说
The constructor of a non-private inner member class implicitly declares, as the first formal parameter, a variable representing the immediately enclosing instance of the class
(如果您有兴趣,它会进一步详细说明原因)。换句话说,您的 InnerClass 构造函数确实看起来像
public InnerClass(OuterClass OuterClass.this){} // this is valid syntax for entirely different reasons
它期望类型为 OuterClass 的参数用作其封闭实例。子类化此 InnerClass 类型不会改变这一点,尤其是因为任何子类型都必须调用其父类(super class)型的超构造函数。
关于构造函数的主题,specification also states
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class
Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
很明显,如果没有参数,您的代码将无法运行
public class Clazz extends OuterClass.InnerClass {
public Clazz() {
// implicit super() invocation
}
}
此 super() 构造函数调用无效。在这种情况下,这是因为语法错误。但是这个想法是, super 构造函数期望代表封闭实例的形式参数的参数,但您没有提供。正确的语法是您已有的语法。让我们定义它。
有multiple kinds of constructor invocations .你的
public Clazz(OuterClass outerClass) {
outerClass.super();
}
是一个合格的父类(super class)构造函数调用,defined作为
Qualified superclass constructor invocations begin with a
Primaryexpression or anExpressionName. They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.
chapter去解释表达式是如何求值的
If the superclass constructor invocation is qualified, then the
Primaryexpression or theExpressionNameimmediately preceding ".super",p, is evaluated.
[...]Otherwise, the result of this evaluation is the immediately enclosing instance of
iwith respect toS.
换句话说,outerClass 引用的对象成为您的 Clazz 实例所需的封闭实例。
简单来说,忽略内部类的情况,您的示例可以归结为类似
public class Foo {}
public class Bar {
public Bar(Foo foo){}
}
public class SubBar extends Bar {
public SubBar(Foo foo) {
super(foo);
}
}
SubBar 必须满足需要 Foo 实例的 Bar super 构造函数。这与您的 Clazz 类型发生的事情相同,只是它的父类(super class)型的构造函数是隐式的。
关于java - 为什么内部类的子类需要封闭实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42094083/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象