Lambda - porównanie Stringa za pomocą == zwraca poprawny wynik

0

Witajcie!

Kończę ogarniać lambdę i mam do was wszystkich pytanie względem przykładu z książki (który już przybliżam).

Mam taki oto interfejs.

public interface MyFunc<T> {
	int func(T[] vals, T t);
}

Taką klasę

public class MyArrayOps {
	
	static <T> int countMatching(T[] vals, T v) {
		int count = 0;
		
		for (int i = 0; i < vals.length; i++) {
			if (vals[i] == v) {
				++count;
			}
		}
		return count;
	}
}

Oraz klasę wykonawczą

public class GenericMethodRefDemo {
	
	static <T> int myOp(MyFunc<T> f, T[] vals, T v) {
		return f.func(vals, v);
	}
	
	public static void main(String[] args) {
		Integer[] vals = {1,2,3,4,2,3,4,4,5};
		String[] strs = {"Jeden", "Dwa", "Trzy", "Dwa"};
		
		int count;
		
		count = myOp(MyArrayOps::countMatching, vals, 4);
		System.out.println(count);
		count = myOp(MyArrayOps::countMatching, strs, "Dwa");
		System.out.println(count);
	}
}

Moje pytanie brzmi: dlaczego podając tablicę obiektów String i osobny obiekt typu String, czyli ta linijka

count = myOp(MyArrayOps::<String>countMatching, strs, "Dwa");

zwraca poprawny wynik? W końcu metoda countMatching porównuje obiekty za pomocą operatora ==, co normalnie porównałoby referencje...
Czy lambda wnioskując typ podanych obiektów korzysta niejawnie z metody equals przy użyciu operatora ==?

1

Niesłusznie zakładasz, że referencje są różne.

0

@bogdans: Ale jak to? O.o
Czy taka sama referencja nie byłaby, gdybym wykorzystał coś takiego?:

count = myOp(MyArrayOps::countMatching, strs, strs[1]);

Rozwiń, jeśli możesz, bo już kompletnie zgłupiałem... (zwłaszcza, że to przykład z kompendium Herberta Schildta przepisany jota w jotę)

1

Tak działa kompilator - jeśli dostrzeże dwa identyczne Stringi (a przy tworzeniu drugiego nie ma operatora new), to nie tworzy dwóch różnych obiektów.

String a = "dwa";
String b = "dwa";
//porównanie a == b zwraca true
String c = new String("dwa");
//porównanie a == c zwraca false
String d = new String("dwa").intern();
//porównanie a == d zwraca true
0

Rzeczywiście, masz rację...
Czy to oznacza błąd w książce?

0

O jaki błąd pytasz?

0

Już nie ważne, już (chyba) ogarnąłem, że jego celem było porównanie referencji, a nie wartości obiektu (bo tak jest, prawda?)

1

@Burdzi0 w 99% przypadków chcesz porównywać wartości a nie referencje. No i pamiętaj że String w javie, tak samo jak np. Integer maja pewien wewnętrzny cache, wiec obiekty tworzone przez valueOf() mogą być tymi samymi obiektami. To nie jest problem bo te obiekty i tak są immutable -> zmiana stringa powoduje utworzenie nowego.

0
Shalom napisał(a):

No i pamiętaj że String w javie, tak samo jak np. Integer maja pewien wewnętrzny cache, wiec obiekty tworzone przez valueOf() mogą być tymi samymi obiektami. To nie jest problem bo te obiekty i tak są immutable -> zmiana stringa powoduje utworzenie nowego.

Tego nie wiedziałem, dzięki :)

1

I tu jako uzupełnienie ciekawa metoda z klasy String
intern

Przydaje się raz na piętnaście lat.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.