Bəzi qarışıq testlərin izahı
Nümunə 1:
import static java.lang.System.*; class _ { static public void main(String[] __A_V_) { String $ = ""; for (int x = 0; ++x < __A_V_.length;) $ += __A_V_[x]; out.println($); } }
And the command line:
java _ - A .
What is the result?
-A
A.
-A.
_A.
_-A.
- Compilation fails
- An exception is thrown at runtime
İzahı:
Başlayaq ilk sətirdən; java.lang paketi
Java tərəfindən bütün class`lara default olaraq import olunur, onu ayrıca aşkar şəkildə import etməyə ehtiyac yoxdur. Bu nümunədə adi importdan fərqli olaraq static importdur, yəni System
class`ının içində mövcud olan bütün static üzvlər (members) import olunur. Bu səbəbdən də 8-ci sətirdə dəyişəni çap etmək üçün System
class adını istifadə etmədik. Əgər import sətrini commentə atsaq, o zaman 8-ci sətir compile error verəcək.
İkinci diqqət çəkən məsələ “identifier” adlarıdır. Java`da identifier adları hərflə və yaxud da $ və ya _ (underscore) simvollarından biri ilə başlamalıdır. Ona görə də _
, $
və __A_V_
adları məsləhət görülən adlar olmasa da qaydalar çərçivəsində elan edilmiş adlardır.
3-cü diqqət çəkən məsələ for
dövrünün quruluşudur. Standart for
dövrü adətən 3 hissədən ibarət olur (mötərizənin içi nəzərdə tutulur):
for(initialization; booleanExpression; updateStatement) { // body }
Və bütün bu hissələr optional`dı, yəni istəyə bağlı olaraq istifadə oluna da bilər, buraxıla da bilər. Aşağıdakı formada yazsaq normal compile olunacaq və şərt buraxıldığından sonsuz dövrə girəcək.
for( ; ; ) { // infinite loop }
Bu nümunədə 3-cü hissə (updateStatement) buraxılıb. Dövrün şərtinə görə əgər x
, main
metoduna göndərilən parametrlərin sayından kiçik olarsa dövr işləyəcəkdir. Azacıq da açıq söyləmiş olsaq command line`dan class`ı run etmək üçün bu sintaksisi istifadə edirik:
java ClassAdi parametr1 parametr2 parametr3 ...
Bu nümunədə verilmiş command line`a görə main metoduna göndərilən parametrlər aşağıdakı massiv şəklini almış olur:
String[] __A_V_ = {“-“, “A”, “.”};
Bu elementlər for
dövrü vasitəsilə şərtə uyğun olaraq $
dəyişəninə concatenation vasitəsilə mənimsədilir və sonda çap olunur. for
`dan sonra blok mötərizələr olmadığına görə onun tərkibinə özündən sonrakı ancaq bir ifadə (statement) daxildir, yəni out.println($);
for
`un gövdəsinə daxil deyil və bir dəfə icra edilir.
İndi for`un 3 halına baxaq
for (int x = 0; ++x < __A_V_.length;)
++x
– pre-increment operatoru olduğundan əvvəlcə operator icra edilir və qaytarılan yeni dəyər massivin ölçüsü ilə müqayisə edilir:
- 1 < 3 ⇒
$ += __A_V_[1];
⇒ A - 2 < 3 ⇒
$ += __A_V_[2];
⇒ A. - 3 < 3 ⇒
false
Output: A.
for (int x = 0; x++ < __A_V_.length;)
x++
– post-increment operatoru olduğundan əvvəlcə müqayisə aparılır, sonra operator icra edilir:
- 0 < 3 ⇒
$ += __A_V_[1];
⇒ A - 1 < 3 ⇒
$ += __A_V_[2];
⇒ A. - 2 < 3 ⇒
$ += __A_V_[3];
⇒ ArrayIndexOutOfBoundsException: 3
for (int x = 0; x < __A_V_.length; ++x)
Bu standart qaydada işlətdiyimiz for
dövrüdür və updateStatement mövcuddur. Burada bir vacib məqamı yadda saxlamaq lazımdır ki, updateStatement həmişə gövdədən sonra icra edilir, ona görə də bu halda ++x
yaxud x++
olmağı heç bir fərq etmir.
- 0 < 3 ⇒
$ += __A_V_[0];
⇒ – - 1 < 3 ⇒
$ += __A_V_[1];
⇒ -A - 2 < 3 ⇒
$ += __A_V_[2];
⇒ -A. - 3 < 3 ⇒
false
Output: -A.
Nümunədə qeyd olunan sualın doğru cavabı 2-ci bənddir.
Nümunə 2:
int m = 9, n = 1, k = 0; while (m > n) { m--; n += 2; k += m + n; } System.out.println(k);
Həlli:
Bu sualdakı əməliyyatları beynimizdə şifahi şəkildə hesablayıb k
`nın cavabını tapmaq nisbətən çətindir. Çünki 2 ya 3 addımdan sonra bütün dəyişənlərin son dəyərini yadda saxlamaq mümkün olmur yaxud səhv yadda saxlama ehtimalı da böyükdür, düz hesabladığına əmin olmaq üçün sualı yenidən beynində hesablamağa başlayırsan. Və bütün bunlar da müəyən vaxt itkisinə səbəb olur. Nəzərə alsaq ki, imtahanda hər suala ortalama 1.5-2 dəqiqə vaxt düşür, o zaman bu sualların optimal həll variantlarını axtarıb tapmaq lazım gəlir. Bu həll variantlarından biri də cədvəl şəklində həll variantıdır. Dəyişənlərin adlarını sütunlara yazırıq və hər növbəti sətirdə də dəyişənlərin müvafiq əməliyyatlardan sonra dəyişilmiş dəyərini qeyd edirik:
m | n | k |
9 | 1 | 0 |
8 | 3 | 11 |
7 | 5 | 23 |
6 | 7 | 36 |
Nümunə 3:
int count = 0; ROW_LOOP: for (int row = 1; row <= 3; row++) for (int col = 1; col <= 2; col++) { if (row * col % 2 == 0) continue ROW_LOOP; count++; } System.out.println(count);
Həlli:
row | col | count |
1 | 1 | 1 |
1 | 2 | 1 |
2 | 1 | 1 |
2 | 2 | 1 |
3 | 1 | 2 |
3 | 2 | 2 |
Nümunə 4:
public static void main(String[] args) { int x = 5; while (x >= 0) { int y = 3; while (y > 0) { if (x < 2) continue; x--; y--; System.out.println(x * y + " "); } } }
43 31 20 12
6 4 2 3
8 3 0 2
- The code will not compile because of line 6.
- The code will not compile because of line 7.
- The code contains an infinite loop and does not terminate.
İzahı:
Bu suala “Sybex Practise Exams”-in birində rast gələcəksiniz, mənim ən çox bəyəndiyim suallardan biridir. Sualı tapmaq üçün xüsusi bir texnika tələb olunmur. Doğru cavablandırmaq üçün sadəcə güclü diqqət və səbr tələb olunur. Özünüz cavablandırmağa çalışın, sualın sonuna çatdığınıza əmin olmadan, cavabı doğru tapdığınıza əmin olmayın 🙂
[topics lang=az]