SEN1001 · 11. hafta · Classes and Objects II

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.

constructordefault constructorno-argument constructorconstructor overloadinginitializationUML class diagramattributeoperationvisibility (+ / -)array of objectsArrayList of objectsnull element

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:

  1. Kurucunun adı sınıfın adıdır ve dönüş tipi yoktur.
  2. Hiç kurucu yazmazsan Java parametresiz bir tane ekler; bir tane yazarsan eklemez.
  3. Kurucular da overload edilebilir. Hangisinin çalışacağını argümanlar belirler.
  4. UML’de - private, + public; tip isimden sonra gelir.
  5. 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çin new 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                |
+--------------------------------------------+
UMLJavaAnlamı
- name : Stringprivate String name;private alan
+ getName() : Stringpublic String getName()public metot, String döndürür
+ setGpa(g : double) : voidpublic 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üşünceDoğrusu
Kurucunun dönüş tipi voidDönüş tipi yazılmaz
Kurucu yazsam da new X() her zaman çalışırParametresiz kurucuyu yazmadıysan çalışmaz
Kurucu obj.Student(...) diye çağrılırSadece new Student(...) ile
Kurucuda doğrulama gereksizSetter’ı çağırarak doğrula
UML’de name : String → Java name StringString name
UML’de + private+ public, - private
new Student[3] üç öğrenci oluştururÜç null referans
Nesne dizisinde her eleman doluKontrol et: if (s != null)
p.getName() == name ile araequals
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ç.

Soru 1kolay

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
7 0

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.

Soru 2orta

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
0.0

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.

Soru 3kolay

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
built 10
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.

Soru 4orta

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
2 4

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.

Soru 5kolay

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
2 Y

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.

Soru 6kolay

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
25.0

Miktar 3 + 2 = 5 olur. 5.0 * 5 = 25.0 (price double olduğu için sonuç double).

Soru 7zor

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
3.9 3.9

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.

Soru 8orta

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
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.

Soru 9orta

Class Car has only the constructor public Car(String m). Does Car c = new Car(); compile?

Cevabı göster
No: constructor Car cannot be applied to given types (required: String)

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.

Soru 10zor

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 compile

Kurucunun 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.

Soru 11orta

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
class Course { private String code; private int credits; public Course(String c, int cr) { code = c; credits = cr; } ... }

- 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; }}

Soru 12zor

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
Student top = list[0]; for (Student s : list) if (s.getGpa() > top.getGpa()) top = s; return top;

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ı.

Deftere not kartı

Kurucu: sınıfla AYNI ad, dönüş tipi YOK (void de yok), new ile otomatik çağrılır public Student(String n, double g) { name = n; setGpa(g); } Hiç kurucu yazmazsan Java boş parametresiz kurucu ekler; bir tane yazarsan EKLEMEZ Kurucu overloading: Point() ve Point(int, int) argümanlara göre seçilir Alan başlangıç değeri (pages = 100) kurucudan ÖNCE atanır void Pen(...) → metot olur, kurucu DEĞİL Doğrulamayı setter'da yaz, kurucudan setter'ı çağır UML: Sınıf adı / alanlar / metotlar (3 bölme) - private + public UML alan: - name : String metot: + getName() : String + setAge(a : int) : void Student[] g = new Student[3]; → 3 null referans, nesne YOK; her biri için new null eleman üzerinden metot → NullPointerException ArrayList<Student> list; list.add(new Student(...)); list.get(i).getName() Nesne arama: if (p.getName().equals(name)) return p; bulamazsan return null;