2016-04-23 18 views
5

Sto cercando di utilizzare la classe java BitSet come campo per una classe personalizzata. E voglio che la classe usi un BitSet predefinito con tutti i bit impostati.La chiamata al metodo dell'oggetto può essere eseguita simultaneamente con l'istanza dell'oggetto?

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

Per default BitSet costruttore non mostra tutte bit. Quindi, prima di inviarlo come oggetto anonimo, mi piacerebbe chiamare il metodo set(int, int) per impostare tutti i bit. So che potrei semplicemente inizializzare il campo mask in un nuovo BitSet e quindi chiamare il metodo set(int, int) da lì.

Tuttavia, in generale, mi chiedo se sia possibile accedere a un metodo di istanza al momento dell'istanza dell'oggetto?

risposta

3

Perché non scrivere un costruttore separato che consente l'inizializzazione BitSet?Utilizzo di Java 8, questo potrebbe apparire come qualcosa di simile:

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

Si può anche fare che più generico con l'introduzione di un metodo statico con parametri di tipo:

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

In tal caso, la prima MyClass sarebbe il seguente aspetto:

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

E c'è un altro modo, senza introdurre nuovi metodi o costruttori:

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

Un anonymous class viene creata un'istanza estendendo BitSet e aggiungendo un instance initialization block, quindi il double curly braces.

+0

Sono molto debole nei generici. Ma sopra è esattamente quello che sto cercando. È conciso e mi permette anche di usare l'operatore 'this'. Quindi posso avere codice di inizializzazione comune nel costruttore non predefinito. Grazie! –

+0

La terza opzione che hai aggiunto. Qual è il termine per questo approccio, se esiste? –

+0

È un 'Istance Initializer Block', ma come appare all'interno del corpo di una classe anonima, sembra come se fosse una sintassi speciale (non lo è). Per questo motivo, le persone spesso si riferiscono ad esso come [l'espressione "Double Braces"] (http://stackoverflow.com/questions/1958636/what-is-double-brace-initialization-in-java). Viene spesso descritto in [anti-pattern] (https://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/) per l'inizializzazione della raccolta nidificata . Tuttavia, il modo in cui viene presentato qui dovrebbe essere ok. – YoYo

0

No; che dovrebbe essere fatto come una chiamata separata, che verrà eseguita dopo la costruzione dell'oggetto è terminata. L'unico modo per farlo in una sola riga nella vostra situazione è se il tipo di ritorno del metodo era stato BitSet e il metodo era tornato l'istanza è stato invocato su, nel qual caso si avrebbe potuto fare

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

Purtroppo, set() è void, quindi non puoi farlo.

2

BitSet non ha un'interfaccia fluente, quindi qualcosa come new BitSet(4).set(0,3) non funziona con BitSet. Esistono solo i metodi statici BitSet.valueOf(), ma quelli sono piuttosto scomodi da usare. Tuttavia, se si desidera una configurazione statica, è sufficiente creare un'istanza di un BitSet con il valore desiderato, utilizzare BitSet.toLongArray(), stampare i valori dell'array e creare un'istanza di BitSet con esso. Nel tuo esempio specifico il costruttore di default potrebbe essere:

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

Per quanto riguarda la parte generale della domanda: Che avrebbe funzionato solo se si dispone di un "setter" che restituisce l'oggetto corrente, che permetterebbe a catena chiamate. Così, per le proprie classi si potrebbe fare qualcosa di simile:

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

Se è stato utilizzato che in un costruttore come con il BitSet si può fare this(new A().withNum(4));

interfacce fluente sono piuttosto popolari (ad esempio, l'AWS SDK è che ovunque), solo gli oggetti JDK non li hanno di solito.

Problemi correlati