niedziela, 1 czerwca 2008

Java Killers #007

Witam na kolejnej odsłonie cyklu Java Killers. Dzisiejszy przykład jest hybyrdą przykładu nadesłanego przez Damiana Szczepanika oraz małego triku, który znalazłem na sieci (niestety źródło zapodziałem :( ). Myślę, że dzisiejszy JK nie powinien sprawić kłopotu nikomu, kto zdawał SCJP, ale kto wie, moze się mylę?
Zatem spojrzmy na naszych bohaterów, trzy klasy: Matcher1, Matcher2 oraz Matcher3.


1 package javakillers.part007;
2
3 /**
4 * @author pawel
5 */
6 public class Matcher1
7 {
8 void g(int x)
9 {
10 System.err.print("int ");
11 }
12
13 void g(long x)
14 {
15 System.err.print("long ");
16 }
17
18 void g(Integer x)
19 {
20 System.err.print("Integer ");
21 }
22 }
23
24


1 package javakillers.part007;
2
3 /**
4 * @author pawel
5 */
6 public class Matcher2
7 {
8 void g(short x)
9 {
10 System.err.print("short ");
11 }
12
13 void g(byte x)
14 {
15 System.err.print("byte ");
16 }
17
18 void g(long x)
19 {
20 System.err.print("long ");
21 }
22
23 void g(Integer x)
24 {
25 System.err.print("Integer ");
26 }
27 }
28
29


1 package javakillers.part007;
2
3 /**
4 * @author pawel
5 */
6 public class Matcher3
7 {
8 void g(int x)
9 {
10 System.err.print("short ");
11 }
12
13 void g(Integer x)
14 {
15 System.err.print("Integer ");
16 }
17
18 void g(Object x)
19 {
20 System.err.print("Object ");
21 }
22 }
23
24


I na koniec metoda, która to wszystko uruchomi:


9 public static void main(String[] args)
10 {
11 int prim = 10;
12 Object obj = prim;
13 Integer intObj = (Integer) obj;
14
15 new Matcher1().g(prim);
16 new Matcher2().g(prim);
17 new Matcher3().g(obj);
18 new Matcher3().g(intObj);
19 }

Pytanie, które pozostaje otwarte, to co zwróci nam wywołanie tej metody? Odpowiedzi do wyboru aż sześć:

A) int Integer Object Integer
B) int long Object Integer
C) int Integer Integer Integer
D) int long Integer Integer
E) Integer Integer Integer Integer
E) Integer Integer Object Integer

Zanim przeczytasz rozwiązanie, spróbuj pomyśleć nad odpowiedzią.

Prawidłowa odpowiedź to oczywiście B) int long Object Integer. Aby zrozumieć czemu tak a nie inaczej należy wiedzieć, że przekazując metodzie wartość typu innego niż się spodziewała, dokonana zostaje konwersja typów (method-call conversion jeśli chcemy się trzymać terminologii). Konwersja jest możliwa tylko, jeśli typ metody jest "szerszy" (ang. widening conversion) od typu przekazywanego. Tak więc int'a przekażemy do metody z longiem ale nie na odwórt. Typy od "najwęższych" do "najszerszych" uszeregowane są następująco:

byte -> short -> int -> long -> float -> double

Ot i cała filozofia. Odnośnie ostatniego Matchera3, w pierwszym przypadku spodziewamy się obiektu klasy Object i ją dostajemy, w następnym wywołaniu obiektu klasy Integer i ją dostajemy. Mimo że jest to wciąż jeden i ten sam obiekt, to jednak kontekst wywołania jest różny, stąd i inne dopasowanie typów podczas wywoływania metody.

1 komentarz:

Filus pisze...

I na koniec metoda, która to wszystko uruchomi:

9 public static void main(String[] args)
[...]

Pytanie, które pozostaje otwarte, to co zwróci nam wywołanie tej metody?


Hmmm... Czy to przypadkiem nie zwróci voida? ;)