Perché il confronto del valore della stringa dell'operatore == non è arrivato a Java?


50

Ogni programmatore Java competente sa che è necessario utilizzare String.equals () per confrontare una stringa, anziché == perché == verifica l'uguaglianza di riferimento.

Quando ho a che fare con le stringhe, la maggior parte delle volte cerco l'uguaglianza di valore piuttosto che l'uguaglianza di riferimento. Mi sembra che sarebbe più intuitivo se la lingua permettesse di confrontare i valori di stringa semplicemente usando ==.

Come confronto, l' operatore == di C # verifica la parità di valore per le stringhe . E se hai davvero bisogno di verificare l'uguaglianza di riferimento, puoi usare String.ReferenceEquals.

Un altro punto importante è che le stringhe sono immutabili, quindi non è possibile fare alcun danno consentendo questa funzione.

C'è qualche motivo particolare per cui questo non è implementato in Java?


12
Potresti voler guardare Scala, dove si ==trova l'uguaglianza degli oggetti ed eqè l'uguaglianza di riferimento ( ofps.oreilly.com/titles/9780596155957/… ).
Giorgio,

Proprio come una nota, e questo potrebbe non aiutarti, ma per quanto mi ricordo, puoi confrontare i letterali delle stringhe con un '=='
Kgrover

10
@Kgrover: puoi, ma è solo un comodo sottoprodotto dell'uguaglianza di riferimento e di come Java ottimizza in modo aggressivo i letterali di corrispondenza delle stringhe in riferimenti allo stesso oggetto. In altre parole, funziona, ma per ragioni sbagliate.
martedì

1
@aviv l' ==operatore esegue la mappatura solo Equalsse l' ==operatore è stato implementato in quel modo. Il comportamento predefinito per ==è lo stesso di ReferenceEquals(in realtà, ReferenceEqualsè definito come la versione oggetto di ==)
Patrick Huizinga

3
È una conseguenza delle decisioni di progettazione che hanno molto senso in molti altri scenari. Ma poiché sembri saperlo e lo stai facendo comunque, mi sento in dovere di rispondere alla tua domanda: perché deve esserci un caso d'uso per il confronto dei riferimenti di stringa?
Jacob Raihle,

Risposte:


90

Immagino sia solo coerenza o "principio del minimo stupore". String è un oggetto, quindi sarebbe sorprendente se fosse trattato in modo diverso rispetto ad altri oggetti.

All'epoca in cui uscì Java (~ 1995), avere semplicemente qualcosa di simile Stringera un lusso totale per la maggior parte dei programmatori che erano abituati a rappresentare le stringhe come array a terminazione nulla. StringIl comportamento è ora quello che era allora, ed è buono; cambiare in modo sottile il comportamento in seguito potrebbe avere effetti sorprendenti e indesiderati nei programmi di lavoro.

Come nota a margine, è possibile utilizzare String.intern()per ottenere una rappresentazione canonica (internata) della stringa, dopo la quale è possibile effettuare i confronti ==. Lo stage richiede un po 'di tempo, ma dopo, i confronti saranno molto veloci.

Aggiunta: a differenza di alcune risposte suggerite, non si tratta di supportare il sovraccarico dell'operatore . L' +operatore (concatenazione) funziona su Strings anche se Java non supporta il sovraccarico dell'operatore; è semplicemente gestito come un caso speciale nel compilatore, risolvendo StringBuilder.append(). Allo stesso modo, ==avrebbe potuto essere trattato come un caso speciale.

Allora perché stupire con il caso speciale +ma non con ==? Perché, +semplicemente non si compila quando applicato a non Stringoggetti, quindi è subito evidente. Il diverso comportamento di ==sarebbe molto meno evidente e quindi molto più sorprendente quando ti colpisce.


8
Casi speciali aggiungono stupore.
Blrfl

17
Le stringhe erano un lusso nel 1995? Veramente?? Guarda la storia dei linguaggi informatici. Il numero di lingue che all'epoca avevano un certo tipo di stringa supererebbe di gran lunga quelle che non lo erano. Quante lingue oltre a C e ai suoi discendenti hanno usato array con terminazione null?
WarrenT

14
@WarrenT: Certo, alcune lingue (se non la maggior parte) avevano un qualche tipo di stringa, ma nel 1995 credo che le stringhe raccolte con immondizia compatibili con Unicode fossero una novità. Ad esempio, Python ha introdotto le stringhe Unicode con la versione 2.0, anno 2000. La scelta dell'immutabilità era anche una scelta controversa in quel momento.
Joonas Pulakka,

3
@JoonasPulakka Allora forse dovresti modificare la tua risposta per dirlo. Perché così com'è, la parte del "lusso totale" della tua risposta è piuttosto sbagliata.
svick

1
L'internet ha un costo: ottieni una stringa che non verrà mai deallocata. (Beh, a meno che tu non usi il tuo motore di interning che puoi buttare via.)
Donal Fellows

32

James Gosling , il creatore di Java, lo spiegò così nel luglio 2000 :

Ho lasciato il sovraccarico dell'operatore come una scelta abbastanza personale perché avevo visto troppe persone abusarne in C ++. Ho passato molto tempo negli ultimi 5-6 anni a sondare le persone sul sovraccarico dell'operatore ed è davvero affascinante, perché fai dividere la comunità in tre parti: probabilmente circa il 20-30% della popolazione pensa al sovraccarico dell'operatore come al spawn del diavolo; qualcuno ha fatto qualcosa con il sovraccarico dell'operatore che li ha appena spuntati, perché hanno usato come + per l'inserimento della lista e rende la vita davvero, molto confusa. Gran parte di questo problema deriva dal fatto che ci sono solo circa una mezza dozzina di operatori che puoi sovraccaricare sensibilmente, eppure ci sono migliaia o milioni di operatori che le persone vorrebbero definire - quindi devi scegliere,


50
Ah, sì, il vecchio "lasciamo smussare lo strumento appuntito in modo che i gufi non si facciano del male" scusa.
Blrfl

22
@Blrfl: se uno strumento crea più problemi di quanti ne risolva, non è un buon strumento. Naturalmente, decidere se questo è il caso del sovraccarico dell'operatore potrebbe trasformarsi in una discussione molto lunga.
Giorgio,

15
-1. Questo non risponde affatto alla domanda. Java ha avere l'overloading degli operatori. L' ==operatore è sovraccarico di oggetti e primitivi. L' +operatore è sovraccarico per byte, short, int, long, float, double, Stringe probabilmente un paio di altri ho dimenticato. Sarebbe stato perfettamente possibile sovraccaricare anche ==per String.
Jörg W Mittag,

10
@Jorg - no non lo fa. Il sovraccarico dell'operatore è impossibile da definire a livello di utente. Ci sono davvero alcuni casi speciali nel compilatore ma che difficilmente si qualifica
AZ01

9
@Blrfl: Non mi dispiace che i gufi si facciano male. È quando accidentalmente mi fanno uscire gli occhi che mi irrita.
Jonas,

9

Coerenza nella lingua. Avere un operatore che agisce diversamente può essere sorprendente per il programmatore. Java non consente agli utenti di sovraccaricare gli operatori, pertanto l'uguaglianza di riferimento è l'unico significato ragionevole ==tra gli oggetti.

All'interno di Java:

  • Tra tipi numerici, ==confronta l'uguaglianza numerica
  • Tra tipi booleani, ==confronta l'uguaglianza booleana
  • Tra oggetti, ==confronta l'identità di riferimento
    • Utilizzare .equals(Object o)per confrontare i valori

Questo è tutto. Regola semplice e semplice per identificare ciò che vuoi. Tutto ciò è coperto nella sezione 15.21 del JLS . Comprende tre sottosezioni che sono facili da capire, implementare e ragionare.

Una volta che si consente il sovraccarico di== , il comportamento esatto non è qualcosa che si può guardare al JLS e mettere il dito su un elemento specifico e dire "è così che funziona", il codice può diventare difficile da ragionare. L'esatto comportamento di ==può essere sorprendente per un utente. Ogni volta che lo vedi, devi tornare indietro e controllare per vedere cosa significa effettivamente.

Poiché Java non consente il sovraccarico degli operatori, è necessario un modo per avere un test di uguaglianza di valore di cui è possibile ignorare la definizione di base. Pertanto, è stato richiesto da queste scelte progettuali. ==in Java test numerici per tipi numerici, uguaglianza booleana per tipi booleani e uguaglianza di riferimento per tutto il resto (che può sovrascrivere .equals(Object o)per fare ciò che vogliono per l'uguaglianza di valore).

Non si tratta di "esiste un caso d'uso per una particolare conseguenza di questa decisione progettuale", ma piuttosto "questa è una decisione progettuale per facilitare queste altre cose, ne è una conseguenza".

Lo string interning , ne è un esempio. Secondo JLS 3.10.5 , tutti i valori letterali di stringa sono internati. Altre stringhe vengono internate se si invoca .intern()su di esse. Questo "foo" == "foo"è vero è una conseguenza delle decisioni di progettazione prese per minimizzare il footprint di memoria assunto dai letterali String. Oltre a ciò, lo string interning è qualcosa a livello di JVM che ha un po 'di esposizione per l'utente, ma nella stragrande maggioranza dei casi, non dovrebbe essere qualcosa che riguarda il programmatore (e i casi d'uso per i programmatori non lo erano qualcosa che era in cima alla lista per i progettisti quando si considera questa funzione).

La gente lo farà notare +e +=sono sovraccarichi di String. Tuttavia, questo non è né qui né lì. Resta il caso che se ==ha un significato di uguaglianza di valore per String (e solo String), si avrebbe bisogno di un metodo diverso (che esiste solo in String) per l'uguaglianza di riferimento. Inoltre, ciò complicherebbe inutilmente i metodi che prendono Object e si aspettano ==di comportarsi in un modo e .equals()di comportarsi in un altro, richiedendo agli utenti casi speciali tutti quei metodi per String.

Il contratto coerente per gli ==oggetti è che si tratta solo di uguaglianza di riferimento e che .equals(Object o)esiste per tutti gli oggetti che dovrebbero verificare l'uguaglianza di valore. Complicare ciò complica troppe cose.


grazie per il tempo dedicato a rispondere. Questa sarebbe un'ottima risposta alle altre domande a cui ho collegato. Sfortunatamente, questo non è adatto a questa domanda. Aggiornerò il PO con chiarimenti basati sui commenti. Sto cercando di più per i casi d'uso in cui un utente della lingua vorrebbe avere i falsi negativi quando confronta le stringhe. Il linguaggio fornisce questa funzionalità come coerenza, ora vorrei che facessimo un ulteriore passo avanti. Forse è necessario pensarlo dal designer di nuova lingua? (purtroppo no lang-design.SE)
Anonsage

3
@Anonsage non è un falso negativo. Non sono lo stesso oggetto. Questo è tutto ciò che sta dicendo. Devo anche sottolineare che in Java 8, new String("foo") == new String("foo")potrebbe essere vero (vedi Deduplicazione di stringhe ).

1
Per quanto riguarda la progettazione del linguaggio, CS.SE pubblicizza che potrebbe essere in tema lì.

ooh, grazie! Invierò qui le mie future domande sul lang design. :) E, sì, sfortunatamente "falso negativo" non è il modo più preciso per descrivere la mia domanda e ciò che sto cercando .. Ho bisogno di scrivere più parole in modo che le persone non debbano indovinare ciò che sono cercando di dire.
Anonsage,

2
"La coerenza nella lingua" aiuta anche con i generici
Brendan,

2

Java non supporta il sovraccarico dell'operatore, il che significa ==che si applica solo a tipi o riferimenti primitivi. Qualsiasi altra cosa richiede l'invocazione di un metodo. Perché i designer hanno fatto questa è una domanda a cui solo loro possono rispondere. Se dovessi indovinarlo, è probabilmente perché il sovraccarico dell'operatore porta complessità che non erano interessati ad aggiungere.

Non sono un esperto di C #, ma i progettisti di quel linguaggio sembrano averlo impostato in modo tale che ogni primitiva è un structe ogni structoggetto è un oggetto. Poiché C # consente il sovraccarico dell'operatore, tale disposizione rende molto semplice per qualsiasi classe, non solo String, far funzionare se stesso nel modo "previsto" con qualsiasi operatore. C ++ consente la stessa cosa.


1
"Java non supporta il sovraccarico dell'operatore, il che significa che == si applica solo a tipi o riferimenti primitivi. Qualsiasi altra cosa richiede l'invocazione di un metodo" ==.
Giorgio,

@Giorgio: Esatto. Vedi il mio commento sulla risposta di Gilad Naaman.
Blrfl

Sebbene ciò possa essere risolto con un metodo statico che confronta i riferimenti di due oggetti (o un operatore). Come in C #, per esempio.
Gilad Naaman,

@GiladNaaman: Sarebbe un gioco a somma zero perché causerebbe il problema opposto a quello che Java ha ora: l'uguaglianza sarebbe su un operatore e dovresti invocare un metodo per confrontare i riferimenti. Inoltre, dovresti imporre il requisito per cui tutte le classi implementano qualcosa a cui è possibile vincolare ==. Questo sta effettivamente aggiungendo il sovraccarico dell'operatore, il che avrebbe enormi implicazioni sul modo in cui Java viene implementato.
Blrfl

1
@Blrfl: Non proprio. Ci sarà sempre un modo definito per confrontare reference ( ClassName.ReferenceEquals(a,b)) e un ==operatore e un Equalsmetodo predefiniti che puntano entrambi a ReferenceEquals.
Gilad Naaman,

2

Questo è stato reso diverso in altre lingue.

In Object Pascal (Delphi / Free Pascal) e C #, l'operatore di uguaglianza è definito per confrontare valori, non riferimenti, quando si opera su stringhe.

Soprattutto in Pascal, la stringa è un tipo primitivo (una delle cose che amo davvero di Pascal, ottenere NullreferenceException solo a causa di una stringa non inizializzata è semplicemente irritante) e avere una semantica copy-on-write che rende (per lo più) operazioni di stringa molto economico (in altre parole, evidente solo quando si inizia a concatenare stringhe multi-megabyte).

Quindi, è una decisione di progettazione del linguaggio per Java. Quando hanno progettato il linguaggio hanno seguito il modo C ++ (come Std :: String), quindi le stringhe sono oggetti, che è un hack di IMHO per compensare la mancanza di un tipo di stringa reale in C, invece di rendere le stringhe una primitiva (che sono).

Quindi, per un motivo, posso solo ipotizzare che abbiano reso tutto ciò facile da parte loro e non codificare l'operatore fa un'eccezione sul compilatore alle stringhe.


come risponde alla domanda posta?
moscerino

Vedi l'ultima frase (che ho separato in un paragrafo appropriato in una modifica).
Fabricio Araujo,

1
IMHO, Stringavrebbe dovuto essere un tipo primitivo in Java. A differenza di altri tipi, il compilatore deve conoscere String; inoltre, le operazioni su di esso saranno sufficientemente comuni che per molti tipi di applicazione potrebbero porre un collo di bottiglia nelle prestazioni (che potrebbe essere facilitato dal supporto nativo). Un tipico string[minuscolo] avrebbe un oggetto allocato sull'heap per contenere il suo contenuto, ma nessun riferimento "normale" a quell'oggetto esisterebbe ovunque; potrebbe quindi essere un singolo indiretto Char[]o Byte[]piuttosto che dover essere Char[]indiretto attraverso un altro oggetto.
supercat,

1

In Java, non c'è alcun operatore che sovraccarica di alcun tipo, ed è per questo che gli operatori di confronto sono sovraccaricati solo per i tipi primitivi.

La classe 'String' non è una primitiva, quindi non ha un sovraccarico per '==' e utilizza il valore predefinito per confrontare l'indirizzo dell'oggetto nella memoria del computer.

Non sono sicuro, ma penso che in Java 7 o 8 Oracle abbia fatto un'eccezione nel compilatore per riconoscerlo str1 == str2comestr1.equals(str2)


"Non sono sicuro, ma penso che in Java 7 o 8 Oracle abbia fatto un'eccezione nel compilatore per riconoscere str1 == str2 come str1.equals (str2)": Non sarei sorpreso: Oracle sembra essere meno preoccupato con minimalismo di quanto non fosse Sun.
Giorgio,

2
Se è vero, è un brutto hack poiché significa che ora c'è una classe che il linguaggio tratta in modo diverso da tutti gli altri e rompe il codice che confronta i riferimenti. : - @
Blrfl

1
@WillihamTotland: considera il caso opposto. Attualmente, se creo due stringhe, s1e s2e dare loro gli stessi contenuti, passano l'uguaglianza ( s1.equals(s2)confronto), ma non lo stesso riferimento ( ==) confronto perché sono due oggetti diversi. Cambiare la semantica ==per significare l'uguaglianza significherebbe s1 == s2valutare truedove era solito valutare false.
Blrfl

2
@Brlfl: Anche se è vero, suona come una cosa eccezionalmente brutta su cui fare affidamento in primo luogo, poiché le stringhe sono oggetti immutabili e internabili.
Williham Totland,

2
@Giorgio: "Java 7 o 8 oracle ha fatto un'eccezione nel compilatore per riconoscere str1 == str2 come str1.equals (str2)" No, la specifica del linguaggio Java dice: Operatori di uguaglianza di riferimento : "Se gli operandi di un operatore di uguaglianza sono sia del tipo di riferimento che del tipo null, quindi l'operazione è l'uguaglianza degli oggetti. " È tutto gente. Non ho trovato nulla di nuovo su questo nella prima bozza di Java 8 .
David Tonhofer,

0

Java sembra essere stato progettato per rispettare una regola fondamentale secondo cui l' ==operatore dovrebbe essere legale ogni volta che un operando può essere convertito nel tipo di altro e dovrebbe confrontare il risultato di tale conversione con l'operando non convertito.

Questa regola non è univoca per Java, ma ha alcuni effetti di vasta portata (e sfortunati per IMHO) sulla progettazione di altri aspetti del linguaggio relativi al tipo. Sarebbe stato più pulito specificare i comportamenti ==riguardo a particolari combinazioni di tipi di operandi, e vietare combinazioni di tipi X e Y dove x1==y1e x2==y1non avrebbe implicato x1==x2, ma le lingue raramente lo fanno [secondo quella filosofia, double1 == long1o dovrebbero indicare se double1non è una rappresentazione esatta di long1, oppure rifiuta di compilare;int1==Integer1dovrebbe essere vietato, ma dovrebbe esserci un modo conveniente ed efficiente di non lancio per verificare se un oggetto è un intero boxed con un valore particolare (il confronto con qualcosa che non è un intero box dovrebbe semplicemente restituire false)].

Per quanto riguarda l'applicazione ==dell'operatore alle stringhe, se Java avesse vietato i confronti diretti tra operandi di tipo Stringe Object, avrebbe potuto piuttosto evitare le sorprese nel comportamento di ==, ma non c'è alcun comportamento che potrebbe implementare per tali confronti che non sarebbe sorprendente. Avere due riferimenti a stringa mantenuti nel tipo si Objectcomporta diversamente dai riferimenti mantenuti nel tipo Stringsarebbe stato molto meno sorprendente che avere uno di questi comportamenti differisca da quello di un confronto legale di tipo misto. Se String1==Object1è legale, ciò implicherebbe che l'unico modo per i comportamenti String1==String2e la Object1==Object2corrispondenza String1==Object1sarebbe che si abbinassero l'un l'altro.


Devo mancare qualcosa, ma IMHO ==sugli oggetti dovrebbe semplicemente chiamare (null-safe) uguale e qualcos'altro (ad esempio, ===o System.identityEqual) dovrebbe essere usato per il confronto delle identità. La miscelazione di primitivi e oggetti sarebbe inizialmente vietata (non esisteva il box automatico prima dell'1.5) e quindi si potevano trovare alcune semplici regole (ad es. Unbox null-safe, quindi cast, quindi confronto).
maaartinus,

@maaartinus: un buon design del linguaggio dovrebbe usare operatori di uguaglianza separati per l'uguaglianza di valore e di riferimento. Anche se concordo sul fatto che concettualmente sarebbe stato possibile int==Integerrestituire un operatore falsese Integerè nullo, e altrimenti confrontare i valori, tale approccio sarebbe stato diverso dal comportamento di ==in tutte le altre circostanze, dove costringe incondizionatamente entrambi gli operandi allo stesso tipo prima confrontandoli. Personalmente mi chiedo se l'auto-unboxing sia stato messo in atto nel tentativo di consentire int==Integerdi avere un comportamento non assurdo ...
supercat

... dal momento che l'autoboxing di inte fare un confronto di riferimento sarebbe stato sciocco [ma non avrebbe sempre fallito]. Altrimenti, non vedo alcun motivo per consentire una conversione implicita che può fallire con un NPE.
supercat

Penso che la mia idea sia coerente. Tieni presente che nel mondo migliore ==non ha nulla a che fare identityEquals. +++ "operatori di uguaglianza separati per valore e uguaglianza di riferimento" - ma quali? Considererei sia il primitivo ==che equalsil confronto del valore nel senso che equalsosserva il valore del riferimento. +++ Quando si ==intende equals, quindi int==IntegerDOVREBBE fare il boxing automatico e confrontare i riferimenti usando uguale a null-safe. +++ Temo che la mia idea non sia davvero mia, ma proprio quello che fa Kotlin.
maaartinus,

@maaartinus: se ==mai testato l'uguaglianza di riferimento, allora potrebbe eseguire sensibilmente un test di uguaglianza di valore nullo e sicuro. Il fatto che essa fa uguaglianza riferimento prova, tuttavia, limita fortemente come può gestire confronto riferimento / valore misti senza incoerenza. Si noti inoltre che Java è fissato sull'idea che gli operatori promuovono entrambi gli operandi sullo stesso tipo, anziché produrre comportamenti speciali basati sulle combinazioni dei tipi coinvolti. Ad esempio, 16777217==16777216.0fritorna trueperché esegue una conversione con perdita del primo operando in float, mentre un ...
supercat

0

In generale, ci sono ottime ragioni per voler poter verificare se due riferimenti a oggetti puntano allo stesso oggetto. Ho avuto molte volte che ho scritto

Address oldAddress;
Address newAddress;
... populate values ...
if (oldAddress==newAddress)
... etc ...

In tali casi, potrei o meno avere una funzione uguale. Se lo faccio, la funzione uguale può confrontare l'intero contenuto di entrambi gli oggetti. Spesso confronta solo un identificatore. "A e B sono riferimenti allo stesso oggetto" e "A e B sono due oggetti diversi con lo stesso contenuto" sono, ovviamente, due idee molto diverse.

È probabilmente vero che per gli oggetti immutabili, come le stringhe, questo è meno un problema. Con oggetti immutabili, tendiamo a pensare all'oggetto e al valore come la stessa cosa. Bene, quando dico "noi", intendo almeno "io".

Integer three=new Integer(3);
Integer triangle=new Integer(3);
if (three==triangle) ...

Naturalmente questo restituisce falso, ma posso vedere qualcuno pensare che dovrebbe essere vero.

Ma una volta che dici che == confronta gli handle di riferimento e non i contenuti per gli oggetti in generale, creare un caso speciale per le stringhe sarebbe potenzialmente fonte di confusione. Come ha detto qualcun altro qui, e se volessi confrontare le maniglie di due oggetti String? Ci sarebbe qualche funzione speciale per farlo solo per le stringhe?

E che mi dici di ...

Object x=new String("foo");
Object y=new String("foo");
if (x==y) ...

È falso perché sono due oggetti diversi o vero perché sono stringhe il cui contenuto è uguale?

Quindi sì, capisco come i programmatori si confondano con questo. L'ho fatto da solo, intendo scrivere se myString == "pippo" quando volevo dire se mioString.equals ("pippo"). Ma a parte riprogettare il significato dell'operatore == per tutti gli oggetti, non vedo come affrontarlo.


Si noti che altri linguaggi moderni sulla JVM, come Scala, usano ==per indicare "stringhe uguali".
Andres F.

@AndresF. (scrollata di spalle) In Java, "<" significa "meno di", mentre in XML "apre un tag". In VB "=" può significare "è uguale a", mentre in Java viene utilizzato solo per l'assegnazione. Ecc. Non sorprende che lingue diverse utilizzino simboli diversi per indicare la stessa cosa o lo stesso simbolo per indicare cose diverse.
Jay,

Non è stato uno scavo alla tua risposta. Era solo un commento. Stavo solo sottolineando che un linguaggio più moderno di Java ha colto l'occasione per ridisegnare il significato ==, proprio come hai detto alla fine.
Andres F.

@AndresF. E la mia risposta non è stata uno scavo al tuo commento, dicendo solo che lingue diverse affrontano questi problemi in modi diversi. :-) In realtà mi piace il modo in cui VB gestisce questo ... pausa per i sibili e i fischi degli odiatori di VB ... "=" confronta sempre il valore (per i tipi definiti dal sistema), sia esso primitivo o oggetto. "Is" confronta le maniglie di due oggetti. Mi sembra più intuitivo.
Jay

Sicuro. Ma Scala è molto più vicino a Java di Visual Basic. Mi piace pensare che i designer di Scala abbiano capito che l'uso di Java ==era soggetto a errori.
Andres F.

0

Questa è una domanda valida per Strings, e non solo per le stringhe, ma anche per altri oggetti immutabili che rappresentano alcuni "valore", per esempio Double, BigIntegere persino InetAddress.

Per rendere l' ==operatore utilizzabile con stringhe e altre classi di valori, vedo tre alternative:

  • Chiedi al compilatore di conoscere tutte queste classi di valore e il modo di confrontare i loro contenuti. Se fosse solo una manciata di classi dal java.langpacchetto, lo prenderei in considerazione, ma questo non copre casi come InetAddress.

  • Consenti il ​​sovraccarico dell'operatore in modo che una classe definisca il suo ==comportamento di confronto.

  • Rimuovere i costruttori pubblici e disporre di metodi statici che restituiscono istanze da un pool, restituendo sempre la stessa istanza per lo stesso valore. Per evitare perdite di memoria, è necessario qualcosa come SoftReferences nel pool, che non esisteva in Java 1.0. E ora, per mantenere la compatibilità, i String()costruttori non possono più essere rimossi.

L'unica cosa che si potrebbe ancora fare oggi sarebbe introdurre il sovraccarico dell'operatore, e personalmente non mi piacerebbe che Java seguisse quella strada.

Per me, la leggibilità del codice è molto importante e un programmatore Java sa che gli operatori hanno un significato fisso, definito nella specifica del linguaggio, mentre i metodi sono definiti da un codice e il loro significato deve essere cercato nel Javadoc del metodo. Vorrei rimanere con questa distinzione anche se ciò significa che i confronti String non saranno in grado di utilizzare l' ==operatore.

C'è solo un aspetto dei paragoni di Java che mi dà fastidio: l'effetto dell'auto-boxing e -unboxing. Nasconde la distinzione tra il tipo primitivo e il tipo di wrapper. Ma quando li confronti ==, sono MOLTO diversi.

    int i=123456;
    Integer j=123456;
    Integer k=123456;
    System.out.println(i==j);  // true or false? Do you know without reading the specs?
    System.out.println(j==k);  // true or false? Do you know without reading the specs?
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.