Поддерживает ли Java внутренние / локальные / суб методы? - PullRequest
48 голосов
/ 22 марта 2011

Это мой код.

public class SubFunction {
    private String drawTribleX(){
        return trible("X");
    }
    private String trible(String t){
        return t + t + t;
    }
    public static void main(String[] args){
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }
}

Могу ли я сделать что-то подобное?

public class SubFunction {
    private String drawTribleX(){
        // *** move trible(t) inside drawTribleX() ***
        private String trible(String t){
            return t + t + t;
        }
        return trible("X");
    }
    public static void main(String[] args){
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }
}

Спасибо.

Ответы [ 5 ]

110 голосов
/ 22 марта 2011

Обновление 2014-02-09:

JDK 8 введены лямбда-выражения (выражения анонимных функций), которые позволяют решить эту проблему следующим образом:

Function<String, String> trible = s -> s+s+s;
System.out.println(trible.apply("X"));           // prints XXX

(JDK 7 и ниже)

Нет, Java не поддерживает "напрямую" вложенные методы.(Однако большинство функциональных языков, включая некоторые языки JVM, такие как Scala и Clojure!)

Только для справки;Вы можете определять локальные классы (классы внутри методов), так что компилирует

class SubFunction {
    private String drawTribleX(){

        // *** move trible(t) inside drawTribleX() ***
        class Trible {
            private String trible(String t){
                return t + t + t;
            }
        }

        return new Trible().trible("X");
    }
    public static void main(String[] args){
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }
}

Обратите внимание, что существуют некоторые ограничения для локальных классов

3.11.2. Ограничения на локальные классы

На локальные классы распространяются следующие ограничения:

  • Локальный класс виден только в пределах блока, который его определяет;его нельзя использовать вне этого блока.

  • Локальные классы не могут быть объявлены как публичные, защищенные, частные или статические.Эти модификаторы предназначены для членов классов;они не допускаются для объявлений локальных переменных или объявлений локальных классов.

  • Как и классы-члены, и по тем же причинам локальные классы не могут содержать статические поля, методы или классы.Единственное исключение - константы, объявленные как статические, так и конечные.

  • Интерфейсы не могут быть определены локально.

  • Локальный класс, такой каккласс-член не может иметь того же имени, что и любой из его окружающих классов.

  • Как отмечалось ранее, локальный класс может использовать локальные переменные, параметры метода и даже параметры исключения, которые находятся вего область действия, но только если эти переменные или параметры объявлены окончательными.Это связано с тем, что время жизни экземпляра локального класса может быть намного больше, чем выполнение метода, в котором определен класс.По этой причине локальный класс должен иметь закрытую внутреннюю копию всех локальных переменных, которые он использует (эти копии автоматически генерируются компилятором).Единственный способ убедиться, что локальная переменная и личная копия всегда одинаковы, это настаивать на том, что локальная переменная является конечной.

Итак, как вы можете видеть, вашаПервый вариант (без вложенных методов) предпочтителен в этих ситуациях.

8 голосов
/ 22 марта 2011

Проще говоря - нет. Вы не можете вложить метод в другой метод.

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

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


Однако, если вам случится использовать Scala, вы можете вкладывать методы так, как душе угодно ...

2 голосов
/ 22 марта 2011

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

public class SubFunction {
    private String drawTribleX() {
        // *** move trible(t) inside drawTribleX() ***
        Trible t = new Trible() {
            public String trible(String t) {
                return t + t + t;
            }
        };
        return t.trible("X");
    }

    public static void main(String[] args) {
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }

    interface Trible {
        String trible(String t);
    }
}
0 голосов
/ 07 ноября 2018

Можно писать лямбда-выражения внутри любого метода.

Используя лямбду, например, для создания рекурсивного метода:

Ожидается объект типа

class Foo{
   Foo parent;
}

Интерфейс длявыражение лямбда-метода

public interface Function<ARGUMENTTYPE, RETURNTYPE>{
    RETURNTYPE apply(ARGUMENTTYPE argument);
}

Рекурсивный findRoot метод для получения верхнего уровня Foo.parent

private Foo findRoot(final Foo foo) {
    //Create a Lambda Function for recursive search.
    final Function<Foo, Foo> recursiveSearch = new Function<Foo, Foo>() {
        @Override
        public Foo apply(final Foo fee) {
            //is the parent null return null
            if (fee.parent == null) {
                return null;
            } else if (fee.parent.equals(fee)) {
                //safety check ;-)
                throw new IllegalStateException("Circular Dependencies of " + fee.toString());
            } else {
                Foo parentFoo = fee.parent;
                //check if parent has parent otherwise return parent in else block
                if (parentFoo != null && parentFoo.parent != null) {
                    return this.apply(parentFoo);
                } else {
                    return parentMarket;
                }
            }
        }
    };
    //get the root
    final Foo rootFoo = recursiveSearch.apply(foo);
    //Safety check 2 ;-)
    if (rootFoo != null && rootFoo.equals(foo)) {
        throw new IllegalStateException("Circular Dependencies of " + foo.toString)();
    }
    return rootFoo;
}
0 голосов
/ 22 марта 2011

Вы можете использовать анонимный класс.Примерно так:

class SubFunction {

    public static void main(String[] args) {
        SubFunction o = new SubFunction();
        System.out.println(o.drawTribleX());
    }

    private String drawTribleX() {
        MyTrible trible = new MyTrible() {
            @Override
            public String doTrible(String t) {
                return t + t + t;
            }
        };

        return trible.doTrible("X");
    }

    private interface MyTrible {
        public String doTrible(String t);
    }
}

Если вы хотите, вы можете определить различные типы операций с одним и тем же интерфейсом и передавать их по своему усмотрению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...