Java Nedir?

Bu konu ile ilgili sunuma buradan ukaşabilirsiniz. Ayrıca sunumu PDF dosyası olarak buradan indirebilirsiniz.

Java’nın ne olduğunu anlamanın en iyi yöntemi bence, Sun’ın, 1995’te, Java’nın ilk günlerinde  yayınlamış olduğu  ve halen http://java.sun.com/docs/overviews/java/java-overview-1.html adresinden ulaşılabilen, kısa ve tanıtıcı olan yazıyı okumaktır. Bu yazının hemen başında, 2. paragrafında şöyle bir cümle vardır:

Java: A simple, object-oriented, network-savvy, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, dynamic language.

Yani

Java: basit, nesne merkezli, ağlarda yetkin, yorumlanan, sağlam (gürbüz), güvenli, mimari olarak tarafsız, taşınabilen, yüksek başarımlı/performanslı, çok kanallı, dinamik bir dil.

Ufff bu ne? Bizim sektörümüzde bu kadar önemli ve etkileyici kelimeyi bir araya getirebilen başka ne vardır bilmiyorum. Java’nın, bu tanımdaki sıfatların hangisini ne kadar haiz olduğu tartışılır ama sonuçta bu tanım üzerinden gitmek, kanımca Java’yı anlaşılır kılmaktadır. Bu yüzden ben ilk öğrenenlere hep bu cümle üzerinden giderek Java’yı anlatmışımdır. Şimdi de öyle yapacağım ve bu özellikleri tek tek ele alacağım:

Basit: Doğrusu, Java o kadar da basit değildir. Aslında, Java’nın en temelde, ataları olarak görebileceğimiz C ve C++’ın sıkıntılı ve zorluk çıkaran taraflarının budanarak  tasarlandığını göz önüne aldığımızda, bu özelliğin “basit” (simple) yerine “daha basit” (simpler) şeklinde ifade edilmesinin daha uygun olacağını farkederiz. Evet Java, çıktığı yıllarda C ve C++’ın doldurmakta olduğu genel amaçlı uygulama geliştirme dili olma rolünü devralmak için, onlara göre daha basit, bu dillerin geliştiricilerine çıkardığı zorlukları çıkarmayan, çalışma zamanında (run-time) yol açtığı sıkıntıları önlemeyi amaçlayan bir dil olarak tasarlandı. Neydi bu Java’nın problemli olarak görüp ya hiç kapsamadığı ya da farklı bir şekilde ele aldığı noktalar?

  • Otomatik bellek yönetimi: Java zaten nesne merkezli olduğu için, çokça oluşturulan nesnelerin sistemin belleğini hızlıca doldurmaları sıkça görülen bir durumdur. Bu nesnelerin kullanımdan çıktıkları zaman sistem belleğine geri kazandırılmaları, Java’nın çöp toplayıcısı (garbage collector) sayesinde, otomatik olarak yapılır. Kullanılmayan nesneleri sistemin belleğine geri kazandırmayı otomatik olarak yapmayıp bunu geliştiricinin insiyatifine bırakan C++’da bellek kaçakları (memory leak) çok sıklıkla görülen bir problemdir. Zaten C++’a göre nesne kullanımını çok daha ön plana çıkaran Java’nın bellek yönetiminde böyle bir yöntem izlemesinin faydalarını en başından bu yana görmekteyiz.
  • Pointer kullanımı: Bellekteki nesnelerin adreslerini tutan pointerların, pointer aritmetiği gibi konulardan arındırılarak, sadece nesnelerin referansı haline getirilmeleri, bu konu ile alakalı gündeme gelen pek çok zorluğu ortadan kaldırmış ve Java’yı donanımdan daha uzakta bir noktaya yerleştirip, daha yüksek seviyeli (high-level) bir dil yapmıştır.
  • Operatör overloading: + ya da % gibi operatörlerin nerelerde nasıl kullanılabileceğinin daha tasarım zamanında, Java’yı tasarlayanlar tarafından belirlenip, bu operatörlerin geliştiriciler tarafından farklı şekillerde kullanılabilmesinin önüne geçilmesi, Java’yı kesinlikle çok daha basit kılmıştır.
  • Çoklu kalıtım (multiple inheritance) ve otomatik tip çevrimleri (automatic type conversion ya da type coercion) gibi irili ufaklı pek çok konu ya dil dışında tutulmuş ya da kullanıcısına sıkıntı çıkarmayacak şekilde dilin altyapısında çözülmüştür.

Görüldüğü gibi, Java, C ve C++’ın kullanıcılarına sağladığı ama aynı zamanda sıkıntılara da yol açan pek çok özelliği ya içinde barındırmamayı ya da derleyici (compiler) veya yorumlayıcı (interpreter) gibi yapıların içinde, konuyu çok da fazla geliştiricinin önüne getirmeden halletmeyi seçmiştir.

Bu seçimler daha sonra da ifade edileceği gibi Java’nın daha basit olmasından öte, dilin gerek derleme zamanında (compile time) gerek ise çalışma zamanında (run-time) daha sağlıklı çalışabilmesiyle alakalıdır. Bu yüzden mesela C/C++’ın otomatik olarak yaptığı tip çevrimlerinin daraltan tiplerinde (yani long gibi daha geniş bir tipten int gibi daha dar bir tipe gitme) Java’nın çevrimi otomatik yapmayıp, geliştiricinin insiyatifini istemesi ve çevirme (cast) operatörünü kullanmasını gerekli kılması, tamamen daha ihtiyatlı davranma tercihinden dolayıdır. Aynı konu Java’nın tipler konusunda çok daha hassas olmasında da ortaya çıkar. Bu anlamda Java, C/C++’a göre tip hiyerarşisine  ve aralarındaki ilişkilere önem veren (strongly-typed) bir dildir.

Özet olarak Java’da, dili daha sade ve rahat kullanılır yapmak için özellikle aşağı seviyeli (low-level) pek çok özelliği budanırken, gerekli mekanizmalar derleyici ve yorumlayıcı seviyesine indirilerek, belki çok daha karşmaşık bir altyapı oluşturulmuş ama öğrenim ve kullanım kolaylığı sağlanmıştır.

Tabi, C/C++ kültürünün çok yaygın olmadığı ülkemizde yukarıda anlatılanların ne kadar anlam ifade ettiği de tartışılır. Ama bütün bunların en azından Java’yı doğru bir şekilde değerlendirmede gerek tarihi bilgi gerek ise entellektüel tartışma açısından önemlidir.

Nesne merkezli: Kanımca Java’nın en önemli özelliği nesne-merkezli (object-oriented) olmasıdır. Nesne-merkezli olmak demek program mantığı açısından en temel soyutlama (abstraction) biriminin nesne olması demektir. Birazdan açıklanacağı gibi bu o kadar temel bir farktır ki, programlamaya yaklaşımınızı her yönüyle değiştirir. Dolayısıyla nesne-merkezli programlama bir paradigmadır. Benzer şekilde nesne-merkezli yanında, programlamaya, prosedürel (procedural),  fonksiyonel (functional) ya da mantıksal (logical) yaklaşımlar da vardır ve bütün bu yaklaşımlar da birer paradigma oluşturacak şekilde bir düşünce sistemine sahiptirler. Bu yaklaşımlar arasında en yaygın olan iki tanesi, nesne-merkezli ve prosedürel yaklaşımdır. Hatta nesne-merkezli dillerin hayatımıza bu kadar çok girmesinden önce en yaygın paradigma prosedürel olandı ve bu dünyanın en tipik temsilcisi olan dil de “C” idi. C gibi Pascal, Fortran, Cobol  gibi diller de prosedürel dünya içerisinde yer almakta olup halen yoğun bir şekilde kullanılmaktadırlar.

Nesne-merkezli yaklaşım ile prosedürel yaklaşım arasındaki en temel fark, procedürel bir dilin en temel soyutlama biriminin bir fonksiyon olmasına karşın, nesne-merkezli bir dilde bu birimin fonksiyondan nesne seviyesine çıkarılmış olmasıdır. Böyle bir farkın detaylı bir şekilde nelere mal olduğu bu yazının en azından şimdilik bir konusu olmamakla birlikte, bu iki yaklaşımın en tipik özelliklerini ifade etmek gereklidir.

Prosedürel dillerde probleme yaklaşım, dil yardımıyla bilgisayara verilecek olan ardışıl komutlarla olur. Bu ardışıl komutlar ki genel olarak statement olarak ifade edilir, bir yemeğin tarifindeki gibi sırayla ifade edilirler ve bilgisayar bunları yerine getirdiğinde problem çözülmüş olur. İşte bu yüzden bu sınıftaki dillere emreden anlamında imperative diller de denir. İlgili komutlar bir araya gelerek daha büyük bir komut birimi olan prosedürler oluşur.   Prosedür, farklı dillerde fonksiyon (function), metot (method), rutin (routine) sabrutin (subroutine) vb. kelimelerde adlandırılan bir kavram olup, Türkçe’de de bazen “yordam” olarak da ifade edilmektedir. (Biz bu yazılarda bu kavramları birbiri yerine geçecek şekilde kullanıyor olmakla birlikte nesne merkezli diller sözkonusu olduğunda metot demeyi tercih edeceğiz.) Prosedürler, değişken denen veri yapıları üzerinde çalışırlar ve çalışmalarının sonuçlarını yine bu veri yapılarında saklarlar.

Nesne merkezli diller de fonksiyonları ve değişkenleri bir araya getirirler fakat prosedürel dillerden en temel farkları, bir araya getirdikleri fonksiyon ve değişkenlerin, insan zihninin kendisine odaklandığı herhangi bir “şey”i betimlemesidir.  Dolayısıyla nesne merkezli diller bir problemi adım adım çözmeye odaklanmaz onun yerine o problemde var olan “şey”leri yani nesneleri bulup onları özellikleri ve davranışlarıyla betimlemeye çalışır. Nesne merkezli teori, fiziksel olsun ya da sadece zihinsel olsun, evrende var olan varlıkları bu yolla, oldukları gibi tanımlamak, aralarındaki ilişkileri doğru bir şekilde resmetmek ve dolayısıyla da bir problemi gerçekte olduğu gibi yazılım dünyasına aktarmak iddiasındadır.

Nesne merkezli bir dil olarak da Java, iş modellerimizi yazılıma aktarmakta, atası olan C ve C++’a göre çok daha başarılıdır.

Ağlarda yetkin: Ağlar, bilgi teknolojileri dünyasının en başından bu yana parçası olmakla beraber, hayatımıza bu girişi 90’lı yılların ilk yarısında başlayan Internet devrimiyle akıl almaz bir şekilde hızlanmıştır. Bu yılların Java’nın doğuş yılları olduğu gerçeği göz önüne alınırsa, Java’nın kendini neden ağlarda bu kadar yetkin kıldığının cevabı da ortaya çıkmış olur. Zaten Java’nın yaratıcısı olan Sun şirketinin de sloganı “The Network is the Computer” yani “Ağ Bilgisayardır”dır. Ağ yapılarıyla alakalı böyle bir vizyona sahip olan ve bunu geliştirmekte olduğu Unix sistemlerinde başarıyla uygulayan Sun’ın, Java’yı, 90’lı yıllarda hızla gelişmekte olan Internet ve web teknolojilerine uygun bir yapıda, ağlar üzerinde rahatça çalışabilecek ilk dil olarak kurgulaması da son derece tabidir.

Bu noktada Java’nın sadece en basit ve temel şekliyle soket programlamaya imkan vermekle kalmayıp, Web’in üzerinde çalıştığı HTTP ve HTTPS protokolları başta olmak üzere FTP ve Telnet gibi diğer protokolları, web servislerini, uzak nesnelere (remote objects)  ulaşmayı destekleyen protokolları rahatça kullanır kılmasından bahsetmek gereklidir. Java’nın nesne-merkezli yapısıyla, ağ programlamayı nesne seviyesine çıkarması ve örneğin uzak nesnelere rahatça ulaşıp onları yerel nesneler gibi görmesi, eskiden çok zaman alıcı olarak görülen bu işlerleri harcıalem hale getirmiştir.

Yorumlanan: Java yorumlanan bir dildir. Aslında bu, bu konudaki gerçeğin sadece bir yüzüdür. Çünkü Java hem derlenir (compiled) hem de yorumlanır (interpreted). Derlemek (compilation) aslında bir çevrim işidir, kodu bir formdan başka bir forma çevirmektir. Genelde de kaynak kodu, derleyici (compiler) tarafından üzerinde bulunulan platformun makina koduna çevirmeye denir öyle ki bu çevrim sonunda ortaya çıkan kod çalışabilen (executable) bir koddur. Yorumlanan dillerde böyle bir çevrim ancak çalışma zamanında ve yorumlayıcı (interpreter) tarafından yapılır.

Bu iki yaklaşımın farkları ve avantaj ve dezavantajları bu yazının konusu değildir. Fakat Java’nın neden hem derlenen hem de yorumlanan bir dil olduğunu ifade etmek gereklidir. “java” uzantılı bir dosyada bulunan Java kaynak kodu Java derleyicisi tarafından adına bytekod (bytecode) denen ve sanal bir makinanın (Java Virtual Machine ya da kısaca JVM) koduna çevrilir. Üretilen bytekodlar “class” uzantılı dosyalarda bulunurlar. JVM, her platform için ayrıdır ve genel olarak o platformu üreticileri tarafından geliştirilp piyasaya sunulur. Java’da derleme zamanında (compile-time) elde edilen bytekodlar her platform için standart ve aynıdır. Yani Java programcısı JVM için kod yazar. JVM ise bytekodları, çalışma zamanında (run-time) üzerinde bulunduğu platformun makina diline çevirir ve çalıştırır.

Böyle bir iki fazlı yaklaşım ne sağlar? Java programcısına, programlama yaparken, kodunun çalışacağı son ortamı bilmek zorunda olmama imkanı verir. Platformların temelde merkezi işlem birimi (CPU) ve diğer çevre birimlerinden oluşan donanım ile bu donanım üzerinde çalışan işletim sisteminden (OS) oluştuğu ve farklı platformların donanım ve yazılım yapılarının birbirlerinden çok farklı oldukları düşünüldüğünde, hem derlenen hem de yorumlanan bir yapıda olma ve bunu JVM isimli sanal bir yapı üzerinden gerçekleştirme, Java programcılarına, platformdan bağımsız kod yazma lüksünü vermektedir ki bu durum Java’nın bir diğer özelliğini, yani taşınabilir olmasını sağlar.

Taşınabilir: Java kodları herhangi bir platformdan bağımsız olarak yazılır ve çalıştırılır. Bu, Java kodlarının bir platformdan  diğerine herhangi bir değişiklik olmaksızın, hatta tekrar derlenmeksizin çalıştırılabilmesi imkanını verir. Bu durum, Java’nın platformlardandan bağımsız ve standartlar üzerine kurgulanmış yapısı sayesindedir.

Java’da kaynak kodları JVM için yazılır, çalışma-zamanı ortamı için değil. JSM, platform ile Java programcısı arasına girerek, programcının çalışma-zamanıyla platformu bilme zorunluluğunu ortadan kaldırır. JVM’ler aynı kodu farklı platformlar üzerinde çalışma-zamanında yorumlayarak çalıştırırlar. Bu noktada JVM, programcıya bakan tarafı Java standartları ve uygulama programlama arayüzleri (Application Programming Interface, API) ile oluşturulmuş ama diğer tarafı platform ile konuşan bir ara katman ya da adaptör olarak düşünülebilir.  Dolayısıyla, JVM’in Java kaynak kodlarıyla çalışma-zamanı platformu arasında bir katman oluşturması, Java kodlarını çalışma-zamanındaki platformdan bağımsız kılar.

Ayrıca, Java’nın yapısı, veri yapıları da dahil olmak üzere  tarifnameler (specification) ile belirlenir.. Dolayısıyla en temelde aynı Java kodu farklı platformlarda aynı davranışı gösterir. Java’yı oluşturan altyapıların tarifnamaleri, platformlara özel yapılar içermez ve hangi konuda nasıl davranması gerektiği detaylı bir şekilde açıklanır. Bu yüzden örneğin Java’nın en temel veri tiplerinden olan int verisinin bütün platformlarda 32 bittir ve aynı şekilde davranır. Aksi taktirde, Java da, C ve C++ dillerindeki gibi taşınabilirliği önleyen platforma özel yapılara sahip olurdu. Ayrıca C ve C++ gibi pek çok dil, tariflerindeki açık bırakılan noktalarda farklı ürünlerin farklı davranmaları sonucu platformlar arasında taşınamaz bir kod yapısına sahiptir.

Taşınabilirlik özelliği sayesinde, Java programcıları bilerek ya da bilmeyerek, dosya yollarındaki ayıraçları (“/”, “\” ya da “:” gibi) kodun içine gömmek gibi hatalar yapmadıkları sürece, bir kurumsal yazılımın, örneğin bir Unix platformundan Windows platformuna taşınması hiç bir tekrar derleme gerektirmeyecek ve sadece bir kaç saat içinde gerçekleştirilebilecektir. Java’nın ilk günlerinde bu durumu ifade eden slogan “Write Once, Run Anywhere” ya da WORA idi. Yani “Bir Kere Yaz, Heryerde Çalıştır”. Tabi umulmadık durumlarla karşılaşmamak için Java’cılar bu sloganı, daha ihtiyatlı olan “slogan “Write Once, Test Anywhere”e yani “Bir Kere Yaz, Heryerde Test Et”e çevirmişlerdir.

Sağlam: Sağlamlıktan kastedilen, kodun, çalışma zamanında oluşabilecek sıradışı durumlarda bile kırılmadan, göçmeden çalışmasına devam edebilme yeteneğidir. Java’nın standartlar üzerine kurulu ve bir sanal makina üzerinde çalışıyor olması, gerek derleme zamanında gerek ise çalışma zamanında pek çok kontrolu rahatça yapabilmesini sağlamaktadır. Örneğin C ve C++’ta çalışma zamanında en sık problem üreten konu olan, programcının belleği göstergeler (pointer) üzerinden açık adreslemeyle yönetmesi ve gösterge aritmetiği, Java’da tamamen JVM’in sorumluluğundadır. Java programcısının belleği yönetirken kullandığı göstergeler ki Java terminolojisinde referans (reference) olarak adlandırılır, sadece soyut göstergelerdir, Java programcısına sadece nesneye ve özellik ve davranışlarına ulaşma imkanı sağlar, daha ötesini değil. Java’nın tip yapılarına ayrı bir dikkat göstermesi, sıradışı durumları yönetmede programcıya ciddi sorumluluk yüklemesi gibi noktalar da çalışma-zamanı güvenirliğini arttırmak için dile konmuş mekanizmalardandır.

Güvenli: Java’nın ağ ortamlarında çalışmak üzere tasarlanmış olması, onun güvenlik konsunda daha dikaktli olmasını gerekli kılar. Bu sebeple Java en başından bu yana, JVM’de çalışan bytekodlar ile JVM’nın üzerinde çalıştığı sistemin dosya, soket vb. kaynakları arasındaki iletişimi iki yönde de kontrol etmek için gerekli mekanizmaları sağlamıştır. Java, gerek web üzerinden hizmet veren uygulamalara ve web servislerine gerek ise uzak nesnelere rol temelli erişim kontrolü (role-based access control, RBAC) yaklaşımıyla gerek tanım tabanlı (declarative) gerek ise API tabanlı erişim imkanı sağlamaktadır.

Java’nın ilk yıllarında zaman zaman duyulan Java Sanal Makina’sındaki güvenlik açıkları haberleri uzun süredir duyulmamakta olması Java’nın bu konuda da istenen seviyeye geldiğini göstermektedir.

Ayrıca Java’nın güvenlik konusunda sunduğu bileşenler son derce zengin olup her türlü şifrelemeye ya da HTTPS gibi güvenli protokolleri kullanmaya imkan tanımaktadır.

Mimari olarak tarafsız: Java, farklı mimarilere sahip pek çok platformun bulunduğu ortamlarda çalışmak için tasarlandığından, hiçbir mimari yapıya öncelik vermez ve hiç bir platforma özel yapılar içermez. Java’nın platformlar ile ilgili kabulleri, bütün platformalar tarafından genel kabul görmüş yapılarla ilgilidir. Dolayısıyla Java ile her türlü mimari yaklaşım kullanıalrak her çeşit platform üzerinde uygulama geliştirmek için vardır.

Yüksek performanslı: Pek tabi ki bu özellik ciddi bir açıklamaya muhtaçtır. Aksi taktirde Java’nın yüksek performanslı olması iddiası Fortran ya da C gibi dillerle yapılacak basit ve üstünkörü kıyaslarla çok kolayca çürütülebilecektir.

Öncelikle şunu ifade etmek gerekir ki nesne-merkezli diller kalıtım ve çok formlu yapıları destekledikleri için zaten prosedürel dillerin derleme zamanında yaptıkları pek çok işi çalışma zamanında yapmak durumundadırlar. Ayrıca Java, daha güvenli ve sağlam bir dil olmak adına sadece derleme zamanında değil çalışma zamanında da pek çok kontrol yapmaktadır. Tip kontrolleri bunun en güzel örneğidir. Ayrıca Java’nın platformdan bağımsız ve taşınabilir olması, onun bir sanal makina üzerinde çalışması ve çalışma zamanında yorumlanmasını gerekli kıldığından, çalışma zamanında ciddi bir handikapa sahip olacağı da açıktır. Bu ve benzeri sebeplerden dolayı Java, zaten tasarlanırken yapılan tercihlerin sonucu olarak zaten Fortran ya da C gibi hızlı olması beklenmemelidir. Fakat Java’nın yukarıda bahsedilen cinsten özellikleri, çalışma zamanında tatmin edici bir performansta erişmesinin önünde engel teşkil etmezler. Lakin pek tabi olarak, Java programcıları, performans konusunda diğer pek çok dilde program yazanlara göre daha bilgili ve uyanık olmalıdırlar. Nesne merkezli teorinin sınırları içinde kalarak olabildiğince az nesne oluşturmak (mesela bu amaçla sıkça değişen string nesneleri için String yerine StringBuffer kullanmak) , oluşturulan nesneye yapılan referansları işi bittiğinde nesneden koparmak vb. teknikleri uygulayarak, Java programcıları daha başından yazdıkların kodun performans yönünden sıkıntıda olmaması için çaba gösterirler. Bütün bu çabalara rağmen bir Java kod parçası halen istenilen performansta çalışmıyorsa tabi olarak ince ayara (tuning) tabi tutulur.

Öte taraftan şu da bilinmelidir ki bir sistemin performans ve ölçeklenirliği (scalability) o sistemde kullanılan dilden ziyade sistemin mimarisinin bir özelliği ve sonucudur. Yüksek performanslı olması istenen sistemler, mimari seviyede bu amacı sağlayacak yaklaşım ve tekniklerle tasarlanmalıdırlar. Tabi olarak böyle bir tasarım dil seviyesinde de pek çok yaklaşımı bünyesinde barındırabilecektir.

Çok kanallı: Kanal (thread) işlem/süreç (process) içerisinde bir akıştır, diğer bir ifade ile işlem içerisinde küçük bir işlemdir, işlemciktir. İşletim sistemi bir işlemi başlatdığında, belleğin bir kısmını ona tahsis eder ve kodunu belleğe yükler. İşletim sistemi CPU gibi sistem kaynaklarını pek çok işlem arasında devamlı surette paylaştırır. Bu paylaştırma çok hızlı yapıldığı için kullanıcı, aynı anda pek çok program çalışıyormuş izlenimini elde eder. Benzer paylaştırma, bir işlem içindeki pek çok işlemcik arasında da yapıldığında o işlem çok daha hızlı çalışacaktır, en azından kullanıcı nezninde öyle algılanacaktır. Hesaplamanın ana unsuru olan CPU’ların çok hızlandığı, hatta birden fazla çekirdeğe sahip CPU’ların yaygın hale geldikleri bir ortamda programlar çok kanallı yapıları daha sık ve etkin kullanmalıdırlar.  Çünkü kanallar, işlemlere göre çok daha hızlı oluşturulurlar. Ayrıca kanalların aralarında veri alışverişi çok kolaydır çünkü işlemlerin veri alanları kanallar tarafından paylaşılır. Bu paylaşım avataj olduğu gibi zaman zaman sıkıntılı durumlara da yol açabilmektedir.

Java’nın kanallar konusundaki yaklaşımı çok basittir; Java’ya başlayan herkes çok kısa sürede kanalları kullanır hale gelebilir. Hatta bir programcı eğer sunucu tarafında (server-side) çalışıyorsa, kendisi kanal oluşturmasa bile JVM’in oluşturduğu pek çok kanalın bulunduğunu bilmek ve buna göre davranmak zorundadır. Bu noktada Java’nın yaklaşımı, yüksek performanslı ve ölçeklenirlikli sistemler için çok kanallı yapılar şarttır ve iyi Java programcıları da kanalları çok etkin bir şekilde kullanır.

Dinamik: Bir Java programı çalışmaya başlarken, çalışması sırasında ihtiyaç duyacağı tiplerin hazır olmasına ihtiyacı yoktur. Program, ihtiaycı olan tipleri, içinde bulundukları .class dosyalarından çalışma zamanında, yeri geldikçe yükleyebilir. Buna dinamik yükleme (dynamic loading) denir. C gibi dillerde bütün yüklenecek kütüphane vb. öğeler bağlantı zamanında (linking time) hazır olmalıdırlar. Buna da statiktir bağlama (static linking) denir ve çalışma zamanından öncedir. Java’nın böyle bir özelliğe sahip olması, onun ağ ortamlarında çalışmasına uygun bir davranıştır. Çünkü ağlı yapılarda, ağ üzerinde erişilecek uzak nesnelerin daha derleme zamanında hazır olmalarını beklemek çok da mantıklı değildir.

Evet işte Java böyle bir dildir. Burada sayılan özelliklerin hangisini ne kadar sahip olduğu ya da ne derece yerine getirdiği tabi ki tartışılır. Ama yazılım dünyasında başka hiçbir dil Java kadar hızlı ve heyecanlı bir karşılama görmemiştir. Telefonlardan çok büyük çaptaki kurumsal projelere kadar pek çok farklı platformda kullanılıyor olması Java’nın bilgi teknolojileri dünyasının en temel dillerinden birisi haline geldiğinin kanıtıdır.

Bundan sonraki yazıda Java’nın kısa tarihinden bahsedeceğiz.

Toplam görüntülenme sayısı: 4335