【问题标题】:Does Java support inner / local / sub methods?Java 是否支持内部/本地/子方法?
【发布时间】:2011-07-20 07:16:26
【问题描述】:

这是我的代码。

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

谢谢。

【问题讨论】:

  • 如果您将示例输入到 IDE 中,它的编译器就会告诉您答案。
  • Nested functions in Java的可能重复
  • @Bombe,不是真的。 IDE 可以确定 OP 是否可以完全做到这一点。如果您仔细阅读,您会注意到问题是“我可以做类似的事情吗?”

标签: java methods


【解决方案1】:

2014-02-09 更新:

JDK 8 引入了 lambdas(匿名函数表达式),允许您像这样解决它:

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

请注意,虽然有一些 restrictions on local classes

3.11.2。 本地类的限制

本地类受以下限制:

  • 本地类仅在定义它的块内可见;它永远不能在该块之外使用。

  • 不能将本地类声明为 public、protected、private 或 static。这些修饰符用于类的成员;它们不允许与局部变量声明或局部类声明一起使用。

  • 与成员类一样,出于同样的原因,本地类不能包含静态字段、方法或类。唯一的例外是声明为 static 和 final 的常量。

  • 接口不能在本地定义。

  • 一个本地类,就像一个成员类,不能与它的任何封闭类同名。

  • 如前所述,局部类可以使用其范围内的局部变量、方法参数甚至异常参数,但前提是这些变量或参数声明为 final。这是因为本地类实例的生命周期可能比定义该类的方法的执行时间长得多。出于这个原因,本地类必须拥有它使用的所有局部变量的私有内部副本(这些副本由编译器自动生成)。确保局部变量和私有副本始终相同的唯一方法是坚持局部变量是最终变量。

因此,如您所见,在这些情况下,您的第一个选项(没有嵌套方法)更可取。

【讨论】:

  • 主要 +1 以使此答案保持最新。
  • Trible中的方法trible可以是static吗?这将避免必须创建一个对象new Trible(),因为您可以只调用静态方法:Trible.trible("X")。在相关的说明中,Trible 类本身可以是static 吗?这会带来什么好处吗?
  • 没有。它在 3.11.2 下的第二个项目符号中。
【解决方案2】:

很简单——不。您不能将一个方法嵌套在另一个方法中。

如果你真的想要这样做,你可以在方法中定义(奇怪的是,考虑到前面的限制),因此可以将你的方法包装在一个类中外部方法。

但是,这不是很惯用,一般做法似乎是有一个私有方法列表(在顶级类中),可能根据目的进行分组,并用注释块划分组。


但是,如果您碰巧发现自己使用 Scala,您可以随心所欲地嵌套方法...

【讨论】:

    【解决方案3】:

    你也可以试试这种方式,匿名内部类。

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

    【讨论】:

      【解决方案4】:

      您可以使用匿名类。像这样的东西;

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

      如果您愿意,您可以使用相同的接口定义不同类型的操作,然后随意传递这些操作。

      【讨论】:

        【解决方案5】:

        可以在任何方法中编写 lambda。

        例如使用 lambda 创建递归方法:

        期待像

        这样的对象
        class Foo{
           Foo parent;
        }
        

        lambda 方法表达式的接口

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

        【讨论】:

          猜你喜欢
          • 2021-10-23
          • 1970-01-01
          • 2021-10-20
          • 2014-12-12
          • 2022-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多