Kurucular (constructors), UML sınıf diyagramı, nesne dizileri
Nesneyi doğduğu anda hazırlayan kurucular, varsayılan kurucu kuralı, kurucu aşırı yükleme, UML sınıf diyagramını okuma ve çizme, nesneleri dizide ve ArrayList'te tutma. Final yazma sorularının iskeleti.
Geçen hafta nesneyi önce new ile boş oluşturup sonra set metotlarıyla doldurdun. Bu her nesne için birkaç satır demek ve bir alanı set etmeyi unutursan nesne yarım kalır. Kurucu (constructor) bu işi nesnenin doğduğu anda yapar. Bu hafta ayrıca sınıfları kâğıda çizmenin standart yolunu (UML sınıf diyagramı) ve çok sayıda nesneyi dizide ya da ArrayList’te tutmayı öğreneceksin.
Altın kurallar:
- Kurucunun adı sınıfın adıdır ve dönüş tipi yoktur.
- Hiç kurucu yazmazsan Java parametresiz bir tane ekler; bir tane yazarsan eklemez.
- Kurucular da overload edilebilir. Hangisinin çalışacağını argümanlar belirler.
- UML’de
-private,+public; tip isimden sonra gelir. - Nesne dizisi oluşturmak nesne oluşturmaz. Her eleman için ayrı
new.
Kurucu (constructor)
class Student {
private String name;
private double gpa;
public Student(String n, double g) { // dönüş tipi yok
name = n;
setGpa(g); // doğrulama setter'da
}
public Student(String n) { // ikinci kurucu (overloading)
name = n;
}
public String getName() { return name; }
public double getGpa() { return gpa; }
public void setGpa(double g) {
if (g >= 0.0 && g <= 4.0) gpa = g;
}
}
Student s1 = new Student("Deniz", 3.2);
Student s2 = new Student("Ece");
System.out.println(s1.getName() + " " + s1.getGpa());
System.out.println(s2.getName() + " " + s2.getGpa());
Student s3 = new Student("Can", 5.7);
System.out.println(s3.getName() + " " + s3.getGpa());
Deniz 3.2
Ece 0.0
Can 0.0
new Student("Deniz", 3.2)önce nesne için yer açar, alanları varsayılana koyar, sonra iki parametreli kurucuyu çalıştırır.- s2 tek parametreli kurucuyla oluştu; gpa’ya dokunulmadığı için 0.0.
- s3’te 5.7 aralık dışı; kurucu setter’ı çağırdığı için reddedildi. Kurucuda doğrudan
gpa = g;yazsaydın geçersiz değer içeri girerdi.
Çalışma sırası
class Book {
private String title;
private int pages = 100; // alan başlangıç değeri
public Book(String t) {
System.out.println("constructor: pages=" + pages);
title = t;
pages = 250;
}
public String describe() { return title + " " + pages; }
}
// main: Book bk = new Book("Java"); System.out.println(bk.describe());
constructor: pages=100
Java 250
Sıra: alanlar varsayılan değeri alır → alan tanımındaki başlangıç değerleri atanır (pages = 100) → kurucunun gövdesi çalışır.
Varsayılan kurucu kuralı
Sınıfa hiç kurucu yazmadıysan Java görünmez, boş, parametresiz bir varsayılan kurucu (default constructor) ekler. Geçen haftaki new Account() bu yüzden çalışıyordu. Ama tek bir kurucu yazdığın an bu ekleme yapılmaz:
class Car {
private String model;
public Car(String m) { model = m; }
}
// main: Car c = new Car();
Main.java:7: error: constructor Car in class Car cannot be applied to given types;
Car c = new Car();
^
required: String
Hem new Car() hem new Car("Egea") istiyorsan iki kurucuyu da kendin yazarsın.
TUZAK · kurucuya void yazmak.
public void Pen(String c)bir kurucu değil, adı sınıfla aynı olan sıradan bir metottur. Sınıfta gerçek kurucu kalmadığı içinnew Pen("red")derlenmez (required: no arguments),new Pen()ise derlenir ama color null kalır.
UML sınıf diyagramı
UML (Unified Modeling Language), bir sınıfı koda dökmeden önce kâğıt üstünde göstermenin standart yolu. Sınavda iki yönlü sorulur: “Bu diyagramın Java kodunu yaz” ya da “Bu sınıfın diyagramını çiz”.
+--------------------------------------------+
| Student | ← sınıf adı
+--------------------------------------------+
| - name : String | ← alanlar (attributes)
| - gpa : double |
+--------------------------------------------+
| + Student(n : String, g : double) | ← kurucular
| + Student(n : String) |
| + getName() : String | ← metotlar (operations)
| + getGpa() : double |
| + setGpa(g : double) : void |
+--------------------------------------------+
| UML | Java | Anlamı |
|---|---|---|
- name : String | private String name; | private alan |
+ getName() : String | public String getName() | public metot, String döndürür |
+ setGpa(g : double) : void | public void setGpa(double g) | parametre adı : tipi |
+ Student(n : String) | public Student(String n) | kurucu, dönüş tipi yazılmaz |
Diyagramdan kod yazarken sırayla git: önce sınıf başlığı, sonra her - satırı için bir private alan, sonra her + satırı için bir public metot başlığı ve gövdesi. Kodu diyagrama çevirirken ters yönde: alanları üst bölmeye, kurucuları ve metotları alt bölmeye yaz. getter ve setter’ları atlama; diyagramda görünmeleri gerekir.
Çevirirken iki şeye dikkat: UML’de tip isimden sonra gelir (name : String), Java’da önce (String name). Metodun dönüş tipi UML’de en sonda, Java’da adın önünde.
Nesne dizileri
Student[] group = new Student[3];
System.out.println(group[0]);
group[0] = new Student("Ali", 2.8);
group[1] = new Student("Bora", 3.6);
group[2] = new Student("Cem", 3.1);
double sum = 0;
for (Student s : group) sum += s.getGpa();
System.out.printf("%.2f%n", sum / group.length);
System.out.println(best(group).getName());
null
3.17
Bora
group ──► [ ref | ref | ref ]
│ │ │
▼ ▼ ▼
Ali Bora Cem (her biri ayrı bir new)
new Student[3] bir dizi oluşturur ama içine hiç Student koymaz: üç null referans. Her eleman için ayrıca new Student(...) gerekir. Dolu olmayan bir elemanın metodunu çağırırsan:
Student[] partial = new Student[2];
partial[0] = new Student("Z", 1.0);
for (Student s : partial) System.out.println(s.getName());
Z
NullPointerException
İkinci eleman null olduğu için ikinci turda çöktü. Dizi tam dolu değilse döngüde if (s != null) kontrolü yap.
best metodu max kalıbının nesne hali; soru bankasında tam kodu var. Fark şu: en büyük değeri değil, o değere sahip nesneyi tutuyoruz ve onu döndürüyoruz.
ArrayList ile nesneler
Kaç nesne olacağı belli değilse ArrayList daha rahat:
class Product {
private String name;
private double price;
private int quantity;
public Product(String n, double p, int q) { name = n; price = p; quantity = q; }
public String getName() { return name; }
public double getPrice() { return price; }
public int getQuantity() { return quantity; }
public void setQuantity(int q) { if (q >= 0) quantity = q; }
public double subtotal() { return price * quantity; }
}
public static Product findByName(ArrayList<Product> items, String name) {
for (Product p : items) {
if (p.getName().equals(name)) return p;
}
return null; // bulunamadı
}
// main içinde:
ArrayList<Product> cart = new ArrayList<>();
cart.add(new Product("Kalem", 12.5, 4));
cart.add(new Product("Defter", 40.0, 2));
cart.add(new Product("Silgi", 7.5, 3));
double total = 0;
for (Product p : cart) total += p.subtotal();
System.out.println(total);
System.out.println(findByName(cart, "Defter").getPrice());
System.out.println(findByName(cart, "Cetvel"));
cart.remove(0);
System.out.println(cart.size() + " " + cart.get(0).getName());
152.5
40.0
null
2 Defter
Nesne aramada isimler equals ile karşılaştırılır. Bulunamayınca int dizilerdeki -1’in karşılığı null döndürmektir. Çağıran taraf null dönebileceğini bilip kontrol etmeli.
Sık yapılan hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
| Kurucunun dönüş tipi void | Dönüş tipi yazılmaz |
Kurucu yazsam da new X() her zaman çalışır | Parametresiz kurucuyu yazmadıysan çalışmaz |
Kurucu obj.Student(...) diye çağrılır | Sadece new Student(...) ile |
| Kurucuda doğrulama gereksiz | Setter’ı çağırarak doğrula |
UML’de name : String → Java name String | String name |
UML’de + private | + public, - private |
new Student[3] üç öğrenci oluşturur | Üç null referans |
| Nesne dizisinde her eleman dolu | Kontrol et: if (s != null) |
p.getName() == name ile ara | equals |
| Arama bulamazsa -1 döndür (nesnede) | null döndür |
Kendini test et
Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.
Point has two constructors: Point() sets x and y to 0, Point(int x0, int y0) stores the given values. What is printed?
Point pt = new Point(3, 4);
Point pt2 = new Point();
System.out.println(pt.getX() + pt.getY() + " " + pt2.getX());Cevabı göster
Argüman sayısına göre kurucu seçilir (overloading). pt.getX() + pt.getY() iki int: 3 + 4 = 7, sonra String birleştirme. pt2 parametresiz kurucuyla 0.
The Student(String n, double g) constructor calls setGpa(g), which accepts only values from 0.0 to 4.0. What is printed?
Student s = new Student("Mert", -1.0);
System.out.println(s.getGpa());Cevabı göster
Kurucu doğrulamayı setter'a bırakıyor: -1.0 reddedilir, gpa varsayılan 0.0'da kalır. Doğrulamayı tek yerde (setter) yazıp kurucudan çağırmak iyi bir alışkanlık.
What is printed?
class Tracer {
private int value;
public Tracer(int v) {
value = v * 2;
System.out.println("built " + value);
value++;
}
public int getValue() { return value; }
}
// in main:
Tracer tr = new Tracer(5);
System.out.println(tr.getValue());Cevabı göster
11
new Tracer(5) kurucuyu çalıştırır: value = 10, built 10 basılır, value 11 olur. Sonra getValue 11 döndürür. Kurucu sıradan bir metot gibi satır satır çalışır.
What is printed?
Student[] arr = new Student[4];
arr[1] = new Student("A", 2.0);
arr[3] = new Student("B", 3.0);
int created = 0;
for (Student s : arr) if (s != null) created++;
System.out.println(created + " " + arr.length);Cevabı göster
new Student[4] dört referans yeri açar, hepsi null; hiçbir Student nesnesi oluşturmaz. Sadece iki tanesine new ile nesne konuldu. Dizinin uzunluğu yine 4.
What is printed?
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("X", 2.5));
list.add(new Student("Y", 3.5));
list.add(new Student("Z", 3.0));
int count = 0;
for (Student s : list) if (s.getGpa() >= 3.0) count++;
System.out.println(count + " " + list.get(1).getName());Cevabı göster
GPA'sı 3.0 ve üstü olanlar Y (3.5) ve Z (3.0): 2. list.get(1) bir Student döndürür; üzerinden doğrudan .getName() çağrılabilir: Y.
Product(String n, double p, int q) stores name, price and quantity; subtotal() returns price * quantity. What is printed?
Product pr = new Product("Su", 5.0, 3);
pr.setQuantity(pr.getQuantity() + 2);
System.out.println(pr.subtotal());Cevabı göster
Miktar 3 + 2 = 5 olur. 5.0 * 5 = 25.0 (price double olduğu için sonuç double).
What is printed?
Student a = new Student("Tan", 2.0);
Student[] two = {a, a};
two[0].setGpa(3.9);
System.out.println(two[1].getGpa() + " " + a.getGpa());Cevabı göster
Dizinin iki elemanı da aynı nesneye referans. Hangi yoldan değiştirirsen değiştir tek bir nesne var: üçü de 3.9 görür.
Account2(String o, double b) sets the balance; withdraw subtracts only if amount > 0 && amount <= balance, otherwise prints Insufficient funds. What is printed?
Account2 acc = new Account2("Deniz", 100);
acc.withdraw(-50);
acc.withdraw(30);
acc.withdraw(500);
System.out.println(acc.getBalance());Cevabı göster
Insufficient funds
70.0
-50 pozitif değil → mesaj. 30 geçerli → 70. 500 > 70 → mesaj. Kurucuya int 100 verildi ama parametre double olduğu için genişletildi; bakiye 70.0 basılır.
Class Car has only the constructor public Car(String m). Does Car c = new Car(); compile?
Cevabı göster
Java parametresiz varsayılan kurucuyu (default constructor) sadece sınıfta hiç kurucu yoksa kendisi ekler. Bir kurucu yazdığın an bu hediye kalkar. new Car() için parametresiz kurucuyu kendin yazmalısın.
What is wrong with this class? What happens with new Pen("red")?
class Pen {
private String color;
public void Pen(String c) { color = c; }
}Cevabı göster
void makes it a method, not a constructor; new Pen("red") does not compileKurucunun dönüş tipi yoktur, void bile yazılmaz. void Pen(...) sınıfla aynı adı taşıyan sıradan bir metot olur. Sınıfta gerçek kurucu kalmadığı için Java parametresiz varsayılan kurucuyu ekler; new Pen("red") hatası: required: no arguments.
Read the UML class diagram and write the class header, the fields and the constructor in Java.
+----------------------------------------+
| Course |
+----------------------------------------+
| - code : String |
| - credits : int |
+----------------------------------------+
| + Course(code : String, credits : int) |
| + getCode() : String |
| + getCredits() : int |
+----------------------------------------+Cevabı göster
- private, + public. UML'de tip isimden sonra iki noktayla yazılır; Java'da önce yazılır. Dönüş tipi parantezden sonra gelir.public class Course { private String code; private int credits; public Course(String c, int cr) { code = c; credits = cr; } public String getCode() { return code; } public int getCredits() { return credits; }}
Write a static method best(Student[] list) that returns the student with the highest GPA (assume the array is full and not empty).
Cevabı göster
Max kalıbının nesne hali: en büyük değeri değil, en büyük değere sahip nesneyi tutuyoruz. Dönüş tipi Student.public static Student best(Student[] list) { Student top = list[0]; for (Student s : list) { if (s.getGpa() > top.getGpa()) top = s; } return top;}Test: Ali 2.8, Bora 3.6, Cem 3.1 → best(group).getName() = Bora.
Doğrulama: Tüm çıktılar JDK 26 ile çalıştırıldı (verify/SEN1001/W11.java ve W11b.java; Student, Book, Product, Point, Tracer, Account2, Course ve Pen sınıfları). Kurucu hataları verify/SEN1001/err/ctor/ altında javac ile alındı.