Bölüm 3 - Java da Programlama Yapılarının Temelleri 4
Stringler
Java'da stringler kısaca; Unicode karakterlerinin birleşimidir.
String e = ""; // Boş bir string
String greeting = "Hello";
Substringler
Biz uzun olarak yazdığımız bir String'den alt string oluşturabiliriz bu sürece substring denir. Bunu da bir method ile yaparız.
String greeting = "Hello";
String s = greeting.substring(0,3); // Hel
Burda 0.index'ten başla 3.index'e kadar al ama 3.index dahil değildir diyoruz.
Concatenation
2 tane String'i birleştirmek için '+' operatörünü kullanırız.
String expletive = "Expletive";
String PG13 = "deleted";
String message =expletive+PG13;
Burda biz birleştirdiğimizde sonuç "Expletivedeleted" yazar.
Eğer ki biz String'i başka bir değer ile birleştirdiğimizde onu otomatik olarak String'e dönüştürür.
int age = 13;
String rating = "PG"+age; // PG13 olur.
Bu süreci daha çok output ifadelerinde kullanıyoruz.
System.out.println("The answer is "+answer);
Eğer ki birden fazla String'i bir delimeter vererek birleştirmek istersek String.join methodunu kullanabiliriz.
String all = String.join(" / ", "S","M","L","XL");
System.out.println(all); // S / M / L / XL
Java 11 ile gelen repeat methoduyla bir String'i istediğimiz kadar yazdırabiliriz.
String repeated = "Java".repeat(3); // JavaJavaJava
Strings are Immutable (Stringler Değişmezler,Sabitler)
Java'da ki String classı bize direkt olarak bir karakteri String içerisinde değiştirmeyi vermez mesela greeting'de ki Help! yapmak istersek eğer biz direkt olarak p yada ! etkileşeme geçemeyiz. Bunu ancak substring ile deneyebiliriz.
String greeting = "Hello";
greeting = greeting.substring(0,3)+"p!";
Bu tanımlama artık değeri greeting'in -> Help! yapar. Yani biz direkt olarak Hello'ya erişip onu değiştiremiyoruz. İşte biz bireysel olarak bir karakteri Java Stringde değiştiremediğimiz için Java dökümantasyonu buna immutable diyor.
Biraz daha derine inecek olursak;
Her defasında biz bir String oluşturduğumuzda, JVM "String Constant Pool(SCP)"'yi kontrol eder böyle bir String var ise bunun referansını döndürür yoksa bunu oluşturur.
String s1 = "Welcome";
String s2 = "Welcome";

Eğer ki biz Şöyle bir şey yaparsak;
String name = new String("a");
String name2 = "a";
Budra artık name ile name2 aynı yere işaret etmez çünkü name artık SCP içerisinde oluşturulmadı name için yeni bir nesne heapte oluşturulur ve SCP ile artık bir bağlantı yoktur.
Testing Strings for Equality (Stringlerin Eşitliğini Kontrol Etme)
Eğer ki 2 tane String değeri eşit mi değil mi kontrol etmek istersek; equals methodunu kullanmamız gerekir.
s.equals(t);
eğer ki s ile t eşit ise true değilse false döner.
Yada şunu da yapabiliriz.
"Hello".equals(greeting);
Eğer ki büyük yada küçük harfe bakmaksızın, incase-sensitive şekilde eşitlikleri kontrol etmek istersek "equalsIgnoreCase" methodunu kullanabiliriz.
"Hello".equalsIgnoreCase("hello");
İki stringi karşılaştırıp eşit mi değiller mi diye bunu da compareTo methodu ile yapabiliriz.
if (greeting.compareTo("Hello) == 0){}
!!!!
String s1 = "Java"; // Havuza "Java" eklenir, s1 oraya işaret eder.
String s2 = "Java"; // Havuzda zaten var, s2 de aynı adrese işaret eder.
String s3 = new String("Java"); // "new" dediğin an Havuz pas geçilir, Heap'te YENİ bir alan açılır.
String s4 = "Ja" + "va"; // Derleyici bunu "Java" olarak optimize eder, havuza gider.
String part = "Ja";
String s5 = part + "va"; // Çalışma zamanında (runtime) hesaplandığı için YENİ bir obje oluşur.
// Testler
System.out.println(s1 == s2); // TRUE (İkisi de havuzdaki aynı adreste)
System.out.println(s1 == s3); // FALSE (Biri havuzda, biri heap'te başka yerde)
System.out.println(s1 == s5); // FALSE (Runtime'da oluşan string farklı adrestedir)
System.out.println(s1.equals(s3)); // TRUE (Adresler farklı ama içerik "Java")
!!!!
Empty (Boş) ve Null Strings
Empty String "" budur ve uzunluğu 0'dır. Bir String empty mi değil mi kontrol etmek için:
if (str.length() == 0){} // yada
if (str.equals("")){} // ile kontrol edebiliriz
Ayrıca Stringler özel değer olan null ifadesini de tutabilirler bu şunu söyler herhangi bir nesne bu değişken ile ilişkide değildir. Eğer ki bir String null mu değil mi kontrol etmek istersek:
if (str == null){}
ile kontrol edebiliriz.
Peki ya bir String hem null değil hem de empty değil kontrol etmek istersek
if (str != null && str.length() != 0){}
String API
java.lang.String
| Method | Açıklaması |
|---|---|
| char charAt(int index) | Verilen indexteki karakteri döner. |
| int codePointAt(int index) | Verilen indexteki code pointi döner. |
| int offsetByCodePoints(int startIndex, int cpCount) | startIndex'teki code pointten cpCount code point uzaklıktaki kod noktasının dizinini döndürür. |
| int compareTo(String other) | Sözlükte eğer ki other önce String olarak geliyorsa negative, sonra geliyorsa positive eşit ise 0 döner. |
| IntStream codePoints() | Verilen String'de ki code pointleri stream olarak döner. Ve ayrıca bunları çağırmak için toArray() methodunu da hemen ardında çağırmalıyız. |
| boolean isEmpty() | String boş mu değil mi kontrol eder. |
| boolean equals(Object other) | String eğer ki other'a eşit ise true döner. |
| boolean equalsIgnoreCase(String other) | String eğer ki other'a eşit ise true döner (küçük/büyük harf incase-sensitive şeklinde davranır). |
| boolean startsWith(String prefix) | String prefix ile başlıyor ise true döner. |
| boolean endsWith(String suffix) | String suffix ile bitiyor ise true döner. |
| int indexOf(String str) | |
| int indexOf(String str, int fromIndex) | |
| int indexOf(int cp) | |
| int indexOf(int cp, int fromIndex) | str dizesine veya cp kod noktasına eşit olan ilk alt dizenin başlangıcını döndürür; bu başlangıç noktası 0 dizininden veya fromIndex dizininden başlar veya str veya cp bu dizide yoksa -1 olur. |
| int lastIndexOf(String str) | |
| int lastIndexOf(String str, int fromIndex) | |
| int lastIndexOf(int cp) | |
| int lastIndexOf(int cp, int fromIndex) | str dizesine veya cp kod noktasına eşit olan son alt dizenin başlangıcını, dizenin sonundan veya fromIndex'ten başlayarak veya str veya cp yoksa -1 değerini döndürür. |
| int length() | String'in uzunluğunu dönderir. |
| int codePointCount(int startIndex, int endIndex) | Verilen startIndex ve endIndex arasındaki code pointlerin sayısını dönderir. |
| String replace(CharSequence oldString, CharSequence newString) | Verilen oldString değerini newString ile değiştirir. |
| String substring(int beginIndex) | Verilen index değerinden length()-1'e kadar String'i alır |
| String substring(int beginIndex, int endIndex) | Verilen index değerinden biten index değerine kadar substringi döner. |
| String toLowerCase() | String karakterlerini küçük harfe dönüştürür. |
| String toUpperCase() | String karakterlerini büyük harfe dönüştürür. |
| String strip() | String'in başındaki ve sonundaki whitespaceleri siler. trim() methodu yerine bunu kullan çünkü trim() method sadece characters <= U+0020'ye kadar olanları siler. |
| String stripLeading() | String'in başındaki whitespaceleri siler. |
| String stripTrailing() | String'in sonundaki whitespaceleri siler. |
| String join(CharSequence delimiter, CharSequence... elements) | Verilen delimeter'e uygun bir şekilde art arda verdiğimiz String'leri birleştirerek verir. |
| String repeat(int count) | Verilen String'i count kadar tekrar ederek yazar. |
API'leri okumak için;
https://docs.oracle.com/en/java/javase/11/docs/api/
Building Strings (Stringleri İnşa Etme)
Daha kısa String'leri bir daha Stringlerle birleştirmek istersek her defasında String immutable olduğu için her defasında String constructed olacak bu yüzden Java buna çözüm olarak StringBuilder classını getirmiştir.
StringBuilder builder = new StringBuilder();
Eğer ki herhangi bir part'ı eklemek istersek:
builder.append(ch); // bir character eklemek istersek
builder.append(str); // String eklemek istersek
Ve String inşaamız bittikten sonra artık String object'imizi almak istersek:
String completedString = builder.toString();
StringBuilder'a istinaden StringBuffer classı da var ama bu biraz daha etkisizdir.
StringBuilder API
java.lang.StringBuilder
| Method | Açıklaması |
|---|---|
| StringBuilder() | Boş bir String Builder nesnesi oluturur. |
| int length() | Builder yada Buffer nesnesinin uzunluğunu dönderir. |
| StringBuilder append(String str) | String'i builder'a ekleyip bunu (this) geri döner. |
| StringBuilder append(char c) | Code unit ekleyip bunu (this) geri döner. |
| StringBuilder appendCodePoint(int cp) | Bir code point ekler ve bir yada daha fazla code units'e dönüştürü ve bunu (this) geri döner. |
| void setCharAt(int i, char c) | i.code unit'i c'ye ayarlar |
| StringBuilder insert(int offset, String str) | offset.indexe String'i ekler ve bunu (this) geri döner. |
| StringBuilder insert(int offset, char c) | offset.indexe bir code unit'i ekler ve bunu (this) geri döner. |
| StringBuilder delete(int startIndex, int endIndex) | startIndex'ten endIndex'e kadar olan code unitleri siler ve bunu (this) geri döner. |
| String toString() | Builder yada Buffer'ın String objectini geri döner |
Text Blocks
Java 15 ile gelmiştir birden fazla satırda String tanımlamak için kullanılır. Bir text bloğu
""" (ile başlar)
""" (ile biter)
String greeting = """
Hello
World
""";
Yukarıdaki String'in karşılığı aşağıdaki gibidir:
"Hello\nWorld\n"
Eğer ki SQL yada HTML gibi kod parçacıklarına sahip dilleri eklemek istersek:
String html = """
<div class="warning">
Beware of those who say "Hello" to the world
</div>
""";
Görüldüğü üzere bizim tırnak işaretlerinden kaçmamıza gerek yok. Sadece 2 durumda tırnak işaretlerini eklerken escape etmemiz gerek:
- Eğer ki text block tırnak işareti ile bitiyorsa.
- Eğer ki text block kendi içerisinde 3 yada daha fazla art arda gelen tırnak işareti içeriyorsa kaçınmamız gerekir.
Backslash'ları eklerken ise hepsinden kaçınmamız gereklidir.
Eğer ki biz text blockta yeni bir satır oluşturmasını istemezsek:
"""
Hello, my name is Hal. \
Please enter your name: """
Burda eklenen \ (backslash) yeni satır eklenmesini engeller.
Hello, my name is Hal. Please enter your name: