web-dev-qa-db-ja.com

Java inner / local / subメソッドをサポートしていますか?

これは私のコードです。

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

ありがとうございました。

48
diewland

2014-02-09の更新:

JDK 8は、ラムダ(匿名関数式)を導入しました。これにより、次のように解決できます。

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

(JDK 7以下)

いいえ、Javaは「直接」ネストされたメソッドをサポートしていません(ただし、ほとんどの機能言語は、ScalaおよびClojure!)

ただし、参照用です。あなたはcanローカルクラス(メソッド内のクラス)を定義できるので、これはdoesコンパイルします

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。 ローカルクラスの制限

ローカルクラスには、次の制限があります。

  • ローカルクラスは、それを定義するブロック内でのみ表示されます。そのブロックの外部で使用することはできません。

  • ローカルクラスは、public、protected、private、またはstaticとして宣言できません。これらの修飾子は、クラスのメンバー用です。ローカル変数宣言またはローカルクラス宣言では使用できません。

  • メンバークラスと同様に、同じ理由で、ローカルクラスに静的フィールド、メソッド、またはクラスを含めることはできません。唯一の例外は、静的と最終の両方で宣言されている定数の場合です。

  • インターフェイスをローカルで定義することはできません。

  • ローカルクラスは、メンバークラスのように、それを囲むクラスと同じ名前を持つことはできません。

  • 前述のように、ローカルクラスは、スコープ内にあるローカル変数、メソッドパラメーター、および例外パラメーターさえも使用できますが、これらの変数またはパラメーターがfinalとして宣言されている場合のみです。これは、ローカルクラスのインスタンスの有効期間が、クラスが定義されているメソッドの実行よりもはるかに長い可能性があるためです。このため、ローカルクラスには、使用するすべてのローカル変数のプライベート内部コピーが必要です(これらのコピーはコンパイラーによって自動的に生成されます)。ローカル変数とプライベートコピーが常に同じになるようにする唯一の方法は、ローカル変数が最終であることを主張することです。

したがって、ご覧のとおり、これらの状況では最初のオプション(ネストされたメソッドなし)が望ましいです。

110
aioobe

簡単に言えば-いいえ。メソッドを別のメソッド内にネストすることはできません。

本当にこれをしたい場合、メソッド内でclassesを定義できます(奇妙なことに、以前の制限がある場合)。したがって、メソッドを外側のメソッド内のクラスにラップできます。

しかし、これはあまり慣用的ではなく、一般的な慣習は、おそらく目的に応じてグループ化されたプライベートメソッド(トップレベルクラス)のリストを持ち、グループを区切るコメントブロックがあるようです。


ただし、Scalaを使用していることに気付いた場合は、メソッドをネストして思いのままに入れてください...

8
Andrzej Doyle

匿名の内部クラスであるこの方法でも試すことができます。

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

任意のメソッド内でラムダを記述することが可能です。

たとえば、ラムダを使用して再帰的なメソッドを作成します。

のようなオブジェクトを期待する

class Foo{
   Foo parent;
}

ラムダメソッド式のインターフェイス

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

トップレベルFoo.parentを取得するための再帰findRootメソッド

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
Spektakulatius

匿名クラスを使用できます。このようなもの;

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

必要に応じて、同じインターフェースで異なるタイプの操作を定義し、好きなように渡すことができます。

0
firefox1986