对象方法调用可以和对象实例化同时进行吗?

Can object method call be done simultaneously with object instantiation?

我正在尝试使用 java class BitSet 作为自定义 class 的字段。我希望 class 使用所有位都设置的默认 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) 方法。

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

否;这必须作为一个单独的调用来完成,它将在对象的构造完成后执行。在你的情况下,在一行中完成它的唯一方法是如果方法的 return 类型是 BitSet 并且方法已经 returned 调用它的实例,在这种情况下你本来可以的

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

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

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

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

至于问题的一般部分:只有当您有 "setter" 当前对象 returns 时,它才会起作用,这将允许您链接调用。所以对于你自己的 类 你可以这样做:

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 SDK 到处都有),只是 JDK 对象通常没有。

为什么不编写一个允许 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;
  }
}

一个anonymous class is being instantiated by extending BitSet and adding an instance initialization block, hence the double curly braces.