【问题标题】:Anonymous inner class members not being accessible, in java在java中无法访问匿名内部类成员
【发布时间】:2016-03-15 08:05:19
【问题描述】:

当我使用匿名内部类来创建节点时。当我打印所有键时,它们打印为 0,而不是我在匿名类声明中分配的值。难道我做错了什么?这是我的代码:

public class LinkedListTest {
Node head;

public void addInOrder(final int value) {
    if (head == null) {
        head = new Node() {
            int key = value;
        };
    }
    else if(head.key > value) {
        final Node temp = head;
        head = new Node() {
            int key = value;
            Node next = temp;
        };
    }
    else {
        Node theNode = head;
        while(theNode.key < value) {
            if (theNode.next == null) {
                theNode.next = new Node() {
                    int key = value;
                };
                return;
            }
            else if(theNode.next.key > value) {
                final Node temp = theNode.next;
                theNode.next = new Node() {
                    int key = value;
                    Node next = temp;
                };
                return;
            }
            theNode = theNode.next;
        }
    }
}

这是我的节点的类声明:

class Node {
    int key;
    Node next;
}

这是我的打印方法:

  public void printAll(Node hasNode) {
    if (hasNode != null) {
        System.out.println(hasNode.key);
        if (hasNode.next != null) {
            printAll(hasNode.next);
        }
    }
}

【问题讨论】:

    标签: java inner-classes anonymous-class anonymous-inner-class


    【解决方案1】:

    这是因为您没有为 Node 中的字段赋值,而是为匿名子类中的同名字段赋值。

    Node添加构造函数,不要创建匿名子类:

    class Node {
      int key;
      Node next;
    
      Node(int key, Node next) {
        this.key = key; this.next = next;
      }
    }
    

    或者,您可以添加第二个构造函数,它只需要密钥:

      Node(int key) {
        this(key, null);
      }
    

    另一种方法是调用new Node(key, null)

    【讨论】:

    • 安迪领先我几秒钟 :-),但是是的,这就是正在发生的事情。匿名子类中的int key = value; 是在匿名子类中声明和初始化一个实例变量,它会覆盖Node 中的同名字段。
    • 我明白,但是如果我分配给它们的值字段无法在它们声明的范围之外访问,那么匿名内部类的意义何在?我认为“阴影”在这种情况下会起作用。也感谢您的反馈!
    • 匿名内部类有很多用途,不涉及声明同名的成员变量。但是,在匿名内部类中声明的任何成员变量或非覆盖方法(几乎)是不可访问的,因为您只是引用了 Node,而不是 LinkedListTest$1Node 的特定子类。
    • (“几乎”是因为您可以像 new Node() { int foo = 5; }.foo 一样访问它们;但这是一件非常不寻常且不是很有用的事情)
    • 谢谢,不知道成员在使用匿名内部类时基本上是不可访问的。
    【解决方案2】:

    正如 Andy Turner 回答的那样,您在匿名类中将 keynext 声明为匿名类的实例变量,并且您正在初始化这些实例变量,但它们与来自班级Node

    如果它更容易理解,那么:

    theNode.next = new Node() {
        int key = value;
        Node next = temp;
    };
    

    相当于这样的本地类:

    class Foo extends Node {
        int key = value;
        Node next = temp;
    };
    theNode.next = new Foo();
    

    或者您甚至可以将类从方法中移除,以便捕获更清晰:

    // outside the method
    class Foo extends Node {
        int key;
        Node next;
        Foo(int value, Node temp) { key = value; next = temp; }
    };
    // inside the method
    theNode.next = new Foo(value, temp);
    

    重点是,在所有这些情况下,您都在为Foo 的实例变量赋值,而不是Node 的实例变量。

    您可以在允许您分配给Node 的实例变量的匿名类中执行初始化。虽然匿名类没有构造函数(它们不需要它们),但可以在实例初始化器中完成初始化:

    theNode.next = new Node() {
        {
            key = value;
            next = temp;
        }
    };
    

    通常写成“双大括号初始化”样式:

    theNode.next = new Node() {{
        key = value;
        next = temp;
    }};
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      相关资源
      最近更新 更多