1. Porównanie referencji i zawartości
W Javie łańcuchy — to obiekty, a nie prymitywy. Gdy deklarujesz zmienne a i b, mogą one wskazywać na ten sam łańcuch w puli łańcuchów. Natomiast c, utworzone przez konstruktor, to już inny obiekt. Operator == porównuje właśnie referencje, a nie tekst.
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b); // true (najprawdopodobniej łańcuch z puli)
System.out.println(a == c); // false (różne obiekty)
Demonstracja błędu
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1 == s2); // false
Chociaż łańcuchy wyglądają tak samo, są to różne obiekty w pamięci.
2. equals(): porównywanie zawartości łańcuchów
Aby porównać właśnie zawartość, użyj metody equals() — porównuje ona łańcuchy znak po znaku (z uwzględnieniem wielkości liter).
String s1 = "Java";
String s2 = new String("Java");
System.out.println(s1.equals(s2)); // true
Przykład: porównywanie haseł
String inputPassword = "Secret123";
String realPassword = "Secret123";
if (inputPassword.equals(realPassword))
{
System.out.println("Dostęp przyznany!");
}
else
{
System.out.println("Hasło nieprawidłowe.");
}
Ważne!
Jeśli choć jeden obiekt jest równy null, wywołanie equals() spowoduje NullPointerException. Bezpieczny wzorzec:
if ("coś".equals(someString)) { ... }
3. equalsIgnoreCase(): porównywanie bez uwzględniania wielkości liter
Gdy ważne jest ignorowanie wielkości liter (np. dane wprowadzane przez użytkownika), używaj equalsIgnoreCase().
String name1 = "Ivan";
String name2 = "ivan";
System.out.println(name1.equalsIgnoreCase(name2)); // true
Przykład: porównywanie adresów e-mail
String email1 = "User@Example.com";
String email2 = "user@example.com";
if (email1.equalsIgnoreCase(email2))
{
System.out.println("Adresy e-mail się zgadzają!");
}
W skrócie: equals vs equalsIgnoreCase
| Metoda | Uwzględnia wielkość liter? | Przykład „Java” vs „java” |
|---|---|---|
|
Tak | |
|
Nie | |
4. compareTo(): leksykograficzne porównywanie łańcuchów
Metoda compareTo() wykonuje porównanie leksykograficzne (jak w słowniku). Zwraca liczbę ujemną, jeśli pierwszy łańcuch jest „mniejszy”, 0 — równe, liczbę dodatnią — jeśli „większy”.
System.out.println("apple".compareTo("banana")); // < 0
System.out.println("apple".compareTo("apple")); // 0
System.out.println("banana".compareTo("apple")); // > 0
a.compareTo(b) →
< 0 — jeśli a jest przed b
0 — jeśli równe
> 0 — jeśli a jest po b
compareTo()
Jak to działa?
- Porównanie przebiega od lewej do prawej według kodów znaków Unicode.
- Przy pierwszej różnicy zwracana jest różnica kodów znaków.
- Jeśli jeden łańcuch jest prefiksem drugiego, krótszy jest „mniejszy”.
System.out.println("cat".compareTo("catalog")); // < 0 ("cat" krótsze)
System.out.println("catalog".compareTo("cat")); // > 0
Przykład: sortowanie tablicy łańcuchów
String[] fruits = {"banana", "apple", "pear"};
Arrays.sort(fruits); // wewnętrznie używa compareTo()
System.out.println(Arrays.toString(fruits)); // [apple, banana, pear]
compareToIgnoreCase()
System.out.println("Java".compareToIgnoreCase("java")); // 0
5. Metody startsWith() i endsWith()
Metody startsWith() i endsWith() sprawdzają początek i koniec łańcucha, zwracając true/false.
String fileName = "document.pdf";
String url = "https://www.google.com";
System.out.println(fileName.startsWith("doc")); // true
System.out.println(fileName.endsWith(".txt")); // false
System.out.println(url.startsWith("https://")); // true
Po co to: walidacja formatów (nazw plików, URL) oraz filtrowanie po prefiksach/sufiksach (np. wszystkie ".jpg").
6. Metoda contains(): szukanie podciągu
contains(CharSequence s) — prosty sposób sprawdzenia obecności podciągu. Czuła na wielkość liter.
String text = "Witaj w świecie Javy!";
System.out.println(text.contains("świat")); // true
System.out.println(text.contains("C++")); // false
Aby zignorować wielkość liter, sprowadź oba łańcuchy do tego samego przypadku: toLowerCase()/toUpperCase().
7. Metody toLowerCase() i toUpperCase()
Zwracają nowy łańcuch przekształcony do małych lub wielkich liter. Przydatne do porównywania nieczułego na wielkość liter i formatowania.
String title = "Java Programming";
String lower = title.toLowerCase();
String upper = title.toUpperCase();
System.out.println(lower); // java programming
System.out.println(upper); // JAVA PROGRAMMING
8. Metoda split(): dzielenie łańcucha na części
split(String regex) dzieli łańcuch według separatora (wyrażenie regularne) i zwraca tablicę String[].
Przykład 1: po przecinkach
String names = "Alex,Maria,Ivan,Elena";
String[] nameArray = names.split(",");
for (String name : nameArray)
{
System.out.println(name.trim()); // trim() usuwa ewentualne spacje
}
// Wynik:
// Alex
// Maria
// Ivan
// Elena
Przykład 2: po spacjach
String sentence = "Uczę się Javy";
String[] words = sentence.split(" ");
for (String word : words)
{
System.out.println(word);
}
// Wynik:
// Uczę
// się
// Javy
Uwagi:
- Separator to wyrażenie regularne. Znaki specjalne należy escapować (np. kropka: "\\.").
- Metoda zawsze zwraca tablicę, nawet jednoelementową.
9. Praktyka: porównywanie łańcuchów w prawdziwej aplikacji
String registeredEmail = "user@example.com";
String registeredPassword = "Secret123";
Scanner console = new Scanner(System.in);
System.out.print("Podaj e-mail: ");
String email = console.nextLine();
System.out.print("Podaj hasło: ");
String password = console.nextLine();
// Porównujemy e-mail bez uwzględniania wielkości liter, a hasło — z uwzględnieniem
if (email.equalsIgnoreCase(registeredEmail) && password.equals(registeredPassword))
{
System.out.println("Witamy!");
}
else
{
System.out.println("Nieprawidłowy e-mail lub hasło.");
}
Uwagi: dla adresu e-mail używamy equalsIgnoreCase(), a dla hasła — ściśle equals(). Operator == dla łańcuchów jest niedozwolony — porównuje referencje.
10. Typowe błędy przy porównywaniu łańcuchów
Błąd nr 1: porównywanie łańcuchów przez == zamiast equals()
Operator == porównuje referencje, a nie zawartość, więc wynik może być nieoczekiwany.
Błąd nr 2: wywołanie equals() na obiekcie, który może być null
Wywołuj metodę na obiekcie, który na pewno nie jest null, albo użyj Objects.equals(a, b).
Błąd nr 3: ignorowanie wielkości liter, gdy ma to znaczenie
Na przykład hasła powinny być porównywane z uwzględnieniem wielkości liter. Doprecyzuj wymagania.
Błąd nr 4: porównywanie łańcuchów z obiektami innych typów
"123" i 123 — to nie to samo. equals() nie konwertuje typów automatycznie.
Błąd nr 5: sortowanie łańcuchów o różnych wielkościach liter
Wielkie litery występują przed małymi. Do sortowania bez uwzględniania wielkości liter użyj Arrays.sort(array, String.CASE_INSENSITIVE_ORDER).
GO TO FULL VERSION