Обратный вызов объекта определен необычным образом в Java

Я наткнулся на код, и одна вещь меня озадачила. Вот код

static public Return fun1()
{
  return new register(new SomeMap[]{
         null, 
         new SomeMap(new Basic(String.class), new Basic(String.class))
  })
  { 
    @Override
    public Return getSomething(int val)
    {
     ....
    }
  };
}

Как видите, метод обратного вызова переопределения определен за пределами new register(..). Кажется, что функция обратного вызова определена снаружи в собственном блоке кода. Это возможно? Как это работает?

) находится перед переопределением функции.

Разве так не должно быть?

static public Return fun1()
    {
      return new register(new SomeMap[]{
             null, 
             new SomeMap(new Basic(String.class), new Basic(String.class))
      }
      
        @Override
        public Return getSomething(int val)
        {
         ....
        }
      );
    }




public static class register extends SomeMap
{
   public register(SomeMap[] somemaps)
   {
   }

    public Return getSomething(int val)
    {
     ....
    }
}

public static abstract class SomeMap
{
   // no constructors here just some method definitions here
}

person Yogi    schedule 15.06.2021    source источник
comment
Вы можете посчитать фигурные скобки и увидеть, что он определен внутри определения анонимного класса. Хотя похоже, что это написала пьяная обезьяна.   -  person Kayaman    schedule 15.06.2021
comment
когда я проверяю свою IDE, ) закрывается до того, как функция переопределит   -  person Yogi    schedule 15.06.2021
comment
Я не говорю о ), я говорю о {. ) предназначен для конструктора.   -  person Kayaman    schedule 15.06.2021
comment
но не должно ли переопределение функции происходить до )?   -  person Yogi    schedule 15.06.2021
comment
register является подклассом Return?   -  person shmosel    schedule 15.06.2021
comment
Да, это. регистр является производным от Return   -  person Yogi    schedule 15.06.2021


Ответы (1)


В то время как обычный простой анонимный класс выглядит просто

new Anonymous() {
    public void method() {
        // implementation
    }
};

В примере используется аргумент конструктора SomeMap[], но в остальном это то же самое.

new register(       // New anonymous class
    new SomeMap[]{  // Provide SomeMap[] for the constructor
         null,      // SomeMap[0] contains null
         new SomeMap(new Basic(String.class), new Basic(String.class)) // SomeMap[1] has data
    }) {            // End constructor 
        // Define the method, in the right place
        @Override
        public Return getSomething(int val) {
        }
    };  // End anonymous class

Я бы не позволил такому коду летать, даже если бы он был правильно отформатирован.

person Kayaman    schedule 15.06.2021
comment
Меня просто смущает та часть, в которой функция переопределения находится за пределами ). Разве он не должен следовать за блоком инициализатора сразу после? - person Yogi; 15.06.2021
comment
Блок инициализатора отсутствует. Определение метода должно находиться за пределами ), иначе оно будет внутри параметров конструктора. - person Kayaman; 15.06.2021
comment
ой. Я запутался, потому что это то, что описано здесь stackoverflow.com/questions/5310403/ Кроме того, getSomething() должен быть частью SomeMap, правильно? - person Yogi; 15.06.2021
comment
SomeMap (или, скорее, SomeMap[]) - параметр конструктора, так что неправильно. - person Kayaman; 15.06.2021
comment
Кроме того, мы не можем вызвать конструктор внутри анонимного класса, и поэтому мы используем блок инициализатора, верно? - person Yogi; 15.06.2021
comment
По-прежнему неправильно, вызывается конструктор абстрактного класса. Не тот распространенный синтаксис, по крайней мере, больше, что является еще одной причиной для переписывания этого кода. - person Kayaman; 15.06.2021
comment
Итак, вы имеете в виду, что мы вызываем конструктор для любого объекта, ожидаемого регистром, и этот конструктор объекта ожидает аргументов SomeMap, а метод getSomething является частью этого абстрактного класса? - person Yogi; 15.06.2021
comment
Я думал, что невозможно вызвать конструктор внутри анонимного класса. - person Yogi; 15.06.2021
comment
Итак, сегодня вы узнали кое-что новое. Это довольно необычно, IIRC вернулся с AbstractAction Swing, он получил некоторое применение, т.е. new AbstractAction("Push") {, тогда вы должны определить actionPerformed(). - person Kayaman; 15.06.2021
comment
Итак, register расширяет SomeMap. SomeMap - это абстрактный класс. SomeMap не имеет getSomething или конструктора. Как вызывается конструктор? - person Yogi; 15.06.2021
comment
Покажите все участвующие классы. В комментариях под вопросом вы утверждаете, что register расширяет Return. В коде четко указано, что существуют конструктор register(SomeMap[]) и метод Return getSomething(int), как это обеспечивается аннотацией @Override. - person Kayaman; 15.06.2021
comment
Я обновился. да. Класс Return расширяет SomeMap и имеет конструктор и getSomething, но мы вызываем конструктор SomeMap (который является абстрактным и не имеет конструктора). Мое замешательство в том, не следует ли переопределить метод из SomeMap? Но мы переопределяем метод из Return и вызываем конструктор из SomeMap (который явно не определен) - person Yogi; 16.06.2021
comment
Привет, извините :( Я обновил вопрос соответствующими классами - person Yogi; 16.06.2021
comment
Я обновил классы и соответствующие коды - person Yogi; 16.06.2021
comment
Да, создается новый анонимный подкласс register. Поскольку нет конструктора без аргументов, который мог бы быть вызван неявным super(), вам необходимо предоставить аргументы конструктора. - person Kayaman; 16.06.2021
comment
Итак, вкратце, мы создаем подкласс register. Поскольку мы хотим передать наши собственные значения для регистрации, мы передаем аргументы constructor регистра, а НЕ SomeMap. Конструктор register принимает аргументы типа SomeMap (абстрактный класс). Поскольку register имеет параметризованный конструктор, нам нужно вызывать его каждый раз. Всей этой путаницы можно было бы избежать, если бы мы просто использовали лямбды. - person Yogi; 16.06.2021
comment
@kayman: Я правильно понимаю? Большое спасибо за терпение и ясность ума .. - person Yogi; 16.06.2021
comment
Подкласс: да, мы должны передавать значения конструктору. SomeMap не имеет значения, поскольку конструкторы в любом случае не наследуются. SomeMap не может быть абстрактным, поскольку новый экземпляр создается в new SomeMap(new Basic(String.class), new Basic(String.class)). С другой стороны, register должен быть абстрактным, чтобы это имело какой-то смысл с точки зрения дизайна. Конкретный класс здесь является результатом плохого дизайна, недоразумения или взлома. - person Kayaman; 16.06.2021
comment
Извините, почему вы говорите, что register должен быть абстрактным? Почему иметь конкретный класс - плохой дизайн? И вы имеете в виду, что поскольку мы создаем экземпляр SomeMap, он больше не является абстрактным, даже если он объявлен? Даже я никогда не видел, чтобы конкретный класс использовался внутри анонимного класса. Вот с чего началась вся путаница - person Yogi; 16.06.2021
comment
Реализация интерфейса или расширение абстрактного класса, поскольку анонимный класс использовал пре-лямбда, но это очень сомнительно для конкретного класса. SomeMap не объявлен абстрактным классом на основе показанного вами кода. См. Строку 4 моего второго блока кода, где он явно создан. - person Kayaman; 16.06.2021
comment
Я добавил декларацию для SomeMap. SomeMap действительно объявлен как абстрактный класс. Но он создается, как вы показали в своем примере. - person Yogi; 16.06.2021
comment
Итак, либо вы смотрите не на нужный класс, либо у вас есть волшебный абстрактный класс, который можно создать с помощью конструктора, которого не существует. - person Kayaman; 16.06.2021
comment
:) Дай еще раз проверить - person Yogi; 16.06.2021
comment
Здесь написано java67.com/2013/ 02 /. абстрактный класс может иметь конструктор в Java. Вы можете либо явно предоставить конструктор абстрактному классу, либо, если вы этого не сделаете, компилятор добавит конструктор по умолчанию без аргументов в абстрактный класс. Это верно для всех классов, а также применимо к абстрактному классу. - person Yogi; 16.06.2021
comment
Вы по-прежнему не можете создать экземпляр абстрактного класса, поэтому существует явный конфликт между тем, что вы говорите, и тем, что говорит код. Но поскольку вы не показываете реальный код, гадать бесполезно, и это не имеет значения в отношении анонимного класса. - person Kayaman; 16.06.2021
comment
Я еще раз проверю. Вы мне очень помогли. Большое спасибо :) - person Yogi; 16.06.2021