web-dev-qa-db-fra.com

Java prend-il en charge les méthodes internes/locales/sous-titres?

Ceci est mon code.

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());
    }
}

Puis-je faire quelque chose comme ça?

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());
    }
}

Je vous remercie.

45
diewland

Mise à jour 2014-02-09:

JDK 8 a introduit les lambdas (expressions de fonction anonymes) qui permettent de le résoudre comme ceci:

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

(JDK 7 et inférieur)

Non, Java ne prend pas en charge les méthodes imbriquées "directement". (La plupart des langages fonctionnels le font cependant, y compris certains langages JVM tels que Scala et Clojure!)

Juste pour référence si; Vous pouvez définissez des classes locales (classes au sein de méthodes) afin que cette fait compile

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());
    }
}

Notez cependant qu'il existe quelques restrictions sur les classes locales

3.11.2. Restrictions sur les classes locales

Les cours locaux sont soumis aux restrictions suivantes:

  • Une classe locale n'est visible que dans le bloc qui la définit; il ne peut jamais être utilisé en dehors de ce bloc.

  • Les classes locales ne peuvent pas être déclarées publiques, protégées, privées ou statiques. Ces modificateurs sont destinés aux membres de classes; ils ne sont pas autorisés avec les déclarations de variable locale ou les déclarations de classe locale.

  • Comme les classes membres et pour les mêmes raisons, les classes locales ne peuvent pas contenir de champs, méthodes ou classes statiques. La seule exception concerne les constantes déclarées statiques et finales.

  • Les interfaces ne peuvent pas être définies localement.

  • Une classe locale, comme une classe membre, ne peut pas porter le même nom que l'une de ses classes englobantes.

  • Comme indiqué précédemment, une classe locale peut utiliser les variables locales, les paramètres de méthode et même les paramètres d'exception figurant dans sa portée, mais uniquement si ces variables ou paramètres sont déclarés finaux. En effet, la durée de vie d'une instance d'une classe locale peut être beaucoup plus longue que l'exécution de la méthode dans laquelle la classe est définie. Pour cette raison, une classe locale doit disposer d'une copie interne privée de toutes les variables locales qu'elle utilise (ces copies sont automatiquement générées par le compilateur). Le seul moyen de s'assurer que la variable locale et la copie privée sont toujours identiques est d'insister pour que la variable locale soit finale.

Comme vous pouvez le constater, votre première option (sans méthodes imbriquées) est préférable dans ces situations.

107
aioobe

vous pouvez aussi essayer de cette manière une classe interne anonyme.

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);
    }
}
2
GuruKulki

Il est possible d'écrire des lambdas dans n'importe quelle méthode.

En utilisant lambda par exemple pour créer une méthode récursive:

Attendre un objet comme 

class Foo{
   Foo parent;
}

Interface pour l'expression de la méthode lambda

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

Méthode récursive findRoot pour obtenir le Foo.parent de niveau supérieur

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
Code.IT

Vous pouvez utiliser une classe anonyme. Quelque chose comme ça;

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);
    }
}

Si vous le souhaitez, vous pouvez définir différents types d'opérations avec la même interface et les transmettre à votre guise.

0
firefox1986