---
title: 'Paketler ve İçe Aktarım'
source: 'https://academia.sh/tr/kurslar/java-temelleri/paketler-ve-ice-aktarim'
course: 'Java Temelleri'
language: tr
updated: '2026-08-17T18:09:39+00:00'
license: 'CC BY-SA 4.0'
---

# Paketler ve İçe Aktarım

İçe aktarım bir yükleme yönergesi değil bir kısaltma kuralıdır: aynı program içe aktarımla ve tam nitelikli adla yazıldığında üretilen sınıf dosyaları bayt bayt aynıdır, statik içe aktarım da hiçbir adım eklemez; buna karşılık paket adı dosyayı değiştirir ve iki ad aynı kısaltmaya sığmaz.

Önceki ders bir sınıfın ne zaman ve hangi sırayla çalıştığını ölçtü: giriş noktası dört
koşulu birden sağlayan tek bir imzaydı, sınıf düzeyi başlatma yalnız bir kez ve ilk
kullanımda çalışıyordu, ve kaynakta yazılmayan üyeler sınıf dosyasında duruyordu. Ama sanal
makinenin o sınıfı **nasıl bulduğu** hiç sorulmadı.

İlk derste bir ayrıntı geçmişti: sınıf dosyası çağıracağı tipi adıyla taşıyor ve bu ad tam
biçimindeydi. Oysa kaynakta `List` yazmak yetiyor. Kısa ad ile tam ad arasındaki fark bir
yerde kapanmak zorunda — bu ders o yerin neresi olduğunu ölçer. Soru şudur: içe aktarımlı
yazım ile tam nitelikli yazım **ayrı sınıf dosyaları** mı üretiyor, yoksa aynısını mı?

## Ad Alanı, Tam Nitelikli Ad, İçe Aktarım

Java'da bir sınıfın gerçek adı yazdığımız kısa ad değildir. Sınıflar **paketlere (package)**
konur ve bir sınıfın **tam nitelikli adı (fully qualified name)** paket adı ile kısa adın
birleşimidir. Paket, adların çakışmasını önleyen bir **ad alanıdır (namespace)**: iki ayrı
paketteki iki `Proxy` ayrı sınıflardır, çünkü tam adları ayrıdır.

**İçe aktarım (import)** bu tam adı her seferinde yazmaktan kurtaran bir bildirimdir. Adı
yanıltıcıdır: hiçbir şey "içeri aktarılmaz", hiçbir dosya yüklenmez, hiçbir kod
kopyalanmaz. Bildirim yalnız derleyiciye şunu söyler — bu dosyada `List` yazdığımda
`java.util.List` kastediyorum.

Bazı adlar bu bildirimi hiç gerektirmez. Dilin çekirdek paketindeki sınıflar — `String`,
`Object`, `Math` gibi — her kaynak dosyada kısa adlarıyla yazılabilir; o paket her dosyaya
kendiliğinden açıktır. Kaynakta hiçbir içe aktarım görünmemesi bu yüzden "hiçbir dış sınıf
kullanılmıyor" demek değildir. Kısaltmanın var olması ile bildirimin yazılmış olması ayrı
şeylerdir, ve bu ders ikisinin de sınıf dosyasında ne bıraktığını sorar.

JavaScript ve Python müfredatları modül sistemini ve paket yapısını kendi kurslarında kurdu;
oradaki kavramlar burada tekrarlanmaz. Bu dersin sorduğu şey ayrıdır ve ölçülebilir: **ad
çözümlemesi sınıf dosyasında bir iz bırakıyor mu?** Aynı biçimde Programlama Temelleri
kursunda kurulan kapsam ve gölgeleme de tekrarlanmaz; burada ölçülen, bir adın hangi aşamada
tam biçimine kavuştuğudur.

## Ölçüm Çekirdeği

Bu derste sayılan şey ne komut ne üyedir: karşılaştırılan şey sınıf dosyasının **ham
baytlarıdır**. Çekirdek bir kaynağı derler, çıkan dosyayı olduğu gibi okur, ve iki yardımcı
bilgi verir — dosyanın taşıdığı tam nitelikli ad ile bir yöntem için kaydedilmiş satır
numarası.

- **CZ11** — Karşılaştırılan kaynaklar **aynı satır düzenini** taşır. Sınıf dosyası satır
  numarası kaydeder; düzen sabit tutulmazsa karşılaştırma ad yazımını değil satır düzenini
  ölçer. Bu yüzden ölçülen kaynaklar tek satıra yazılmıştır.
- **CZ12** — Karşılaştırma sınıf dosyasının bütün baytları üzerinde yapılır; hiçbir alan
  dışarıda bırakılmaz.
- **CZ13** — Derlenmeyen kaynak "derlenmedi" olarak yazılır; derleyicinin ürettiği hata metni
  basılmaz, çünkü ölçülen şey metnin kendisi değil derlemenin sonucudur.
- **CZ14** — Dosya adı kısa sınıf adından, dizin ise paket adından üretilir; ölçüm hiçbir
  gerçek yolu basmaz.
- **CZ15** — Ölçüm ortama bağlı hiçbir veri okumaz; sayılan tek şey bayt sayısı, satır
  numarası ve derlemenin sonucudur.

```java
// Olcek.java — sınıf dosyasının ham baytları, taşıdığı ad ve kaydettiği satır numarası
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.classfile.*;
import java.lang.classfile.instruction.LineNumber;
import java.nio.file.*;
import java.util.spi.ToolProvider;

class Olcek {
    static byte[] derle(String kaynak, String sinif) throws Exception {
        Path d = Files.createTempDirectory("olcek");
        Path k = d.resolve(sinif.substring(sinif.lastIndexOf('.') + 1) + ".java");
        Files.writeString(k, kaynak);
        PrintWriter bos = new PrintWriter(Writer.nullWriter());
        if (ToolProvider.findFirst("javac").orElseThrow()
                .run(bos, bos, "-d", d.toString(), k.toString()) != 0)
            throw new IllegalStateException("derlenmedi: " + sinif);
        return Files.readAllBytes(d.resolve(sinif.replace('.', '/') + ".class"));
    }

    static String ad(byte[] b) { return ClassFile.of().parse(b).thisClass().asInternalName(); }

    static int satir(byte[] b) {
        for (MethodModel m : ClassFile.of().parse(b).methods())
            if (m.methodName().equalsString("uzunluk"))
                for (CodeElement e : m.code().orElseThrow())
                    if (e instanceof LineNumber ln) return ln.line();
        return -1;
    }

    static String dene(String kaynak, String sinif) {
        try { derle(kaynak, sinif); return "derlendi"; }
        catch (Exception e) { return "derlenmedi"; }
    }
}
```

## İçe Aktarım Sınıf Dosyasında İz Bırakmıyor

Aynı sınıfın dört yazımı derlenir. Birincisi içe aktarım kullanır, ikincisi tam nitelikli ad
yazar, üçüncüsü hiç kullanılmayan bir içe aktarım daha ekler, dördüncüsü birincinin aynısıdır
ama içe aktarımı alt satıra alır. İlk üçü tek satırdır ve bu bilinçlidir — dördüncüsü niçin
gerektiğini birazdan söyleyecek.

```java
// Ana.java — içe aktarım sınıf dosyasında iz bırakıyor mu
import java.util.Arrays;

public class Ana {
    static String kaynak(String onek, String tip) {
        return onek + "class Sayac { static int uzunluk(" + tip + " l) { return l.size(); } }\n";
    }

    public static void main(String[] args) throws Exception {
        byte[] kisa = Olcek.derle(kaynak("import java.util.List; ", "List"), "Sayac");
        byte[] tam = Olcek.derle(kaynak("", "java.util.List"), "Sayac");
        byte[] fazla = Olcek.derle(
                kaynak("import java.util.List; import java.util.ArrayList; ", "List"), "Sayac");
        byte[] altSatir = Olcek.derle("import java.util.List;\n" + kaynak("", "List"), "Sayac");
        System.out.printf("%-24s %4d bayt  satir %d  ad %s%n",
                "ice aktarimli yazim", kisa.length, Olcek.satir(kisa), Olcek.ad(kisa));
        System.out.printf("%-24s %4d bayt  satir %d  ad %s%n",
                "tam nitelikli yazim", tam.length, Olcek.satir(tam), Olcek.ad(tam));
        System.out.printf("%-24s %4d bayt  satir %d%n",
                "kullanilmayan ek ile", fazla.length, Olcek.satir(fazla));
        System.out.printf("%-24s %4d bayt  satir %d%n",
                "ice aktarim alt satirda", altSatir.length, Olcek.satir(altSatir));
        System.out.println("ilk ikisi bayt bayt ayni  : " + Arrays.equals(kisa, tam));
        System.out.println("birinci ile ucuncu ayni   : " + Arrays.equals(kisa, fazla));
        System.out.println("birinci ile dorduncu ayni : " + Arrays.equals(kisa, altSatir));
    }
}
```

```
ice aktarimli yazim       304 bayt  satir 1  ad Sayac
tam nitelikli yazim       304 bayt  satir 1  ad Sayac
kullanilmayan ek ile      304 bayt  satir 1
ice aktarim alt satirda   304 bayt  satir 2
ilk ikisi bayt bayt ayni  : true
birinci ile ucuncu ayni   : true
birinci ile dorduncu ayni : false
```

İlk iki dosya **bayt bayt aynıdır**. Kaynaklardan biri `List`, öbürü `java.util.List` yazıyor
ve ikisi tek bir bayt farkla bile ayrılmıyor. Bunun anlamı kesindir: **içe aktarım sınıf
dosyasında hiçbir iz bırakmaz.** Sınıf dosyası zaten tam nitelikli adı taşır — kısa yazım,
derleyicinin o tam adı bulmasını sağlayan bir kuraldan ibarettir. Ad çözümlemesi derleme
zamanında biter; çalışma zamanına içe aktarım diye bir şey ulaşmaz. Aynı sonucun tersi de
doğrudur: tam nitelikli yazmak bir ek yük getirmez, çünkü kısaltılan şey yalnız kaynak
metindir.

Üçüncü satır aynı sonucu bir kez daha veriyor. Hiç kullanılmayan bir içe aktarım eklendiğinde
dosya yine aynıdır. Kullanılmayan bir bildirim bir ağırlık değildir, çünkü kullanılan
bildirim de bir ağırlık değildir: ikisinin de karşılığı sıfır adımdır.

Dördüncü satır ölçümün kendi denetimidir. İçe aktarım alt satıra alındığında dosya **aynı boyda**
kalıyor ama artık bayt bayt aynı değil, ve ayrımın nerede olduğu görünüyor: kaydedilen satır
numarası **1** yerine **2**. Yani sınıf dosyası kaynağın her şeyine kayıtsız değildir — satır
düzenini kaydeder. "İz bırakmıyor" iddiası bu yüzden gevşek bir iddia olamaz; ancak düzen
sabit tutulduğunda ölçülen şey ad yazımı olur. Karşı örneği olmayan bir eşitlik iddiası neyi
ölçtüğünü söylemiş sayılmaz.

## Paket Adı Dosyayı Değiştirir

İçe aktarım iz bırakmıyorsa, paket bildirimi de bırakmaz mı? İkisi de dosyanın başında duran
birer satırdır. Ölçüm ayrı yanıt verir.

```java
// Paket.java — paket adı sınıf dosyasını değiştiriyor mu
public class Paket {
    static final String GOVDE =
            "class Sayac { static int uzunluk(java.util.List l) { return l.size(); } }\n";

    public static void main(String[] args) throws Exception {
        byte[] paketsiz = Olcek.derle(GOVDE, "Sayac");
        byte[] paketli = Olcek.derle("package depo; " + GOVDE, "depo.Sayac");
        System.out.println("paketsiz: " + paketsiz.length + " bayt, ad " + Olcek.ad(paketsiz));
        System.out.println("paketli : " + paketli.length + " bayt, ad " + Olcek.ad(paketli));
    }
}
```

```
paketsiz: 304 bayt, ad Sayac
paketli : 309 bayt, ad depo/Sayac
```

Paket bildirimi eklendiğinde dosya **beş bayt** büyüyor ve taşıdığı ad `Sayac` yerine
`depo/Sayac` oluyor. Eklenen önek tam olarak beş karakterdir. Sınıf dosyası adı bir metin
olarak taşıdığına göre büyüme de o metnin büyümesidir.

Ayrım şuradan gelir: **içe aktarım kaynağı yazan tarafın kolaylığıdır, paket ise sınıfın
kimliğidir.** Birincisi bir dosyada geçerlidir ve dosyayla biter; ikincisi sınıfın adının
parçasıdır ve onunla birlikte her yere gider. Aynı gövdeden iki ayrı sınıf çıkmıştır, çünkü
tam nitelikli adları ayrıdır.

Ölçümün kendisi ikinci bir şeyi daha kanıtlıyor. Çekirdek, derlenmiş dosyayı ararken yolu
tam nitelikli addaki noktaları bölü işaretine çevirerek kuruyor; `depo.Sayac` ölçümü
başarıyla okunduğuna göre derleyici o dosyayı bir `depo` dizininin altına yazmıştır. Paket bir
isimlendirme sözleşmesi değildir: hem adın parçasıdır hem de sınıfın nerede aranacağını
belirler. Kaynakta tek bir sözcük olarak duran bildirim, dosya düzeninde bir dizin olarak
karşılık bulur.

## Sınırlayıcı Ölçüm: Sıfır Adım, Sıfır Kural Değil

Kısaltmanın bir biçimi daha var. **Statik içe aktarım (static import)** bir sınıfın statik
üyesini de kısa adıyla yazdırır: `Math.max` yerine yalnız `max`. Bu da sıfır adım mı ekliyor,
ve kısaltmanın hiç mi bedeli yok?

```java
// Statik.java — statik içe aktarım ve ad çakışması
import java.util.Arrays;

public class Statik {
    static String kaynak(String onek, String cagri) {
        return onek + "class Enb { static int enb(int a, int b) { return " + cagri + "(a, b); } }\n";
    }

    public static void main(String[] args) throws Exception {
        byte[] tam = Olcek.derle(kaynak("", "Math.max"), "Enb");
        byte[] statik = Olcek.derle(kaynak("import static java.lang.Math.max; ", "max"), "Enb");
        System.out.println("Math.max yazimi      : " + tam.length + " bayt");
        System.out.println("statik ice aktarimli : " + statik.length + " bayt");
        System.out.println("bayt bayt ayni       : " + Arrays.equals(tam, statik));
    }
}
```

```
Math.max yazimi      : 274 bayt
statik ice aktarimli : 274 bayt
bayt bayt ayni       : true
```

Statik içe aktarım da hiçbir adım eklemez; iki dosya bayt bayt aynıdır. Yöntemin sahibi olan
sınıfın adı çağrının içinde zaten yazılıdır, kısa yazım o adı yalnız kaynak metinden siler.

Buraya kadar her ölçüm sıfır verdi. Kısaltmanın hiç mi bedeli yok? Bedel çalışma zamanında
değil, derleme zamanında ödenir ve gerçektir. Aşağıdaki beş durum aynı iki sınıfı — iki ayrı
pakette bulunan, kısa adları aynı iki sınıfı — beş ayrı biçimde yazar.

```java
// Cak.java — ad çakışması hangi durumda derleme hatasıdır
public class Cak {
    public static void main(String[] args) {
        String[][] durum = {
            {"iki tam ad, kullanilmasa da",
             "import java.net.Proxy; import java.lang.reflect.Proxy; class Cakisma { }"},
            {"iki toplu ad, kullanilmadan",
             "import java.net.*; import java.lang.reflect.*; class Cakisma { }"},
            {"iki toplu ad, kullanilinca",
             "import java.net.*; import java.lang.reflect.*; class Cakisma { Proxy p; }"},
            {"tam ad + toplu ad, kullanilinca",
             "import java.net.Proxy; import java.lang.reflect.*; class Cakisma { Proxy p; }"},
            {"ice aktarimsiz, iki tam adla",
             "class Cakisma { java.net.Proxy a; java.lang.reflect.Proxy b; }"},
        };
        for (String[] d : durum)
            System.out.printf("%-32s %s%n", d[0], Olcek.dene(d[1], "Cakisma"));
    }
}
```

```
iki tam ad, kullanilmasa da      derlenmedi
iki toplu ad, kullanilmadan      derlendi
iki toplu ad, kullanilinca       derlenmedi
tam ad + toplu ad, kullanilinca  derlendi
ice aktarimsiz, iki tam adla     derlendi
```

Beş satır ad çözümlemesinin kuralını baştan sona veriyor. Birinci satır: iki sınıfı adlarıyla
tek tek içe aktarmak, o adlar **hiç kullanılmasa bile** derleme hatasıdır — kısaltma tablosu
kaynağın kendisinden önce kurulur ve bir kısa ad iki tam adı gösteremez. İkinci ile üçüncü
satır bunun karşıtını gösteriyor: paketin tamamını toplu biçimde içe aktarmak çakışmayı tek
başına doğurmuyor, hata ancak belirsiz ad **kullanıldığında** çıkıyor. Toplu içe aktarım bir
karar değil, bir arama listesidir.

Dördüncü satır sıralamayı söylüyor: adıyla yazılmış bir içe aktarım, toplu içe aktarımdan
**öncelikli** olduğu için belirsizlik doğmuyor. Beşinci satır ise sınırı çiziyor — iki sınıf
tam adlarıyla yazıldığında yan yana sorunsuz kullanılabiliyor. Yani ikisini birlikte kullanmak
yasak değildir, ikisini **aynı kısaltmaya sığdırmak** yasaktır.

Kursun ölçüsü buradan bir kez daha okunur. İlk derste eklenen adımın **olmadığı** bir durum
sabit katlamayla gösterilmişti; burada eklenen adımın olmadığı üç durum daha var ve üçünde de
bedeli ödeyen taraf derleyicidir. Bir biçimin çalışma zamanında hiçbir şeye mal olmaması, o
biçimin kuralsız olduğu anlamına gelmez.

Kursun ölçüsü buradan bir kez daha okunur. İlk derste eklenen adımın **olmadığı** bir durum
sabit katlamayla gösterilmişti; burada eklenen adımın olmadığı üç durum daha var ve üçünde de
bedeli ödeyen taraf derleyicidir. Bir biçimin çalışma zamanında hiçbir şeye mal olmaması, o
biçimin kuralsız olduğu anlamına gelmez.

## Özet

- Bir sınıfın gerçek adı tam nitelikli adıdır; paket bir ad alanıdır ve sınıf dosyası bu adı
  metin olarak taşır.
- İçe aktarımlı yazım ile tam nitelikli yazımın ürettiği sınıf dosyaları **bayt bayt
  aynıdır**; kullanılmayan bir içe aktarım da dosyayı değiştirmez. Ad çözümlemesi derleme
  zamanında biter.
- Sınıf dosyası kaynağın satır düzenini kaydeder: içe aktarım alt satıra alındığında dosya
  aynı boyda kalır ama artık aynı değildir, çünkü kayıtlı satır numarası 1 yerine 2 olur.
- Paket bildirimi dosyayı **değiştirir**: taşınan ad `Sayac` yerine `depo/Sayac` olur ve dosya
  eklenen önek kadar, beş bayt büyür.
- Statik içe aktarım da sıfır adım ekler; buna karşılık aynı kısa ada sahip iki sınıfı adıyla
  içe aktarmak, o adlar hiç kullanılmasa bile derleme hatasıdır. Toplu içe aktarımda hata
  ancak belirsiz ad kullanıldığında çıkar ve adıyla yazılmış içe aktarım önceliklidir.
- Kısaltmanın çalışma zamanındaki bedeli sıfırdır, derleme zamanındaki kuralı gerçektir: bir
  dosyada bir kısa ad tek bir tam adı gösterebilir, ama iki sınıf tam adlarıyla yan yana
  kullanılabilir.

## Sonraki Adım

Bu konu boyunca ölçülen şey hep **derleyicinin ne eklediği** oldu: bir adım, bir üye, bir ad.
Üçünde de karar derleme zamanında verildi ve çalışma zamanına yalnız sonucu ulaştı — hangi
sınıfın kastedildiği, sınıf dosyası yazılırken çoktan bellidir. Ad çözümlemesi derleme
zamanında bitiyorsa, **değerin kendisi** ne zaman belirleniyor? Sıradaki konu bunu ölçmeye
ilkel tiple sarmalayıcı arasındaki geçişten başlar: bir tam sayıyı bir sarmalayıcıya atamak
kaynakta tek bir eşittir işaretidir, sınıf dosyasında ise bir çağrı ve üretilen bir nesnedir.
