3. [TD]: Sınıflar
Anahtar kelimeler: sınıf, arayüz, miras, istisna, polimorfizm
Önerilen okumalar:
- [ref1]: Sınıflar ve Arayüzler kitabının 2. bölümündeki 2.1, 2.2, 2.4 ve 2.7 numaralı paragraflar
- 3.3 (String sınıfı), 3.5 (ArrayList sınıfı) ve 3.6 (Arrays sınıfı) paragrafları
ELECTIONS alıştırmasının 1. bölümünde hiçbir sınıf kullanılmamıştır. Çözüm, C dilinde yazılmış gibi oluşturulmuştur. Şimdi Java sınıf kavramını tanıtacağız.
3.1. Support
![]() | ![]() |
[support / chap-03] klasörü, bu bölümün Eclipse projesini içerir.
Bundan sonra JDK 1.8 sürümüyle çalışacağız, çünkü ileride ele alacağımız bazı projeler bu JDK sürümünü gerektiriyor. Kullanılan JDK sürümünü öğrenmek için şu adımları izleyin:
![]() |
![]() |
- [4]'te, kullanılan JRE (Java Runtime Environment). Bu JRE aslında burada bir JDK (Java Development Kit) olup, burada ise [jdk1.8.0_60]'tir. Eğer bu bir JDK değilse veya 1.8'den daha eski bir sürümünüz varsa, [5-21] için aşağıdaki adımları izleyin;
![]() |
- [8]'e, Eclipse tarafından şu anda varsayılan olarak kullanılan JRE'e;
- [11]'e, Eclipse tarafından şu anda bilinen çeşitli JDK ve JRE sürümlerine;
![]() |
- [15]'e gelirken, JRE yerine JDK'i seçin. Bu belge, JDK gerektiren Maven projeleri kullanmaktadır;
![]() |
![]() |
- [21]'te, sürümü >=1.8 olan bir JDK vardır;
- [22-23]'te, projenin fasetlerine (aynı Eclipse projesinin farklı görünümleri) erişin;
![]() |
- [24]'te, Java sürümünüzün >=1.8 olduğundan emin olun;
3.2. [ListeElectorale] sınıfı
C dilinde, seçimlere katılan bir listeyi temsil etmek için muhtemelen bir yapı kullanırdık. Bu yapı şu şekilde olabilirdi:
Java dilinde "yapı" kavramı yoktur. Bunun yerine "sınıf" kavramı kullanılmalıdır. Bu nedenle, aday listesiyle ilgili bilgileri depolamak için bir sınıf oluşturulmasına karar verilir. Bu sınıfın temel yapısı şu şekilde olacaktır:
package istia.st.elections;
public class ListeElectorale {
/**
* identité de la liste
*/
private int id;
/**
* nom de la liste
*/
private String nom;
/**
* nombre de voix de la liste
*/
private int voix;
/**
* nombre de sièges de la liste
*/
private int sieges;
/**
* indique si la liste est éliminée ou non
*/
private boolean elimine;
/**
* constructeur par défaut
*/
public ListeElectorale() {
}
/**
*
* @param nom String : le nom de la liste
* @param voix int : son nombre de voix
* @param sieges int : son nombre de sieges
* @param elimine boolean : son état éliminé ou non
*/
public ListeElectorale(int id,String nom, int voix, int sieges, boolean elimine) {
...
}
/**
*
* @return int : l'identifiant de la liste
*/
public int getId() {
...
}
/**
* initialise l'identifiant de liste
* @param id int : identifiant de la liste
* @throws ElectionsException si id<1
*/
public void setId(int id) {
...
}
/**
*
* @return String : le nom de la liste
*/
public String getNom() {
...
}
/**
* initialise le nom de la liste
* @param nom String : nom de la liste
* @throws ElectionsException si le nom est vide ou blanc
*/
public void setNom(String nom) {
...
}
/**
*
* @return int : le nombre de voix de la liste
*/
public int getVoix() {
...
}
/**
* initialise le nombre de voix de la liste
* @param voix int : le nombre de voix de la liste
*/
public void setVoix(int voix) {
...
}
/**
*
* @return int : le nombre de sièges de la liste
*/
public int getSieges() {
...
}
/**
* fixe le nombre de sièges de la liste
* @param sieges int : le nombre de sièges de la liste
*/
public void setSieges(int sieges) {
...
}
/**
*
* @return boolean : valeur du champ elimine
*/
public boolean isElimine() {
...
}
/**
*
* @param sieges int
*/
public void setElimine(boolean elimine) {
...
}
/**
*
* @return String : identité de la liste électorale
*/
public String toString() {
...
}
}
- 8. satır: Bir listeyi benzersiz bir şekilde tanımlayan numara. Burada zorunlu değildir, ancak ileride kullanılmak üzere ayrılmıştır.
- 13. satır: listenin adı.
- 17. satır: Listenin aldığı oy sayısı
- 21. satır: Listenin kazandığı sandalye sayısı
- 25. satır: Listenin elenip elenmediğini (seçim barajının altında oy yüzdesi elde edip etmediğini) belirten boole değeri.
[xyz] adlı her özel alan, [setXyz] adlı bir yöntemle başlatılabilir. [getXyz] yöntemi ise [xyz] adlı özel alanın değerini almayı sağlar. [xyz]'in boole türü bir alan olduğu özel durumda, [getXyz] yöntemi, [isXyz] yöntemiyle değiştirilebilir. Bu yöntemlerin özel isimlendirilmesi, JavaBean standardı olarak adlandırılan bir kodlama standardına uygundur. Böylece aşağıdaki genel yöntemleri tanımlıyoruz:
- getId (satır 48), setId (satır 57)
- getNom (satır 65), setNom (satır 74)
- getVoix (satır 82), setVoix (satır 90)
- getSieges (satır 98), setSieges (satır 106)
- isElimine (satır 114), setElimine (satır 122)
- satır 30-31: parametresiz bir oluşturucu tanımlar. Bu oluşturucu, [ListeElectorale] nesnesini başlatmadan oluşturmaya olanak tanır. Bu nesne daha sonra set yöntemleri kullanılarak başlatılabilir.
- satır 40-42: Beş özel alanını başlatarak bir [ListeElectorale] nesnesi oluşturulmasına olanak tanıyan bir oluşturucu tanımlar.
- 130-132. satırlar: Nesnenin beş alanının değerlerini içeren bir karakter dizesi döndüren [toString] yöntemini tanımlar.
ListeElectorale sınıfı için bir test programı şu şekilde olabilir:
package istia.st.elections.tests;
import istia.st.elections.ListeElectorale;
public class MainTest1ListeElectorale {
public static void main(String[] args) {
// seçmen listesinin oluşturulması
ListeElectorale listeElectorale1 = new ListeElectorale(1, "A", 32000,
0, false);
// liste kimliğinin görüntülenmesi
System.out.println("listeElectorale1=" + listeElectorale1);
// koltuk sayısını değiştirme
listeElectorale1.setSieges(2);
// 1 numaralı listenin kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale1=" + listeElectorale1);
// yeni bir seçim listesi
ListeElectorale listeElectorale2 = listeElectorale1;
// liste 2 kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale2=" + listeElectorale2);
// koltuk sayısında değişiklik
listeElectorale2.setSieges(3);
// 2 listenin kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale2=" + listeElectorale2);
System.out.println("listeElectorale1=" + listeElectorale1);
}
}
Bu testin Eclipse ortamı şu şekilde olabilir:
![]() |
- [1]: projenin adı [elections-02A]'tir
- [2]: Uygulama bir pakete yerleştirilecektir; burada [istia.st.elections]
- [3]: [ListeElectorale.java], [ListeElectorale] sınıfının kaynak kodudur
- [4]: Test sınıfları bir pakete yerleştirilecektir; burada [istia.st.elections.tests]
- [5]: [MainTest1ListeElectorale] test sınıfı
Yukarıdaki programın çalıştırılmasından sonra elde edilen ekran görüntüsü şöyledir:

Yapılması gereken: Yukarıdakilerden yararlanarak, ListeElectorale sınıfının kodunu tamamlayın.
3.3. [ElectionsException] istisna sınıfının oluşturulması
Java dilindeki çeşitli istisna sınıfları arasında [RuntimeException] adlı bir sınıf bulunmaktadır. Bu sınıf, tüm istisna sınıflarının kökü olan [Exception] sınıfından türetilmiştir. [RuntimeException] örneklerinin veya bunlardan türetilen örneklerin özelliği, bunların bildirilmesi veya yönetilmesi gerekmemesidir. Bunlara kontrol edilemeyen istisnalar denir.
İlk örneği ele alalım. [BufferedReader] sınıfı, örnekleri bir veri akışındaki metin satırlarını okumaya olanak tanıyan bir sınıftır. Bu sınıf, imzası aşağıdaki gibi olan [readLine] yöntemine sahiptir:
Görüldüğü gibi, bu yöntem [IOException] türünde bir istisna oluşturabilir. Bu sınıfın ağaç yapısı şöyledir:
[IOException] sınıfı, [Exception] sınıfından türetilmiştir (3. satır). Derleyici, [java.lang.Exception] türündeki veya bu türden türetilmiş istisnaları (daha sonra ele alacağımız [RuntimeException] dalı hariç) yönetmemizi ve bildirmemizi zorunlu kılar. Dolayısıyla, klavyeden girilen bir metin satırını okumak için şunun gibi bir kod yazmak zorunda kalacağız:
Başka bir örnek verelim. Bir dizgiyi tamsayıya dönüştürmek için, imzası aşağıdaki gibi olan [Integer.parseInt] statik yöntemini kullanabiliriz:
[s] argümanı, tamsayıya dönüştürülecek karakter dizisidir. Yöntemin [NumberFormatException] türünde bir istisna atabileceği görülmektedir. Bu sınıfın ağaç yapısı şöyledir:
[NumberFormatException] sınıfı, [RuntimeException] sınıfından türetilmiştir (4. satır). Derleyici, [java.lang.RuntimeException] türündeki veya bu türden türetilmiş istisnaları yönetmemizi ve bildirmemizi zorunlu kılmaz. Böylece, şunun gibi bir kod yazabiliriz:
[Integer.parseInt] (9. satır) tarafından oluşturulabilecek olası istisnayı yönetmek için bir [try - catch] cümlesi eklemek zorunda değiliz.
[RuntimeException]'ten türetilmiş istisna sınıfları oluşturmanın ve kullanmanın avantajları ve dezavantajları vardır:
- Avantajlar açısından: kod daha hafif olur
- dezavantajları: C dilindeki yöntemlere geri dönülmesi söz konusu olabilir; burada her fonksiyon, tam da kodu daha hafif tutmak amacıyla çok az kişinin kullandığı bir hata kodu döndürür. Böyle bir işlenmemiş hata oluştuğunda, program genellikle pek de zarif olmayan bir şekilde çöker.
ELECTIONS uygulamamızda ortaya çıkabilecek tüm istisnaları bir araya getiren özel bir sınıf oluşturmaya karar verdik. Bu sınıfın adı [ElectionsException] olacak ve [RuntimeException] sınıfından türetilecektir. Kod şöyledir:
package istia.st.elections;
public class ElectionsException extends RuntimeException {
private static final long serialVersionUID = 1L;
public ElectionsException() {
super();
}
public ElectionsException(String message) {
super(message);
}
public ElectionsException(Throwable cause) {
super(cause);
}
public ElectionsException(String message, Throwable cause) {
super(message, cause);
}
}
- 1. satır: Sınıfı [istia.st.elections] paketine yerleştiriyoruz;
- 3. satır: Sınıf, [RuntimeException] sınıfından türetilmiştir. Dolayısıyla, denetlenmemiştir;
- 4. satır: Şu an için göz ardı edebileceğimiz bir serileştirme tanımlayıcısı;
- Uygulamamızda iki tür oluşturucu kullanacağız:
- Aşağıdaki gibi 15-17. satırlardaki klasik yapıcı:
Bu durumda, böyle bir istisna oluşturan bir yöntemi çağıran yöntem, bunu şu şekilde yönetebilir:
// istisna testi
try {
listeElectorale2.setSieges(-3);
} catch (ElectionsException ex) {
System.err.println("L'exception suivante s'est produite : ["
+ ex.toString() + "]");
}
- (devamı)
- ya da 14-20. satırlarda yer alan, daha önce meydana gelmiş bir istisnayı [ElectionsException] türünde bir istisna içine kapsülleyerek yukarıya iletmeye yönelik kod:
try {
...;
} catch (SQLException ex) {
// istisna kapsüllenir
throw new ElectionsException("erreur de fermeture de la connexion à la BD",ex);
}
Bu ikinci yöntemin avantajı, ilk istisnada yer alabilecek bilgileri korumasını sağlamasıdır. Bu durumda, böyle bir istisna oluşturan bir yöntemi çağıran yöntem, bunu şu şekilde yönetebilir:
try {
...;
} catch (ElectionsException ex) {
System.out.println(ex.getMessage() + ", Cause : "+ ex.getCause().getMessage());
System.exit(1);
}
Yapılması gereken iş: ListeElectorale sınıfının kodunu, istenen başlatma işlemi hatalıysa (örneğin, adı boş bir dizeyle başlatmak gibi) set yöntemlerinin [ElectionsException] türünde bir istisna atması için yeniden düzenleyin.
Bu yeni sürümün test amaçlı Eclipse projesi şu şekilde olabilir:
![]() |
- [1]: projenin adı [elections-02B]'tir
- [2]: uygulama bir pakete yerleştirilmiştir, burada [istia.st.elections]
- [3]: [ListeElectorale] ve [ElectionsException] sınıfları
- [4]: Test sınıfları bir pakete yerleştirilmiştir; burada [istia.st.elections.tests]
- [5]: [MainTest1ListeElectorale] test sınıfı
Daha önce incelenen [MainTest1ListeElectorale] test sınıfı, istisna durumlarını test etmek için hafifçe değiştirilmiştir:
package istia.st.elections.tests;
import istia.st.elections.ElectionsException;
import istia.st.elections.ListeElectorale;
public class MainTest1ListeElectorale {
public static void main(String[] args) {
// seçmen listesi oluşturma
ListeElectorale listeElectorale1 = new ListeElectorale(1, "A", 32000,
0, false);
// liste kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale1=" + listeElectorale1);
// koltuk sayısının değiştirilmesi
listeElectorale1.setSieges(2);
// 1 numaralı listenin kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale1=" + listeElectorale1);
// yeni bir seçim listesi
ListeElectorale listeElectorale2 = listeElectorale1;
// liste 2 kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale2=" + listeElectorale2);
// koltuk sayısında değişiklik
listeElectorale2.setSieges(3);
// 2 listenin kimlik bilgilerinin görüntülenmesi
System.out.println("listeElectorale2=" + listeElectorale2);
System.out.println("listeElectorale1=" + listeElectorale1);
// istisna testi
try {
listeElectorale2.setSieges(-3);
} catch (ElectionsException ex) {
System.err.println("L'exception suivante s'est produite : ["
+ ex.toString() + "]");
}
}
}
- 28. satır: koltuk sayısını yasaklanmış bir değerle başlatmaya çalışılıyor
- 30. satır: istisna oluşursa, bu görüntülenir
Testin yürütülmesi şu sonuçları vermektedir:

Koltuk sayısını geçersiz bir değerle başlatmaya çalıştığımızda (kodun 28. satırı), [ListeElectorale] sınıfının bir istisna oluşturduğu görülmektedir.
3.4. Bir birim test sınıfı
Yukarıdaki test türü görsel bir doğrulamaya dayanmaktadır. Ekranda beklenen sonucun elde edilip edilmediği kontrol edilir. Bu yöntem, profesyonel ortamlarda tavsiye edilmez. Testler her zaman mümkün olduğunca otomatikleştirilmeli ve hiçbir insan müdahalesine gerek kalmayacak şekilde tasarlanmalıdır. İnsanlar yorgunluğa maruz kalır ve testleri doğrulama yetenekleri gün içinde azalır.
Bir uygulama zamanla gelişir. Her güncellemede, uygulamanın “gerilemediğini”, c.a.d, yani ilk yazım aşamasında yapılan işlevsellik testlerini geçmeye devam ettiğini doğrulamak gerekir. Bu testlere “gerileme testi” denir. Biraz büyük bir uygulama, yüzlerce test gerektirebilir. Uygulamanın her sınıfındaki her yöntem test edilir. Buna birim testleri denir. Bu testler, otomatikleştirilmemişse çok sayıda geliştiriciyi meşgul edebilir.
Testleri otomatikleştirmek için çeşitli araçlar geliştirilmiştir. Bunlardan biri [JUnit] adını taşır. Bu, testleri yönetmeye yönelik bir sınıf kütüphanesidir. [ListeElectorale] sınıfını test etmek için bu aracı kullanacağız.
JUnit (4.x sürümleri) test programı şu şekildedir:
package istia.st.elections.tests;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class JUnitEssai {
@Before
public void avant() throws Exception {
System.out.println("tearUp");
}
@After
public void après() throws Exception {
System.out.println("tearDown");
}
@Test
public void t1() {
System.out.println("test1");
Assert.assertEquals(1, 1);
}
@Test
public void t2() {
System.out.println("test2");
Assert.assertEquals(1, 2);
}
}
- 1. satır: Sınıf, [istia.st.elections.tests] paketine yerleştirilmiştir;
- 11. satır: [@Before] anotasyonu ile anotlanmış yöntem, her birim testinden önce yürütülür;
- 16. satır: [@After] anotasyonuyla işaretlenmiş yöntem, her birim testinden sonra yürütülür;
- 21. satır: [@Test] anotasyonuyla işaretlenmiş bir yöntem, birim testi tarafından test edilen bir yöntemdir. [@Test] anotasyonuyla işaretlenmiş yöntemler, test eden kişinin test edilecek yöntemleri kendisi seçebileceği durumlar hariç, sırayla çalıştırılacaktır. [@Test] yönteminin her çalıştırılmasından önce, [@Before] yöntemi çalıştırılır. [@Test] yönteminin her çalıştırılmasından sonra, [@After] yöntemi çalıştırılır;
- 22-25. satırlar: [t1] adlı bir test yöntemini tanımlar;
- 18. satır: Assertion'ları doğrulamaya yarayan [Assert.assert*] yöntemlerinden biri. Aşağıdaki [assert] yöntemleri bulunur:
- assertEquals(ifade1, ifade2): iki ifadenin değerlerinin eşit olup olmadığını kontrol eder. Birçok ifade türü kabul edilir (int, String, float, double, boolean, char, short). İki ifade eşit değilse, [AssertionFailedError ] türünde bir istisna atılır,
- assertEquals(reel1, reel2, delta): İki reel sayının delta kadar farklı olup olmadığını kontrol eder; c.a.d abs(reel1-reel2)<=delta. Örneğin, iki değerin 10⁻⁶'ya yakın olup olmadığını kontrol etmek için assertEquals(reel1, reel2, 1E-6) yazılabilir;
- assertEquals(message, expression1, expression2) ve assertEquals(message, réel1, réel2, delta), [assertEquals] yöntemi başarısız olduğunda atılan [AssertionFailedError] türündeki istisnaya eşleştirilecek hata mesajını belirlemeye olanak tanıyan varyantlardır,
- assertNotNull(Object) ve assertNotNull(message, Object): Object'in null'a eşit olmadığını doğrular,
- assertNull(Object) ve assertNull(message, Object): Object'in null'a eşit olup olmadığını kontrol eder,
- assertSame(Object1, Object2) ve assertSame(message, Object1, Object2): Object1 ve Object2 referanslarının aynı nesneye işaret edip etmediğini kontrol eder,
- assertNotSame(Object1, Object2) ve assertNotSame(message, Object1, Object2): Object1 ve Object2 referanslarının aynı nesneye işaret etmediğini doğrular;
- 24. satır: bu doğrulama başarılı olmalıdır;
- satır 30: bu doğrulama başarısız olmalıdır;
Eclipse ortamında, JUnit adlı bir test sınıfı şu şekilde oluşturulabilir:
![]() |
- [1]: Test sınıfını eklemek istediğiniz pakete sağ tıklayın, ardından [JUnit / New / JUnit Test Case] seçeneğini seçin
![]() |
- [1]: bir sürüm seçin JUnit;
- [2]: Test sınıfının oluşturulacağı klasörü seçin;
- [3]: Test sınıfının oluşturulacağı paketin seçilmesi;
- [4]: test sınıfının adı;
- [5]: oluşturulacak sınıfa dahil edilecek yöntemlerin seçimi;
- [6]: JUnitEssai sınıfı oluşturuldu
Önceki sihirbaz, neredeyse boş bir sınıf oluşturur:
package istia.st.elections.tests;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
public class JUnitEssai {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
}
Önceki kodu aşağıdaki şekilde tamamlayıp değiştirelim:
package istia.st.elections.tests;
import org.junit.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class JUnitEssai2 {
@Before
public void avant() throws Exception {
System.out.println("tearUp");
}
@After
public void après() throws Exception {
System.out.println("tearDown");
}
@Test
public void t1() {
System.out.println("test1");
Assert.assertEquals(1, 1);
}
@Test
public void t2() {
System.out.println("test2");
Assert.assertEquals(1, 2);
}
}
Eclipse'te, test sınıfına sağ tıklayıp [Run as / JUnit test] seçeneğini seçerek sınıfı çalıştırabilirsiniz:

Bu testin çalıştırılması sonucunda elde edilen sonuçlar şunlardır:

Yukarıda, [test2] yöntemi başarısız olmuştur. Bir test her başarısız olduğunda, ona ait bir hata mesajı görüntülenir. [test2] için bu, yukarıda gösterilen mesajdır. Mesaj, hatanın meydana geldiği satır numarasını (30. satır) belirtir. 30. satırda, başarısız olan çağrı şuydu:
Assert.assertEquals(1, 2);
İlk parametre beklenen değer, ikincisi ise gerçek değer olarak adlandırılır. Yukarıdaki [test2] hata mesajı, beklenen değerin 2 olduğunu, ancak gerçek değerin 3 olduğunu göstermektedir.
Son olarak, çeşitli test yöntemleri tarafından konsola yazılan mesajlar şunlardı:

Bu mesajlar, [@Before] ve [@After] yöntemlerinin, her test yönteminden önce ve sonra sırasıyla başarıyla çağrıldığını göstermektedir.
Test sınıfları mutlaka geliştiriciler tarafından yazılmak zorunda değildir. Bunlar, uygulamanın şartnamelerini hazırlayan kişiler tarafından da yazılabilir. TDD (Test Odaklı Geliştirme) olarak adlandırılan bazı geliştirme yöntemleri, test edilecek sınıflar yazılmadan önce test sınıflarının yazılmasını önerir. Bu, aksi takdirde çeşitli şekillerde yorumlanabilecek spesifikasyonları netleştirmeye bazen olanak tanır.
[ListeElectorale] sınıfı için JUnit 4 adlı bir test oluşturalım. Eclipse'te, daha önce anlatıldığı gibi ilerleyeceğiz:
![]() | ![]() |
Sihirbaz tarafından oluşturulan kodu şu şekilde tamamlıyoruz:
package istia.st.elections.tests;
import org.junit.Assert;
import istia.st.elections.ElectionsException;
import istia.st.elections.ListeElectorale;
import org.junit.Test;
public class JUnitTest1ListeElectorale {
@Test
public void t1() {
// seçmen listesinin oluşturulması
ListeElectorale liste = new ListeElectorale(1, "a", 32000, 0, false);
// kontroller
Assert.assertEquals("a", liste.getNom());
Assert.assertEquals(32000, liste.getVoix());
Assert.assertEquals(false, liste.isElimine());
Assert.assertEquals(0, liste.getSieges());
// kimlik geçerliliğinin kontrolü
boolean erreur = false;
try {
liste.setId(-4);
} catch (ElectionsException e) {
erreur = true;
}
Assert.assertEquals(true, erreur);
// adın geçerliliğinin kontrolü
erreur = false;
try {
liste.setNom("");
} catch (ElectionsException e) {
erreur = true;
}
Assert.assertEquals(true, erreur);
// oy geçerliliği kontrolü
erreur = false;
try {
liste.setVoix(-4);
} catch (ElectionsException e) {
erreur = true;
}
Assert.assertEquals(true, erreur);
// koltuk geçerliliğinin kontrolü
erreur = false;
try {
liste.setSieges(-4);
} catch (ElectionsException e) {
erreur = true;
}
Assert.assertEquals(true, erreur);
}
}
Testin çalıştırılması sonucunda şu çıktı elde edilir:

Testler başarılı oldu. Artık [ListeElectorale] sınıfının çalışır durumda olduğunu varsayacağız.
3.5. MainElections: sürüm 2
Önerilen okumalar:
- [1]: Sınıflar ve Arayüzler başlıklı 2. bölümün 2.1, 2.2, 2.4 ve 2.7 numaralı paragrafları
- 3.3 (String sınıfı), 3.5 (ArrayList sınıfı) ve 3.6 (Arrays sınıfı) paragrafları
[Elections] uygulamasını, aşağıdaki yeni kısıtlamaları ekleyerek yeniden yazmak istiyoruz:
- Aday listesini temsil etmek için [ListeElectorale] sınıfı kullanılacak
- uygulama, klavyeden aşağıdaki bilgileri isteyecektir:
- doldurulacak koltuk sayısı
- listelerin adları ve sesleri. Önceden kaç liste olduğu bilinmemektedir. Son liste, "*" dizesine eşit bir adla belirtilecektir.
- Liste sayısını önceden bilmediğimiz için, listeler öncelikle [ArrayList] türünde bir nesneye kaydedilecektir. Ardından, tüm listeler girildiğinde, bunlar bir liste tablosuna aktarılacaktır.
- Sonuçlar, kazanılan koltuk sayısına göre azalan sırada görüntülenecektir.
T dizisini sıralamak için, [Arrays] sınıfının çeşitli statik yöntemleri kullanılabilir:
- Arrays.sort(T): T dizisini, varsa doğal sıraya göre sıralar (sayılar için artan, tarihler için artan, dizeler için alfabetik, vb.)
- Arrays.sort(T,karşılaştırıcı): doğal bir sıralaması olmayan T tablolarını sıralamak için kullanılır. Bu durumda, listelerin tablosu, listenin belirli bir alanına göre (kazanılan koltuk sayısı) sıralanmalıdır.
Arrays.sort(T,karşılaştırıcı) yönteminde, karşılaştırıcı parametresi aşağıdaki Comparator arayüzünü uygulayan bir nesnedir:

- compare yöntemi, T dizisindeki iki öğeyi karşılaştırmaya olanak tanır
- equals yöntemi, iki nesnenin eşit olup olmadığını belirler
Her iki yöntem de Object türlerini karşılaştırır: obj1 ve obj2. obj1<obj2, obj1=obj2 veya obj1>obj2'in hangisi olduğu, iki nesne arasında oluşturulmak istenen sıralama ilişkisine bağlıdır. Bu arayüzü uygulayan geliştirici, aşağıdakilerin nasıl bilindiğini belirtmelidir:
- obj1, obj2'den daha küçük
- obj1, obj2'den daha büyük
- obj1, obj2'ye eşittir
Tüm Java sınıflarının türediği Object sınıfı, halihazırda [equals] yöntemine sahiptir. O türündeki nesnelerden oluşan bir T dizisini sıralamak için, O sınıfının [equals] yöntemi gerekli değildir. Dolayısıyla, Object sınıfı tarafından sağlanan varsayılan uygulamayı kullanmaya devam edilebilir. Bu durumda yalnızca [compare] yöntemi uygulanmalıdır. Bu yöntem, [Arrays.sort] yöntemi tarafından tekrar tekrar çağrılır. [Arrays.sort] yöntemi, her seferinde sıralanacak T dizisinin iki elemanını compare yönteminin obj1 ve obj2 parametreleri olarak geçirir. Bizim örneğimizde bu elemanlar [ListeElectorale] türünde olacaktır. Burada polimorfizmin iş başında olduğunu belirtelim. [compare] yöntemi, [Object] türünde parametreler alacak şekilde tanımlanmıştır. Bu, yöntemin [Object] türünde veya bunun türevleri olan parametreleri alabileceği anlamına gelir (polimorfizm). [Object], tüm Java sınıflarının üst sınıfı olduğundan, fiili parametreler [ListeElectorale] türünde olabilir.
Artan sırada sıralama için, [compare] yöntemi şu sonucu döndürmelidir:
- -1, obj1 obj2'den küçükse
- +1, obj1 obj2'den büyükse
- obj1, obj2'ye eşitse 0
Azalan sıralamada ise +1 ve -1 değerleri tersine çevrilir. "Küçüktür", "büyüktür", "eşittir" terimleri bir sıralama ilişkisini ifade eder. [ListeElectorale] türündeki nesneler için, liste1'in liste2'den daha az oyu varsa liste1 "liste2'den küçüktür" ilişkisi söz konusudur.
[MainElections] sınıfıyla aynı kaynak dosyada ikinci bir sınıf eklenebilir:
- 2. satır: Sınıf, public olarak tanımlanmamıştır. Bir Java kaynak dosyasında birden fazla sınıf bulunabilir, ancak yalnızca kaynak dosyanın adını taşıyan sınıf public özniteliğine sahip olabilir.
Önceki compare yönteminde, parametreler Object, türündedir; bu da 7. ve 8. satırlarda, yöntem parametrelerinin Object türünden ListeElectorale türüne dönüştürülmesini gerektirir. compare yönteminin imzası, herhangi bir nesneyi karşılaştırmak için yazılmış olan Comparator arayüzü tarafından belirlenir. JDK 1.5 sürümünden itibaren, Comparator adlı genel bir arayüz mevcuttur: Comparator<T>; burada T, herhangi bir Java türüdür. Comparator<T> arayüzündeki compare yöntemi, T türündeki nesneleri karşılaştırır; Object türündeki nesneleri karşılaştırmaz, bu da önceki tür dönüşümlerini ortadan kaldırır. ListeElectorale türündeki nesneleri karşılaştıran sınıf şu şekilde olabilir:
// seçim listelerinin karşılaştırılması sınıfı
class CompareListesElectorales implements Comparator<ListeElectorale> {
// iki seçim listesinin sandalye sayısına göre karşılaştırılması
public int compare(ListeElectorale listeElectorale1,
ListeElectorale listeElectorale2) {
...
}
}
- 2. satır: Sınıf, Comparator<ListeElectorale> arayüzünü uygular
- 5-6. satırlar: compare yönteminin parametreleri ListeElectorale türündedir. Artık tür dönüştürme gereksizdir.
JDK 1.5 sürümü, başlangıçta yalnızca Object türündeki nesneleri işleyen JDK 1.4 sürümündeki çeşitli sınıflar ve arayüzler için jenerik sınıf/arayüz kavramını getirmiştir. Listeler, sözlükler vb. bunun bir örneğidir.
Biraz önce, listelerin sayısının bilinmediği için bunların bir dizide depolanamayacağını belirtmiştik. Bunlar, "nesne listesi" kavramını uygulayan bir ArrayList nesnesinde depolanabilir. Bu sınıf, Object türündeki nesneleri depolar. JDK 1.5 sürümünden itibaren, türlendirilmiş nesne listeleri mevcuttur. Bu nedenle, listeleri bir diziye aktarmadan önce saklamak için ArrayList<ListeElectorale> nesnesi kullanılır. Eğer bu dizi tListes olarak adlandırılmışsa, sıralama şu komutla gerçekleştirilir:
// listelerin sıralanması
Arrays.sort(tListes, new CompareListesElectorales());
burada CompareListesElectorales, Comparator<ListeElectorale> arayüzünü uygulayan sınıftır.
Yapılması gereken iş: Bu yeni şartnameleri dikkate alarak [Elections] uygulamasını yeniden yazın.
Eclipse projesi şu şekilde olabilir:
![]() |
[1]'in bir çalıştırma örneği şöyledir:
















