Создание внутреннего класса

Я работал над примером проблемы избыточного избавления от hashCode и метода equals, но получил ошибку: "Нет включающего экземпляра типа CustomHashCodeExample. Необходимо квалифицировать выделение с включающим экземпляром типа CustomHashCodeExample (например, xnew A(), где x - это экземпляр of 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;

    }
}

2 ответа

Решение

Я думаю, что вы хотите объявить HashPerson класс как static, В противном случае его можно создать только в контексте содержащего класса, либо в методе содержащего класса, либо с помощью кода, подобного следующему:

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

На самом деле, мое эмпирическое правило заключается в том, чтобы сделать любой вложенный класс статическим, если только у меня нет особой причины не делать этого. Это также более эффективно, потому что нестатические вложенные классы (называемые внутренними классами) всегда содержат неявную ссылку на содержащий объект.

Вам нужно либо сделать свой внутренний класс статичным, либо ссылаться на него через экземпляр внешнего класса. Скорее всего, вы просто хотите сделать свой внутренний класс статичным.

Нестатические члены класса (переменные, методы, внутренние классы) относятся к экземпляру класса. Поэтому при доступе к нестатическим элементам из статического контекста (такого как статический метод, такой как testHashCodeOverride), вам нужно указать экземпляр окружающего класса.

Как я вижу, могут быть разные способы создания экземпляров внутренних классов.

  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();
    
Другие вопросы по тегам