【问题标题】:Instantiating inner class实例化内部类
【发布时间】:2011-05-03 12:17:39
【问题描述】:

我正在处理覆盖 hashCode 和 equals 方法的示例问题,但出现错误:“没有可访问类型 CustomHashCodeExample 的封闭实例。必须使用 CustomHashCodeExample 类型的封闭实例来限定分配(egxnew A () 其中 x 是 CustomHashCodeExample 的一个实例)。" 我编写了一个内部类 HashPerson,当我尝试在另一个名为 testHashCodeOverride() 的方法中实例化这个内部类时出现此错误。

public static void testHashCodeOverride(){   
    System.out.println("\nTest HashCode Override Method");
    System.out.println("==================================\n");

    HashPerson william = new HashPerson("willy");
    HashPerson bill = new HashPerson("willy");          
}

这段代码工作正常,即使我没有看到静态内部类或外部类的实例,很困惑:(

public class HashCodeExample {

    public static void testHashCodeOverride() {

        HashPerson william = new HashPerson("Willy");
        HashPerson bill = new HashPerson("Willy");
        System.out.println("Hash code for william  = " + william.hashCode());
        System.out.println("Hash code for bill     = " + bill.hashCode());

        HashMap table = new HashMap();
        table.put(william, "Silly");

        if (table.containsKey(william)) {
            System.out.println(table.get(william));
        } else {
            System.out.println("Key " + william + " not found");
        }

        if (table.containsKey(bill)) {
            System.out.println(table.get(bill));
        } else {
            System.out.println("Key " + bill + " not found");
        }


    }

    class HashPerson {
        private static final int HASH_PRIME = 1000003;

        public HashPerson(String name) {
            this.name = name;
        }

        public String toString() {
            return name;
        }

        public boolean equals(Object rhs) {
            if (this == rhs)
                return true;

            // make sure they are the same class
            if (rhs == null || rhs.getClass() != getClass())
                return false;

            // ok, they are the same class. Cast rhs to HashPerson
            HashPerson other = (HashPerson) rhs;

            // our test for equality simply checks the name field
            if (!name.equals(other.name)) {
                return false;
            }

            // if we get this far, they are equal
            return true;
        }
        public int hashCode() {
            int result = 0;
            result = HASH_PRIME * result + name.hashCode();
            return result;
        }
        private String name;

    }
}

【问题讨论】:

  • 您真的阅读了错误信息吗?它确切地告诉你该怎么做。实例化内部类时,必须使用封闭类的实例对其进行限定。
  • 您应该真正清理示例代码的格式并将其剥离到基本要素。在目前的状态下,这几乎是不可读的。
  • 您可以将 hashCode 方法简化为 return name.hashCode();
  • @Jonik:感谢您清理代码格式。我还没有足够的声誉来做那件事。不过,这让我有点困惑。当我查看代码时,它应该会产生相同的“无封闭实例”错误,因为静态方法 testHashCodeOverride 想要实例化非静态嵌套(=inner)类 HashPerson 的对象。
  • @Steve,这是一个展示如何在所有场景中覆盖哈希码的示例,我只是自己尝试相同。名称.hashCode();会返回我的内存地址,对吗?

标签: java inner-classes


【解决方案1】:

您需要将内部类设为静态,或者通过外部类的实例引用它。很可能你只是想让你的内部类静态。

类的非静态成员(变量、方法、内部类)是类的每个实例。因此,当从静态上下文(如testHashCodeOverride之类的静态方法)访问非静态成员时,需要指定封闭类的实例。

【讨论】:

  • 嗨oksayt,所以在大多数情况下我们应该让内部类静态?首选方式是什么?通过外部类的实例访问还是静态访问?
  • 不要将内部类用于公共 API。添加了内部类以具有闭包和匿名类。
  • 默认情况下,顶级类是静态的,但内部类是非静态的。如果您仅出于代码组织目的而创建内部类,则首选将其设为 static 并将其视为独立类(具有限制可见性的选项)是首选。如果您需要内部类能够访问其封闭类的非静态成员,那么您应该将其设为非静态。
【解决方案2】:

我想你想将HashPerson 类声明为static。否则它只能在包含类的上下文中实例化,要么在包含类的方法中,要么使用如下代码:

ContainingClass container = new ContainingClass();
HashPerson william = container.new HashPerson("willy");

实际上,我的经验法则是将任何嵌套类设为静态,除非我有特殊理由不这样做。这也更有效,因为非静态嵌套类(称为内部类)总是包含对包含对象的隐式引用。

【讨论】:

  • 谢谢 MForster,我很困惑的地方,我有一个示例程序,它的编写方式与我在这里和该代码中的编写方式完全相同,内部类不是静态的,它们也不是包含类的实例。我在那个代码中遗漏了什么吗? “在我的问题中附加代码”
  • 他们是否在包含类的方法中创建实例?
  • 也许我没有正确阅读代码。刚刚发布了实际代码。
  • >> 因为非静态嵌套类(称为内部类)总是包含对包含对象的隐式引用。 MForster,为什么内部类引用包含类是不好的?
  • 它需要内存。顺便说一句,您发布的代码不可读。但在我看来,HashPerson 类在这种情况下是顶级类,而不是嵌套类。
【解决方案3】:

正如我所见,实例化内部类可能有不同的方法

  1. 静态内部类:当内部类是静态时,假设代码看起来像描述的那样。

    class OuterClass 
    {
        static int outer_x = 10;
        int outer_y = 20;
        // static nested class 
        static class StaticNestedClass {
            void display() {
    
            }
        }
    }
    
    OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();
    

或者这对于静态类来说就足够了

 new StaticNestedClass();
  1. 本地内部类(非静态):非静态的内部类,本地内部类的一件好事是它们可以访问封闭类的所有私有数据成员。

    OuterClass outerObject = new OuterClass(); 
    OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    
  2. Anonymous Inner Class (implementing Interface) :这类类一般是隐藏的,在代码中无法直接看到 Class{...} 块,所以称为Anonymous Inner Class .这里描述了如何在内部类实现接口Runnable Interface的情况下实例化它。

    Runnable r = new Runnable() 
    { 
      //This is Anonymous Class
      public void run() {
        System.out.println("Child Thread");
      }
    };
    
  3. 匿名内部类(扩展一个类):我们可以有一个匿名内部类扩展一个类,这里​​我以线程类为例,

    Thread t = new Thread(new Runnable() 
    {
      //Anonymous Inner class
    public void run() {
        System.out.println("Child Thread");
    }
    });
    
  4. 在方法/构造函数参数中定义的匿名内部类:内部类也可以在方法中定义,这里举例说明如何在参数中定义和实例化它

    public static void main(String[] args) 
    { 
    //Here we are using Anonymous Inner class 
    //that define inside argument, here constructor argument 
    Thread t = new Thread(new Runnable() 
    { 
        public void run() 
        { 
            System.out.println("Child Thread"); 
        } 
    });
    t.start();
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 2016-06-11
    • 1970-01-01
    • 2012-11-05
    相关资源
    最近更新 更多