![](/img/trans.png)
[英]If outer class(enclosing class) and inner class have data member with same names then how can we differentiate them
[英]How many outer **this** will have this inner class?
我有以下内部类的情况。
class Outer {
private class Inner1 extends InnerBase {
}
private class Inner2 extends InnerBase {
}
private class InnerBase {
}
}
通常我认为内部类有一个额外的,隐藏的“this”到外部类。
但是,会发生什么是内部类派生自另一个内部类?
所有内部类(Inner1,Inner2,InnerBase)都应该有一个额外的。
Inner1,Inner2会有自己的外部引用吗? 或者只是重用InnerBase中的那个,导致一个略有不同的行为?
(隐藏此= =指向外类实例的引用)
内部层次结构中的每个非静态内部类将有自己的参照this
。 你可以用javap
确认
$ javap -private Outer.Inner1
Compiled from "Outer.java"
class Outer$Inner1 extends Outer$InnerBase{
final Outer this$0;
private Outer$Inner1(Outer);
}
$ javap -private Outer.InnerBase
Compiled from "Outer.java"
class Outer$InnerBase extends java.lang.Object{
final Outer this$0;
private Outer$InnerBase(Outer);
Outer$InnerBase(Outer, Outer$1);
}
顺便说一句,如果你真的想要,你可以利用一些不起眼的java语法,为父类和子类之间的this$0
成员提供不同的值。 这是如何做:
public class Outer {
class InnerBase {
Outer innerBaseOuter() { return Outer.this; }
}
class Inner1 extends InnerBase {
public Inner1() {}
public Inner1(Outer parentOuter) {
parentOuter.super(); // set a different super in InnerBase
}
Outer innerOuter() { return Outer.this; }
}
public static void main(String[] args) {
Outer outer1 = new Outer();
Outer outer2 = new Outer();
Inner1 a = outer1.new Inner1();
System.out.println("Checking (a.base == a.inner) => "+
(a.innerBaseOuter() == a.innerOuter()));
Inner1 b = outer1.new Inner1(outer2);
System.out.println("Checking (b.base == b.inner) => "+
(b.innerBaseOuter() == b.innerOuter()));
}
}
运行您获得的程序:
Checking (a.base == a.inner) => true
Checking (b.base == b.inner) => false
每个都将引用同一个Outer实例。 它们每个都有自己对Outer的引用,但该引用将指向外部的同一个实例。 由于无法更改引用,因此从其中任何一个引用Outer都是等效的。
class Outer {
private class Inner1 extends InnerBase {
Outer getOuter() {
return Outer.this;
}
}
private class Inner2 extends InnerBase {
Outer getOuter() {
return Outer.this;
}
}
private class InnerBase {
Outer getOuter() {
return Outer.this;
}
}
public static void main(String[] args) {
new Outer().test();
}
public void test() {
System.out.println((new Inner1()).getOuter());
System.out.println((new Inner2()).getOuter());
System.out.println((new InnerBase()).getOuter());
}
}
我们来看看这个节目:
public class Outer
{
public Outer() {}
class Inner1 extends Outer
{
public Inner1()
{
super(); // invokes Object() constructor
}
}
class Inner2 extends Inner1
{
public Inner2()
{
super(); // invokes Inner1() constructor
}
}
}
如果尝试编译它,则会发生错误。
Outer.java:12: cannot reference this before
supertype constructor has been called
super(); // invokes Inner1() constructor
因为Inner2
的超类本身就是一个内部类,所以一个模糊的语言规则开始发挥作用。 如您所知,内部类(如Inner1
的实例化需要将封闭实例提供给构造函数。 通常,它是隐式提供的,但它也可以使用表单expression.super(args)
的超类构造函数调用显式提供。
如果隐式提供了封闭实例,则编译器将生成表达式:它将此引用用于超类所属的最内层封闭类。 诚然,这是相当令人满意的,但它正是编译器所做的。 在这种情况下,超类是Inner1
。 因为当前类Inner2
间接扩展了Outer,所以它将Inner1作为继承成员。 因此,超类构造函数的限定表达式就是这样。 编译器提供一个封闭的实例,重写super到this.super。
默认的Inner2
构造函数尝试在调用超类构造函数之前引用this
,这是非法的。
解决此问题的蛮力方法是明确提供合理的封闭实例:
public class Outer
{
class Inner1 extends Outer { }
class Inner2 extends Inner1
{
public Inner2()
{
Outer.this.super();
}
}
}
编译,但它很复杂。 有一个更好的解决方案: 每当你编写一个成员类时,问问自己,这个类真的需要一个封闭的实例吗? 如果答案是否定的,请将其设为静态 。 内部类有时是有用的,但它们很容易引入使程序难以理解的复杂性。 它们与泛型,反射和继承有着复杂的相互作用。 如果将Inner1
声明为静态,则问题就会消失。 如果你还声明Inner2
是静态的,你实际上可以理解程序的作用。
总之,一个类很少适合作为另一个类的内部类和子类。 更一般地说,扩展内部阶级很少是合适的; 如果你必须,请仔细思考封闭的实例。 大多数成员类可以而且应该被声明为static。
在您的示例中只有一个级别的“内部”,因此每个内部类都可以像您提到的那样访问Outer
类。
这是一个有趣的例子:
public class Test {
public static void main(String[] args) {
Level1 l1 = new Level1();
Level1.Level2 l2 = l1.new Level2();
Level1.Level2.Level3 l3 = l2.new Level3();
}
public static class Level1 {
private String s = "Level1";
public Level1() {
System.out.println(this + ": " + s);
}
public class Level2 {
private String s = "Level2";
public Level2() {
System.out.println(this + ": " + s);
System.out.println("Level1: " + Level1.this);
}
public class Level3 extends OtherLevel {
private String s = "Level3";
public Level3() {
System.out.println(this + ": " + s);
System.out.println("Level1: " + Level1.this);
System.out.println("Level2: " + Level2.this);
System.out.println("super: " + super.toString());
}
}
}
public class OtherLevel {
private String s = "OtherLevel";
public OtherLevel() {
System.out.println(this + ": " + s);
}
}
}
}
输出:
javaapplication4.Test$Level1@70284ac3: Level1
javaapplication4.Test$Level1$Level2@74a14fed: Level2
Level1: javaapplication4.Test$Level1@70284ac3
javaapplication4.Test$Level1$Level2$Level3@88d00c6: OtherLevel
javaapplication4.Test$Level1$Level2$Level3@88d00c6: Level3
Level1: javaapplication4.Test$Level1@70284ac3
Level2: javaapplication4.Test$Level1$Level2@74a14fed
super: javaapplication4.Test$Level1$Level2$Level3@88d00c6
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.