【问题标题】:How can I access a method of an "unnamed" class?如何访问“未命名”类的方法?
【发布时间】:2012-06-15 01:48:35
【问题描述】:
public class Test {
    public static void main(String[] args) {
        DemoAbstractClass abstractClass = new DemoAbstractClass() {
            private String val;

            @Override
            public void runner() {
                val = "test";
                System.out.println(val);
                this.run();
            }

            public String getVal() {
                return val;
            }
        };

        abstractClass.runner();

        /**
         * I want to access getVal method here
         */
    }
}

abstract class DemoAbstractClass {
    public void run() {
        System.out.println("running");
    }

    public abstract void runner();
}

在这里,我声明一个抽象类DemoAbstractClass。我显然可以创建一个扩展此类的新类并将此方法添加到其中。但是,我不希望在我的场景中这样做。 有没有其他方法可以访问上述代码中的 getVal 方法??

【问题讨论】:

标签: java inheritance abstract-class


【解决方案1】:

你不能。您需要从中创建一个适当的(非异常)类。如果您想限制其范围,请将其设为内部私有类。

或者,您可以使用 StringBuffer 并在方法之间共享对它的引用。但是不是很干净。

相关问题:

【讨论】:

  • “私有内部类”似乎是问题的最终答案。使用 StringBuilder 将是语言设计者的一场糟糕游戏。 ;)
  • 另一个疑问.. 私有内部类或本地类会更好(如您建议的链接答案中给出的)。
  • 本地人的范围会更窄,所以如果可能的话,去吧。
【解决方案2】:

没有使用反射,你不能因为你无法访问对象的具体类型才能将方法调用绑定到

如果您不想以理智的方式做这样的事情,请声明一个命名类并将其用作 abstractClass 的类型

【讨论】:

    【解决方案3】:

    很遗憾,如果您无法命名类型,则无法访问语言级别的方法。

    不过,您可以使用反射 API 获取 Method 对象并在此对象上获取 invoke

    然而,这很慢。私有类或私有接口会快得多。

    【讨论】:

    • 同意!!反思将成为这里的负担。私有类/接口(或本地类)是这里的完美解决方案。
    【解决方案4】:

    我显然可以创建一个新的类来扩展这个类并将这个方法添加到它。

    你已经这样做了;最终结果是一个匿名内部类:new DemoAbstractClass() { ... }; 如果您只是将该声明移到它自己的类中——您甚至可以将其设为私有类——您可以访问 getVal。

    根据您上面的示例:

    public class Test {
        public static void main(String[] args) {
            DemoClass abstractClass = new DemoClass();
    
            abstractClass.runner();
    
            /**
             * I want to access getVal method here
             */
            abstractClass.getVal(); // can do this here now
        }
    
        private class DemoClass extends DemoAbstractClass {
    
                private String val;
    
                @Override
                public void runner() {
                    val = "test";
                    System.out.println(val);
                    this.run();
                }
    
                public String getVal() {
                    return val;
                }
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      另一种选择是让 StringBuilder 成为 main 方法的成员,并使用匿名内部方法的闭包特性:

      public static void main(String[] args) {
          final StringBuilder value = new StringBuilder();
          DemoAbstractClass abstractClass = new DemoAbstractClass() {
              @Override
              public void runner() {
                  value.append( "test" );
                  System.out.println(val);
                  this.run();
              }
          };
      
          abstractClass.runner();
      
          // use val here...
          String val = value.toString();
      }
      

      【讨论】:

      • 我喜欢这个答案,但它更像是一种“替代安排”。如果您的匿名对象包含 String 以外的成员怎么办?
      • 我从不在匿名类中使用成员/实例变量。我总是使用在类定义之外定义的变量,并依靠闭包来访问它们。只要它是可变的,它就适用于任何类型的变量。它必须是可变的,因为引用必须是最终的。换句话说,您只能编辑引用变量的值,而不是引用本身,这就是我使用 StringBuilder 而不是 String 的原因。
      • 我也选择了类似的方法,使用最终列表来保存我的对象数据,但我被要求寻找更好的方法..
      猜你喜欢
      • 2015-07-28
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-10-11
      • 2020-10-12
      • 2013-09-03
      • 2015-11-14
      相关资源
      最近更新 更多