实例化内部类

时间:2010-11-01 16:11:27

标签: java inner-classes

我正在研究过度使用hashCode和equals方法但出现错误的示例问题:“无法访问CustomHashCodeExample类型的封闭实例。必须使用CustomHashCodeExample类型的封闭实例限定分配(例如,xnew 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;

    }
}

3 个答案:

答案 0 :(得分:125)

我认为您要将HashPerson类声明为static。否则它只能在包含类的上下文中实例化,无论是在包含类的方法中还是使用如下代码:

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

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

答案 1 :(得分:8)

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

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

答案 2 :(得分:1)

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

  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. 匿名内部类(实现接口):这种类型的类通常是隐藏的,无法直接在代码中看到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();