Java String'in neden statik dize düzenleme yöntemleri yok?


17

Java tasarımcıları neden java.lang.Stringsınıfta dize düzenleme yöntemlerinin statik sürümlerini oluşturmadı ? Aşağıdaki yöntemler, bahsettiğim şeydir, ancak soru sınıftaki diğer statik olmayan yöntemlere de genişletilebilir.

concat(String)                        substring(int, int)
replace(char, char)                   toLowerCase()
replace(CharSequence, CharSequence)   toLowerCase(Locale)
replaceAll(String, String)            toString()
replaceFirst(String, String)          toUpperCase()
split(String)                         toUpperCase(Locale)
split(String, int)                    trim()
substring(int)

Bu yöntemlerin yalnızca statik olmayan sürümlerine sahip olmak, böyle bir yöntemin çağrılması gereken her yerde açık sıfır denetimini zorlar . Örneğin, sadece çağırmak eğer NullPointerExceptionexample = example.trim() yol açar . Bu yüzden programcı aşağıdaki boyler plakası null kontrolünü yapmak zorundadır:String example = null

if (example != null)
    example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);

İlk argüman olarak giriş dizesini alacaktı Stringbu yöntemlerin (belki de sadece ) statik sürümleri olsaydı çok daha uygun olurdu düşünürdüm:

example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);

Bu, programcılar tarafından yazılan ve programcıları açıkça boş durumlarla başa çıkmaya zorlamak yerine, yalnızca boş durumlarla otomatik olarak boş durumlarla ilgilenecek olan temiz kodlara yol açacaktır. Null dönen bir manipüle beri bana mantıklı boş bir yol açmalıdır dize boş dize değil, bir hata.

Java tasarımcıları Stringsınıfı Java 1 veya Java 2'de tasarladıklarında neden böyle düşünmediler, hatta daha sonraki bir Java sürümüne böyle bir işlevsellik eklediler?


17
"Java tasarımcıları neden X'i düşünmedi" ile "Java tasarımcıları neden X'e karşı karar verdiler" ifadesini değiştirmenizi öneririm. Onlara seçeneği kör olmama konusunda temel kredi verin.
Avner Shahar-Kashtan

5
nullistisnai bir durumdur ve açıkça ele alınmalıdır.
CodesInChaos

2
@KonradMorawski: Şahsen ben uzatma yöntemlerinin büyük bir kötüye kullanımı olduğunu düşünüyorum. Eğer bir null değeriniz varsa, o zaman dünyadaki yöntemleri çağırmaya çalışıyorsunuz, sadece bu kodu okuyan herkesi karıştıracaksınız. Sanırım kötü bir Maybe<T>tür yeniden uygulama.
Phoshi

1
@Phoshi biri vardır onlar sadece sözdizimi şeker konum, uzatma yöntemleri gerçek yöntemler DEĞİLDİR olduğunu akılda tutmak için. Ama tartışmalı olduğuna katılıyorum. Keşke C # / Java bir tür yerleşik sözdizimsel null güvenlik teklif, diyelim ki - Kotlin. string name = employee?.personalData?.name. Tüm bu tekrarlayanlar için bir kısayol gibi if (employee != null). İlgili SO sorusu: stackoverflow.com/questions/1196031/…
Konrad Morawski

2
@ ADTC Erm, bir programın bir değerin boş olduğunu önceden tahmin edemeyeceğini biliyorsunuz, değil mi? - Arabirimleriniz arasındaki sözleşmeleri , bir değerin boş olmasına izin verilip verilmeyeceğinden emin olabileceğiniz şekilde tanımlamanız gerekir . Her yerde boş kontrol, bir program tasarım sorununuz olduğu anlamına gelir.
Uooo

Yanıtlar:


30

Null değerinin döndürülmesi benim için anlamlıdır, çünkü null dizeyi değiştirmek bir hata değil null dizeyle sonuçlanmalıdır

Bu senin fikrin. Diğerleri, bir dize içermeyen boş bir nesnede String işlemlerinin bir anlam ifade etmediğini ve bu nedenle bir Exception oluşturması gerektiğini iddia edebilir

"Java tasarımcılarının" neden bir şey yapması ya da yapmaması neden zor.

Orada zaten null-güvenli String işlemleri yapabilen kütüphaneler var, örneğin Apache Commons StringUtils . İhtiyacınız varsa bu veya benzer kütüphaneleri kullanabilirsiniz.


Yorumlarınıza dayalı ekleme

Yorumları okurken, karşılaştığınız gerçek sorun nullkodunuzun her yerini kontrol etmeniz gerektiği gibi görünüyor . Bu, arayüzler arasında açıkça tanımlanmış sözleşmeler olmadan kötü bir program tasarımının bir göstergesi olabilir. Java'da “! = Null” deyimlerini kullanmaktan kaçınmak isteyebilirsiniz ?


1
Geri bildiriminiz için teşekkürler. Asıl soru şu ki, böyle bir temel özellik standart Java'nın bir parçası haline getirilebildiğinde neden harici bir kütüphaneye veya ev yapımı sınıflara güvenmemiz gerekiyor?
ADTC

4
@ADTC soruyu tam tersine söyleyelim: "Java tasarımcıları" niye bir şey eklemeli, eğer zaten iyi test edilmiş ve belgelenmiş çok sayıda iyi kütüphane varsa? Bir "temel özellik" nasıl tanımlanır görüş temelli. Çoğunlukla her projenin "Temel işlevsellik" için harici bir kütüphaneye ihtiyacı yoktur (birim testi, alay, tarih ve saat, ...)? Çok önemli değil, değil mi?
Uooo

Null'larla başa çıkmanın bir yolu Guava's kullanmaktır Optional- code.google.com/p/guava-libraries/wiki/…
Konrad Morawski

10

IMO yazma yöntemlerine tüm "arg null return null" yaklaşımı gereksiz yere programınızın siklomatik karmaşıklığını artırır.

İlk Java kütüphaneleri dönüş null yaklaşımını kullandılar, ancak JDK adamları istisnalar dışında her zaman null'a karşı korudular.

Zamanla, ikinci yaklaşımın açık kazanan olduğunu düşünüyorum.

Neden? Boş alanlar çok fazla oo ilkesini kırdığı için. Onları bir polimorfik sınıfın üyeleri olarak ele alamazsınız. Bu, her zaman null için özel durumları kodlamanız gerektiği anlamına gelir ve bu nedenle, her şeyin null olabileceğini varsaymanız gerektiğinde siklomatik karmaşıklığınız yükselir.

Sorunlarınızı çözmek için, boş alanlara güvenmek yerine boş nesne desenini kullanmayı düşünün.


2
Ama Stringpolimorfik değil, değil mi? Ve null nesne desenini String gibi zaten var olan bir tip için nasıl kullanırsınız?
svick

Dize polimorfik değildir, hayır. Yine de, sahip olduğunuz herhangi bir dize başvurusunda örnek yöntemlerini çağırabileceğinizi bilmek istersiniz. Bu null olmayan tüm başvurular için geçerlidir. Dize zaten boş bir nesneye sahip: boş dize. Tıpkı listelerin boş listeye sahip olması gibi. Öyleyse kendinize boş dizenin sizin durumunuzda neden yeterli olmadığını sorun. Bazı özel durum işaretlemek için bir boş dize kullanın sanırım. Bu özel durum için ayrı bir bayrak kullanıp kullanamayacağınızı kendinize sorun.
Alexander Torstling

@AlexanderTorstling: Yazılan bir alan intvarsayılan olarak sıfır yerine kullanılır null. Kavramsal olarak string, varsayılan değeri null[böyle bir tür anlamsal olarak Stringne intolacağına Integer] göre boş bir dize olacak bir türe sahip olmak mümkün olmalıdır . Boş olmayan stringbir öğenin dahili olarak bir yığın nesnesine başvuruda bulunması bir uygulama ayrıntısı olacaktır; anlamsal bir ilkel gibi davranmamasının bir nedeni yoktur.
supercat

@supercat: Kabul etti. Açıkça etkin olmadıkça referanslar için null değerleri yasaklamanın daha iyi olacağını düşünüyorum. Varsayılan null olmayan ve son alanlar. Birçok türde zaten boş davranış nesneleri var
Alexander Torstling

@AlexanderTorstling: Tüm türlerdeki depolama konumlarının varsayılan olarak all-byte-zero olarak ayarlanması ve yapı türlerinin all-byte-copy ile atanabilmesi koşuluyla bir çerçeveyi büyük ölçüde basitleştirir, ancak değiştirilebilir referans anlambilimine sahip türlerin varsayılan olarak boş. Ancak, tek bir başvuruyu içine alan ve bu başvuru türü olarak "kutu" oluşturabilecek ve kutuyu kaldırabilecek değer türleri için çerçeve desteğine sahip olmak yararlı olurdu .
supercat

3

Sebebini söylememek, ancak toString dışında, bu yöntemlerin tümü statik bir yardımcı sınıfta kolayca kapsüllenirken, tersi doğru değildir.

Yani Stings.toUpper (string input) için bunun kodunu yazmak istiyorsanız, ama example.toUpper ve tüm sahip olduğunuz String.toUpper istiyorsanız, bu mümkün değildir ... o zaman bile dikkate alınmamıştı.


İyi bir nokta, bir cevap daha bir yorum olmasına rağmen. Ancak bu bile göz önüne alındığında, böyle bir temel özellik standart Java'nın bir parçası haline getirilebildiğinde neden harici bir kütüphaneye veya ev yapımı sınıflara güvenmemiz gerekiyor?
ADTC

2
Şu andan itibaren String.format(statik) var ama yapamazsınız "something %s".format(id).
Konrad Morawski

@adtc: statik bir sınıf aracılığıyla bunu yapmak dilin temel bir özelliği değildir. Bu öncülden başlayarak, bunu yapmamak için birçok neden var - gereksiz kod / kod şişmesi, yinelenen işlevsellik, geliştirme / bakım maliyeti.
jmoreno

-2

Java'da bu dize bir nesnedir. Bu bir tasarım seçimi.

Nesne başvuruları boş olabilir ve kendisine atanmış bir nesne yoksa boştur. Böyle bir nesneyi çağırırsanız, bir NullPointerException oluşturulur. Bu standart oo-davranışıdır.

Java tasarımcıları, dizeleri nesne olarak seçmeyi seçti ve bu yöntemlerin boş gösterici istisnaları atmasını sağladıysanız, dizelerin nesne olmasını istiyorsanız elde edeceğiniz şey budur.

Java tasarımcıları, Java 1 veya Java 2'de String sınıfını tasarladıklarında ya da daha sonraki bir Java sürümüne böyle bir işlevsellik eklediklerinde neden bunu düşünmediler?

Muhtemelen bunu düşündüler ve oo-davranışını birleştirmeyi seçtiler.


OO davranışı değil , null vakalarla ilgilenmek için statik yöntemler nasıl oluşturabilirim ? Açıkça söylemek gerekirse, söylemiyorum, ama tasarım kararının neden OO davranışını birleştirmek olduğunu söylediğinizi anlamaya çalışıyorum.
ADTC

Statik yöntemler daha çok fonksiyonlara benzer. Ve istediğiniz kullanım için dize sınıfının bir parçası olmamalı, bazı yardımcı program sınıfının parçası olmamalıdır. Tıpkı matematik sınıfı işlevleri gibi.
Pieter B

4
Dizelerin nesne olması, String sınıfının statik yöntemlere sahip olamayacağı anlamına gelmez. Ve aslında zaten bir kısmı var, örneğin. String.format. (Bu arada C # ile aynı). Dolayısıyla, bu bir tasarım seçimi ise, yalnızca dizelerin nesne olduğu gerçeğinden gelemez ve tutarlı bir şekilde uygulanmaz.
Konrad Morawski

@PieterB En azından bu tür yöntemlerin bir Stringsyardımcı sınıfta sağlanmış olması durumunda şikayet etmem, yardımcı sınıfımız var gibi Arrays( her ne kadar ilkeller ve nesneler arasında garip bir çarpı diziler olduğu için sırf gereklilikten yaratıldığını anlıyorum: ) ) .. standart Java'nın bir parçası olduğu ve bağımlılık gerektirmediği sürece.
ADTC
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.