Java: singleton e static instans

0 views
Skip to first unread message

mick...@posteo.net

unread,
Mar 5, 2025, 7:13:14 AMMar 5
to Socraten
Ciao a tutti.
Mi ritrovo in una situazione che non riesco a capire.

Ho una classe (derivata da una abstract) che si vuole gestita come
singleton, in cui è dichiarata una istanza static ad un oggetto della
classe stessa. Per capirci:

class Class1 extends AbstClass {
Class1 INSTANCE = new Class();

private final List<Cosa> listaCose = new LinkedList<>();
[...]
}

Così com'è sembra funzionare. Ora però io vorrei aggiungere un
costruttore, in cui aggiungo alcuni elementi a listaCose, ma se lo
faccio, lanciando il test unitario dove uso INSTANCE, solleva
un'eccezione java.lang.NoClassDefFoundError: Could not initialize class
Class1.

Secondo voi cosa non torna?
--
Mick

mick...@posteo.net

unread,
Mar 5, 2025, 7:16:48 AMMar 5
to Socraten
Aggiungo un dettaglio: se metto l'inizializzazione in un generico metodo
della classe, allora funziona:

public getListaCose() {
if(listaCose.isEmpty()) {
[... inizializza listaCose ...]
}
return listaCose;
}

--
Michele

mick...@posteo.net

unread,
Mar 5, 2025, 7:32:26 AMMar 5
to Socraten
On 05.03.2025 13:16, mick...@posteo.net wrote:
> On 05.03.2025 13:13, mick...@posteo.net wrote:
>>
>> Ora però io vorrei aggiungere un
>> costruttore, in cui aggiungo alcuni elementi a listaCose
>>
Forse comincio a capire (anche se non del tutto). Il dettaglio che
mancava nella mia descrizione, è che l'inizializzazione della lista,
avviene tramite chiamate ad un metodo della classe (astratta) padre.
Da notare che non è rilevante quello che viene effettivamente fatto da
tale metodo, l'eccezione viene sollevata nel momento in cui si tenta di
invocarla.
--
Michele

mick...@posteo.net

unread,
Mar 5, 2025, 7:55:04 AMMar 5
to Socraten
Ok, ho definitivamente compreso il meccanismo, indagando nelle
implementazioni delle classi padre: il metodo che viene invocato, si
appoggia su diversi membri static della classe stessa, quindi
l'inizializzazione del membro INSTANCE = new Class1(); va fatta
SUCCESSIVAMENTE all'inizializzazione dei membri di cui ha bisogno -
sostanzialmente l'ultima cosa che viene fatta, prima della dichiarazione
del costruttore.

Chiedo venia per il rumore inutile...
--
Michele

Simone Bordet

unread,
Mar 5, 2025, 2:25:15 PMMar 5
to socr...@googlegroups.com
Ciao,

On Wed, Mar 5, 2025 at 1:55 PM <mick...@posteo.net> wrote:
> Ok, ho definitivamente compreso il meccanismo, indagando nelle
> implementazioni delle classi padre: il metodo che viene invocato, si
> appoggia su diversi membri static della classe stessa, quindi
> l'inizializzazione del membro INSTANCE = new Class1(); va fatta
> SUCCESSIVAMENTE all'inizializzazione dei membri di cui ha bisogno -
> sostanzialmente l'ultima cosa che viene fatta, prima della dichiarazione
> del costruttore.

Non so se il codice che hai postato qui è quello reale, ma di solito
il singleton è "static".

Questo significa che è inizializzato prima di qualsiasi non-static
field, prima dei costruttori, ecc.

Altrimenti non è un singleton, è solo una istanza in più con uno stato diverso.

Anche per l'inizializzazione della lista, devi stare attento a
sincronizzare l'accesso, altrimenti più threads possono inizializzarla
a valori diversi.

Insomma, stai attento :)

--
Simone Bordet
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless. Victoria Livschitz

mick...@posteo.net

unread,
Mar 6, 2025, 3:06:35 AMMar 6
to socr...@googlegroups.com


On 05.03.2025 20:24, Simone Bordet wrote:
> Ciao,
>
> On Wed, Mar 5, 2025 at 1:55 PM <mick...@posteo.net> wrote:
>
> Non so se il codice che hai postato qui è quello reale, ma di solito
> il singleton è "static".
>
Hai ragione su tutti i fronti.
Purtroppo non ho grandi margini di manovra, a causa di vincoli
imposti dalla classe padre, su cui non sono autorizzato a mettere
mano (anche alla luce del fatto che potrebbe influenzare un
mondo di altre classi che ereditano da essa).
Ho messo il costruttore private, e ovunque ci sia bisogno di
un'istanza, la prende dal membro INSTANCE, che appunto è
static.

Per il resto qui vige la regola "finché funziona non toccarlo", di
cui io non sono grande sostenitore.

Comunque sia sono già abbastanza soddisfatto del risultato
ottenuto fin'ora.
All'inizio c'era un getter "lazy" che riempiva direttamente la lista
quando la trovava vuota.
--
Michele
Reply all
Reply to author
Forward
0 new messages