【问题标题】:Can object method call be done simultaneously with object instantiation?对象方法调用可以与对象实例化同时进行吗?
【发布时间】:2016-04-23 03:35:29
【问题描述】:

我正在尝试使用 java 类 BitSet 作为自定义类的字段。我希望该类使用设置所有位的默认 BitSet。

import java.util.BitSet;

public class MyClass {
    private BitSet mask;

    public MyClass() {
        this(new BitSet(4));
        // want to set all bits first
        // something like 
        // this( new BitSet(4).set(0,3) );
    }

    public MyClass(BitSet mask) {
        this.mask = mask;
    }    
}

默认情况下,BitSet 构造函数会取消设置所有位。所以在我将它作为匿名对象发送之前,我想调用set(int, int) 方法来设置所有位。我知道我可以简单地将字段mask 初始化为新的BitSet,然后从那里调用set(int, int) 方法。

但是,总的来说,我想知道是否可以在对象实例化时访问实例方法?

【问题讨论】:

    标签: java this instantiation


    【解决方案1】:

    为什么不编写一个允许BitSet 初始化的单独构造函数呢?使用 Java 8,这可能看起来像这样:

    public class MyClass {
      private BitSet mask;
      public MyClass() {
        this(new BitSet(4),(m)->m.set(0,3));
      }
      public MyClass(BitSet mask,Consumer<BitSet> initializer) {
        initializer.accept(mask);
        this.mask = mask;
      }
    }
    

    您甚至可以通过引入带有类型参数的静态方法来使其更通用:

    public static <T> T initialize(T t,Consumer<T> initializer) {
      initializer.accept(t);
      return t;
    } 
    

    在这种情况下,较早的 MyClass 如下所示:

    public class MyClass {
      private BitSet mask;
      public MyClass() {
        this(initialize(new BitSet(4),(m)->m.set(0,3)));
      }
      public MyClass(BitSet mask) {
        this.mask = mask;
      }
    }
    

    更新

    还有一种方法,不需要引入新的方法或构造函数:

    public class MyClass {
      private BitSet mask;
      public MyClass() {
        this(new BitSet(4) {{ set(0,3); }});
      }
      public MyClass(BitSet mask) {
        this.mask = mask;
      }
    }
    

    通过扩展BitSet 并添加instance initialization block 来实例化anonymous class,因此double curly braces

    【讨论】:

    • 我在泛型方面很薄弱。但上面正是我正在寻找的。它简洁,还允许我使用this 运算符。然后我可以在非默认构造函数中有通用的初始化代码。谢谢!
    • 您添加的第三个选项。这种方法的术语是什么?
    • 它是一个'Instance Initializer Block',但是当它出现在一个匿名类的主体中时,它看起来好像是一些特殊的语法(它不是)。因此,人们通常将其称为the 'Double Braces' idiom。在anti-patterns 中经常描述嵌套集合初始化。不过这里介绍的方式应该没问题。
    【解决方案2】:

    BitSet 没有流畅的界面,所以像 new BitSet(4).set(0,3) 这样的东西不适用于 BitSet。只有静态的 BitSet.valueOf() 方法,但使用起来有些尴尬。但是,如果您想要一个静态配置,您可以只用所需的值实例化一个 BitSet,使用 BitSet.toLongArray(),打印数组值并用它实例化您的 BitSet。在您的具体示例中,默认构造函数可能是:

    public MyClass() {
        this(BitSet.valueOf(new long[]{7}));
    }
    

    至于问题的一般部分:它只有在你有一个返回当前对象的“setter”时才有效,这将允许你链接调用。因此,对于您自己的课程,您可以执行以下操作:

    public class A {
        private int num;
    
        public int getNum() {
            return num;
        }
        public void setNum(int num) {
            this.num = num;
        }
        public A withNum(int num) {
           setNum(num);
           return this;
       }
    }
    

    如果你在像 BitSet 这样的构造函数中使用它,你可以这样做 this(new A().withNum(4));

    Fluent 接口非常流行(例如 AWS 开发工具包到处都有),只是 JDK 对象通常没有它们。

    【讨论】:

      【解决方案3】:

      没有;这必须作为一个单独的调用来完成,该调用将在对象的构造完成后执行。在您的情况下,在一行中执行此操作的唯一方法是,如果方法的返回类型是 BitSet 并且该方法返回了调用它的实例,在这种情况下您可以这样做

      this(new BitSet(4).set(0, 1)); // Doesn't actually work
      

      很遗憾,set()void,所以你不能这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-22
        相关资源
        最近更新 更多