2016-04-23 4 views
5

Я пытаюсь использовать класс 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).

Однако, в общем, мне интересно, можно ли получить доступ к методу экземпляра во время создания объекта?

ответ

3

Почему бы не написать отдельный конструктор, который допускает инициализацию 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; 
    } 
} 

UPDATE

И еще один способ, без введения новых методов или конструкторов:

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

An anonymous class в настоящее время экземпляра путем расширения BitSet и добавление instance initialization block, отсюда double curly braces.

+0

Я очень слаб в дженериках. Но выше именно то, что я ищу. Это кратким и позволяет мне использовать оператор 'this'. Тогда у меня может быть общий код инициализации в конструкторе, отличном от стандартного. Благодаря! –

+0

Третий вариант, который вы добавили. Каков термин для этого подхода, если таковой имеется? –

+0

Это «блок инициализатора экземпляра», но, как он появляется в теле анонимного класса, он выглядит так, как будто это особый синтаксис (это не так). По этой причине люди часто называют это [идиомой «Двойные брекеты»] (http://stackoverflow.com/questions/1958636/what-is-double-brace-initialization-in-java). Это часто описывается в [anti-patterns] (https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/) для инициализации вложенной коллекции , Однако способ, которым он вводится здесь, должен быть в порядке. – YoYo

0

Нет; это должно быть сделано как отдельный звонок, который будет выполнен после. Строительство объекта завершено. Единственный способ сделать это в одной строке в вашей ситуации, если тип возвращаемого значения был BitSet и метод возвратил экземпляр он был вызван на, в этом случае вы могли бы сделать

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

К сожалению, set() это void, поэтому вы не можете этого сделать.

2

У BitSet нет свободного интерфейса, поэтому что-то вроде new BitSet(4).set(0,3) не работает для BitSets. Существуют только статические методы BitSet.valueOf(), но они несколько неудобны в использовании. Однако, если вы хотите статическую конфигурацию, вы можете просто создать экземпляр BitSet с нужным значением, используйте BitSet.toLongArray(), напечатайте значения массива и создайте экземпляр своего BitSet. В вашем конкретном примере конструктор по умолчанию может быть:

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

Что касается общей части вопроса: Она будет работать только если у вас есть «сеттер», который возвращает текущий объект, который позволит вам ЦЕПЬ звонки. Так что для ваших собственных классов, которые вы могли бы сделать что-то вроде этого:

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 обычно не имеют их.

Смежные вопросы