Java Programlama. Jenerikler



Benzer belgeler
Sınıf üyeleri: değişkenler (fields) and metotlar (methods) Değişkenler: nesne içerisindeki değişkenlerdir Temel veri tipi veya sınıf tipi

Sınıf üyeleri: değişkenler (fields) and metotlar (methods) Değişkenler: nesne içerisindeki değişkenlerdir Temel veri tipi veya sınıf tipi

Nesne tabanlı programlama nesneleri kullanan programlamayı içerir. Bir nesne farklı olarak tanımlanabilen gerçek dünyadaki bir varlıktır.

BİL-141 Bilgisayar Programlama I (Java)

/*Aşağıda ki kodları doğru şekilde anlar ve kullanırsanız java da sınıfları biraz da olsa anlamış olursunuz.*/

Java da Soyutlama ( Abstraction ) ve Çok-biçimlilik ( Polymorphism )

Lecture 11: Generics

Öğr. Gör. Musa AYDIN Fatih Sultan Mehmet Vakıf Üniversitesi

Sunum İçeriği. Programlamaya Giriş

abstract Sınıflar 1 Sınıf sınıf1 new class Ama aşağıdaki şekilde referans alınabilir;

Interface Comparator. Kılgılayan sınıf: Collator. Bildirimi: public interface Comparator

BMH-303 Nesneye Yönelik Programlama

JAVADA METOTLAR. BMÜ-111 Algoritma ve Programlama. Yrd. Doç. Dr. İlhan AYDIN

Java Programlama Dilinde Veri Tipleri. Yrd. Doç. Dr. Aybars UĞUR

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Java ile Nesneye Yönelik Programlama (Object Oriented Programming)

İçerik. Temel Kavramlar. Nesne Nedir? 1. Nesne : Örnek. Nesne Nedir? 2. Geçen hafta: Bu hafta: BBS-515 Nesneye Yönelik Programlama

5.HAFTA. Sınıf ve Nesne Kavramı, Metot Oluşturma, Kurucu Metot, this Deyimi

Temel Kavramlar BBS-515 Nesneye Yönelik Programlama

Dizi türündeki referanslar, dizi nesnelerine bağlanmaktadır. Dizi referansları tanımlamak bu dizinin hemen kullanılacağı anlamına gelmez...

BMÜ-111 Algoritma ve Programlama. Bölüm 5. Tek Boyutlu Diziler

Lambda İfadeleri (Lambda Expressions)

// hataları işaret eden referans

KUYRUKLAR QUEUES. Doç. Dr. Aybars UĞUR

Arayüz soyut metotların oluşturduğu bir koleksyondur. Bir sınıf arayüzü çalıştırırken arayüzün sahip olduğu soyut metotları da miras alır.

İST 264 VERİ YAPILARI Bitirme Sınavı A Grubu

JAVA PROGRAMLAMA DİLİ ÖZELLİKLERİ

Java String İşlemleri

NESNEYE DAYALI PROGRAMLAMA 9. HAFTA UYGULAMA DERSİ

public static int Toplam int x, int y

Görsel Programlama DERS 02. Görsel Programlama - Ders02/ 1

BİL132 Bilgisayar Programlama II

Eclipse, Nesneler ve Java 2 Java Nereden Çıktı? 2

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

BTEP243 Ders 3. class Yazım Kuralı:

MOBIL UYGULAMA GELIŞTIRME

Nesne Yönelimli Programlama

Sınıflar ve Yapılar Arasındaki Farklılıklar. Değer ve Referans Türde Olan Aktarımlar

Görsel Programlama DERS 03. Görsel Programlama - Ders03/ 1

Şablon Türler (Generics)

11- FONKSİYONLAR (FUNCTIONS)

Nesneye Dayalı Programlama

BMM3101 PROGRAMLAMA DİLLERİ

Operator Aşırı Yükleme (Operator OverLoading)

İçerik. Kapsülleme ( Encapsulation ) Java da Kalıtım: Örnek 2.1. Kalıtım ( Inheritance ) Tekrar Ziyaret. Java da Kalıtım: Örnek 2.2.

BMÜ-111 ALGORİTMA VE PROGRAMLAMA AKIŞ KONTROLÜ YRD. DOÇ. DR. İLHAN AYDIN

NESNE TABANLI PROGRAMLAMA-1 DERS UYGULAMALARI (22 EYLÜL - 14 KASIM

YZM 2105 Nesneye Yönelik Programlama

Dizi ( Array ) ve Dizgi ( String )

BMÜ-112 ALGORİTMA VE PROGRAMLAMA-II LABORATUARI DENEY-2 FÖYÜ

Bir c sınıfının doğal sıralaması ile tutarlı olması (be consistent with equals) demek, c sınıfı içindeki her e1 ve e2 nesnesi için

Java da, tüm değişkenlerin kullanılmadan önce tanımlanması edilmesi gerekir. Bir değişken tanımlamanın temel gösterimi bu şekildedir:

Java C.Thomas Wu 2004b kitabından Türkçeleştirilerek ve örneklendirilerek hazırlanmıştır.

1. Aşağıdaki program parçacığını çalıştırdığınızda result ve param değişkenlerinin aldığı en son değerleri ve programın çıktısını yazınız.

Yığıtın en üstündeki öğeyi değer olarak alır; ama onu yığıttan almaz, yerinde bırakır.

Kapsülleme ( Encapsulation ) BBS-515 Nesneye Yönelik Programlama

Programlama Dilleri 3

Nesne Yönelimli Programlama

ANA SINIF TÜRETİLEN BİRİNCİ SINIF TÜRETİLEN İKİNCİ SINIF

NESNEYE YÖNELİK PROGRAMLAMA

Önemli noktalar. Paradigma Nesnelere Giriş Mesajlar / Ara bağlantılar Bilgi Gizleme (Information Hiding ) Sınıflar(Classes) Kalıtım/Inheritance

Arayüz (Interface) Altuğ B. Altıntaş 2003 Java ve Yazılım Tasarımı - Bölüm 7 1

Java dili, aşağıdakiler de dahil olmak üzere çok çeşitli denetleyici türlerine sahiptir.

İNÖNÜ ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ 2. SINIF 1. DÖNEM VERİ YAPILARI DERSİ LABORATUAR ÖDEVİ

JAVADA DİZİ İŞLEMLERİ

Nesne Yönelimli Programlama

Lab7 DOĞU AKDENİZ ÜNİVERSİTESİ BİLGİSAYAR VE TEKNOLOJİ YÜKSEKOKULU BİLGİSAYAR PROGRAMCILIĞI. BTEP212 Java. Uygulama1: package javaapplication58;

Bilgisayar Teknolojileri Bölümü Bilgisayar Programcılığı Programı. Öğr. Gör. Cansu AYVAZ GÜVEN

MAT214 BİLGİSAYAR PROGRAMLAMA II DERSİ Ders 12: Grafik Kullanıcı Arayüzü (Graphical User Interface-GUI)

Görsel Programlama. Temel Veri Tipleri, Değişkenler, Operatörler, Akış Kontrolü, Sınıflar, Metotlar, Paketler ve JavaDoc

Yazılım Kodlama ve İ simlendirme Standartları v1.0

DÖNGÜLER BMÜ-111 ALGORİTMA VE PROGRAMLAMA-I YRD. DOÇ. DR. İLHAN AYDIN

Upgrading Internet Technology skills of Information and Communication Technologies (ICT) Professionals

C#(Sharp) Programlama Dili

TEMPLATES. Binnur Kurt Bilgisayar Mühendisliği Bölümü İstanbul Teknik Üniversitesi. C++ ile Nesneye Dayalı Programlama 1

Metotlar. d e f metot_adı [ ( [ arg [= d e f a u l t ] ]... [, arg [, &expr ] ] ) ] deyim ( l e r ) end

Binary Search. (Yarılama) Bölüm Dizide Bir Öğe Arama

BIL1202 ALGORİTMA VE PROGRAMLAMAYA GİRİŞ

BİL-142 Bilgisayar Programlama II

Mantıksal (Logic) Operatörler

BMH-303 Nesneye Yönelik Programlama

İNÖNÜ ÜNİVERSİTESİ MÜH. FAK. BİLGİSAYAR MÜH. BÖL. ALGORİTMA VE PROGRAMLAMA 2 DERSİ LAB. ÖDEVİ

Nesne Yönelimli Programlama ve Kalıtım

Nesneye Dayalı Programlama

Class PriorityQueue. Class PriorityQueue<E> java.lang.object java.util.abstractcollection<e> java.util.abstractqueue<e> java.util.

İNÖNÜ ÜNİVERSİTESİ MÜHENDİSLİK FAKÜLTESİ BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ 2. SINIF 1. DÖNEM VERİ YAPILARI DERSİ LABORATUAR ÖDEVİ

Final Sınavı Örnek Soruları Bahar 2018

Programlama Dillerinde Kullanılan Veri Tipleri

HSancak Nesne Tabanlı Programlama I Ders Notları

HSancak Nesne Tabanlı Programlama I Ders Notları

YZM 2116 Veri Yapıları

NESNE YÖNELİMLİ PROGRAMLAMA HAFTA # 4. Yrd.Doç.Dr.Hacer Karacan

C++ Dersi: Nesne Tabanlı Programlama

7. HAFTA. Erişim Belirleyiciler

Operatörlerin Aşırı Yüklenmesi

3. Bölüm Soyut Sınıflar (Abstract Classes) Java ile Nesne Merkezli ve Fonksiyonel Programlama Akın Kaldıroğlu

BLM 111 ALGORİTMA VE PROGRAMLAMA I

Dr. Fatih AY Tel: fatihay@fatihay.net

Sınav Dağılım & IMKB Endeks

Java Programlama. Diziler, Döngüler ve Karakter Katarları (String Sınıfı)

Transkript:

Java Programlama Jenerikler

Jenerikler ve Kolleksiyonlar İlk kez Java 5 e eklendi (2004) Jeneriklerle dile yeni yazım kuralları eklendi Temel API lerdeki pek çok sınıf ve metodun tanımı değiştirildi Özellikle Kolleksiyonlar API si (Collections API) güncellendi Koleksiyon: nesneler grubu Koleksiyon sınıfları: List (liste), Map (harita), Stack (yığın), Vector (vektör) Koleksiyon sınıfları her tür nesne tipi için çalışırlar (Örnek: Integer, Double )

Jenerikler - Faydaları Pek çok algoritma hangi veri tipine uygulanırsa uygulansın aynı mantıkta çalışır Örnekler: Integer veya String yığını (Stack) işlemleri Sıralama algoritmaları Jenerikler öncesi de bu tür sınıflar/metotlar farklı nesne tipleri ile çalışacak şekilde yazılabiliyordu: Object temel sınıfı kullanılarak Jenerikler: Bu işlemin daha kolay ve Tip güvenli (type-safe) şekilde yapılmasını sağladı

Jenerik Nedir? Parametreleştirilmiş veri tipleridir (parameterized types) Jenerikler, üzerinde çalışacakları veri tipleri parametre olarak belirtilebilen sınıflar, arayüzler ve metotlar oluşturmamızı sağlarlar Örneğin, jenerikler sayesinde farklı veri tipleri ile otomatik çalışabilen bir sınıf oluşturulabilir Sonraki slaytlarda basit bir jenerik sınıf tanımı ve kullanımı gösterilmiştir

Örnek: Jenerik Sınıf Tanımı class Gen<T> { T ob; // declare an object of type T Gen(T o) { ob = o; T getob() { return ob; void showtype() { System.out.println("Type of T is " + ob.getclass().getname());

Örnek: Jenerik Sınıf Kullanımı (1/2) // Create a Gen reference for Integers. Gen<Integer> iob; // Create a Gen<Integer> object and assign its // reference to iob. Notice the use of autoboxing // to encapsulate the value 88 within an Integer object. iob = new Gen<Integer>(88); // Show the type of data used by iob. iob.showtype(); // Get the value in iob. Notice that // no cast is needed. int v = iob.getob(); System.out.println("value: " + v); System.out.println();

Örnek: Jenerik Sınıf Kullanımı (2/2) // Create a Gen object for Strings. Gen<String> strob = new Gen<String>("Generics Test"); // Show the type of data used by strob. strob.showtype(); // Get the value of strob. Again, notice // that no cast is needed. String str = strob.getob(); System.out.println("value: " + str); Type of T is java.lang.integer value: 88 Type of T is java.lang.string value: Generics Test

Jenerik Referans Tipleri Jenerikler sadece nesne referans tipleri ile çalışır: // Hata! temel veri tipleri kullanılamaz Gen<int> intob = new Gen<int>(53); Farklı parametre tipi kullanan jenerik nesne referansları, aynı jenerik sınıftan türetilse bile farklı nesne tipleridir iob = strob; // Derleme hatasi verir iob = new Gen<Double>(88.0); // Hata!

Örnek: Jenerik Olmayan Sınıf class NonGen { Object ob; // ob is now of type Object Aynı örneğin jenerik olmayan (eski tip) versiyonunu inceleyelim: NonGen(Object o) { ob = o; Object getob() { return ob; void showtype() { System.out.println("Type of ob is " + ob.getclass().getname());

Örnek: Jenerik Olmayan Sınıf Kullanımı (1/2) NonGen iob; // Create NonGen Object and store // an Integer in it. Autoboxing still occurs. iob = new NonGen(88); // Show the type of data used by iob. iob.showtype(); // Get the value of iob. // This time, a cast is necessary. int v = (Integer) iob.getob(); System.out.println("value: " + v); System.out.println();

Örnek: Jenerik Olmayan Sınıf Kullanımı (2/2) // Create another NonGen object and // store a String in it. NonGen strob = new NonGen("Non-Generics Test"); // Show the type of data used by strob. strob.showtype(); // Get the value of strob. // Again, notice that a cast is necessary. String str = (String) strob.getob(); System.out.println("value: " + str); // This compiles, but is conceptually wrong! iob = strob; v = (Integer) iob.getob(); // run-time error!

İki Tip Parametreli Jenerik Sınıf (1/2) Jenerik bir tip için birden fazla tip parametresi tanımlayabilirsiniz. Birden fazla tip var ise, bunlar virgül ile birbirinden ayrılmalıdır. Örnek: // A simple generic class with two type // parameters: T and V. class TwoGen<T, V> { T ob1; V ob2; TwoGen(T o1, V o2) { ob1 = o1; ob2 = o2;

İki Tip Parametreli Jenerik Sınıf (2/2) void showtypes() { System.out.println("Type of T is " + ob1.getclass().getname()); System.out.println("Type of V is " + ob2.getclass().getname()); T getob1() { return ob1; V getob2() { return ob2;

İki Tip Parametreli Jenerik Sınıf Kullanımı TwoGen<Integer, String> tgobj = new TwoGen<Integer, String>(88, "Generics"); // Show the types. tgobj.showtypes(); // Obtain and show values. int v = tgobj.getob1(); System.out.println("value: " + v); String str = tgobj.getob2(); System.out.println("value: " + str); Type of T is java.lang.integer Type of V is java.lang.string value: 88 value: Generics

Jenerik Sınıfların Genel Kullanım Şekli Sınıf tanımlama: class sınıf-adı <tip-parametre-listesi> { // Jenerik sınıf için referans tanımlama ve nesne oluşturma: sınıf-adı <tip-argüman-listesi> değişken-adı = new sınıf-adı <tip-argüman-listesi>(sabit-argüman-listesi);

Sınırlı Tipler (Bounded Types) (1/2) Önceki örneklerde, jenerik sınıflara parametre olarak herhangi bir sınıf gönderilebiliyordu Bazen tip parametresi olarak belirlenebilecek sınıfları kısıtlanmak istenebilir Örneğin, bir sayı dizisinin ortalamasını döndüren bir metot içeren jenerik bir sınıf düşünün Bu sınıfın her tür sayı tipi (int, float, double) dizisi için çalışmasını istediğinizi varsayın İlk aşamada bir sonraki slayttaki gibi bir çözüm düşünebilirsiniz:

Sınırlı Tipler Hatalı Çözüm class Stats<T> { T[] nums; // nums is an array of type T Stats(T[] o) { nums = o; double average() { double sum = 0.0; for (int i = 0; i < nums.length; i++) sum += nums[i].doublevalue(); // Error!!! return sum / nums.length;

Sınırlı Tipler (Bounded Types) (2/2) Java da tüm sayı sınıfları (Integer, Double, Float vs.), Number temel sınıfından türemişlerdir Bu nedenle, jenerik tipimizi bu sınıf ve alt sınıfları ile sınırlayabiliriz Bu amaçla kullanılan yazım kuralı şu şekildedir: <T extends temel-sınıf> Bu kural jenerik sınıfı için kullanılabilecek nesne tiplerini, temel-sınıf ve bu sınıfın alt sınıfları ile sınırlandıracaktır

Sınırlı Tipler Doğru Çözüm (1/2) class Stats<T extends Number> { T[] nums; // array of Number or subclass Stats(T[] o) { nums = o; // Return type double in all cases. double average() { double sum = 0.0; for (int i = 0; i < nums.length; i++) sum += nums[i].doublevalue(); return sum / nums.length;

Sınırlı Tipler Doğru Çözüm (2/2) Integer inums[] = { 1, 2, 3, 4, 5 ; Stats<Integer> iob = new Stats<Integer>(inums); double v = iob.average(); System.out.println("iob average is " + v); Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 ; Stats<Double> dob = new Stats<Double>(dnums); double w = dob.average(); System.out.println("dob average is " + w); // This won't compile because String is not a // subclass of Number. // String strs[] = { "1", "2", "3", "4", "5" ; // Stats<String> strob = new Stats<String>(strs); // double x = strob.average(); // System.out.println("strob average is " + v);

Sınırlı Tipler Arayüzle Sınırlandırma Jenerik tipler arayüzler ile de sınırlandırılabilir. Notasyon aynıdır: <T extends arayüz> Jenerik tip, en genel halinde bir sınıf ve birden fazla arayüzle sınırlandırılabilir Sınırlandırma yapacak sınıf başta olmak kaydıyla, sınıf ve arayüz(ler) & işareti ile ayrılmalıdır. Örnek: Class Gen <T extends MyClass & MyInterface> { //

Joker Parametreleri (Wildcard Parameters) Tip güvenliği ne kadar yararlı olsa da, bazen programcıları sınırlandırabilir Bir önceki Stats örneğini ele alalım İki stats nesnesinin, hangi tip sayısal veri içerdiğine bakmaksızın, aynı ortalamayı verip vermediğini sameavg() metodu ile belirlemeye çalışalım Örneğin, sameavg metodunu sonraki slayttaki gibi çağırmak isteyelim

sameavg() Metodu Kullanımı Integer inums[] = { 1, 2, 3, 4, 5 ; Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 ; Stats<Integer> iob = new Stats<Integer>(inums); Stats<Double> dob = new Stats<Double>(dnums); if(iob.sameavg(dob)) System.out.println("are the same."); else System.out.println("differ.");

Problem: sameavg() Metodu Gerçekleştirimi Aşağıdaki implementasyon çözüm olmaz. Neden? // This won t work boolean sameavg(stats<t> ob) { if (average() == ob.average()) return false; return true;

Çözüm: sameavg() Metodu Gerçekleştirimi Aşağıdaki gibi, joker parametre (?) kullanımı problemi çözer Joker tipi bilinmeyen bir tipi temsil eder // Determine if two averages are the same. // Notice the use of the wildcard. boolean sameavg(stats<?> ob) { if (average() == ob.average()) return true; return false;

Sınırlı Jokerler (Bounded Wildcards) Joker parametreler, tıpkı tip parametresinin sınırlandırıldığı gibi sınırlandırılabilir Özellikle bir sınıf hiyerarşisi üzerinde çalışacak bir jenerik tip oluştururken önemlidir Bunun nedenini anlamak için takip eden slaytlardaki örneği inceleyelim Öcelikle 2, 3 ve 4 boyutun koordinatlarını tutan sınıflar oluşturacağız Ve bu sınıflar, bir sınıf hiyerarşisi oluşturacak

TwoD Sınıfı // Two-dimensional coordinates. class TwoD { int x, y; TwoD(int a, int b) { x = a; y = b;

ThreeD Sınıfı // Three-dimensional coordinates. class ThreeD extends TwoD { int z; ThreeD(int a, int b, int c) { super(a, b); z = c;

FourD Sınıfı // Four-dimensional coordinates. class FourD extends ThreeD { int t; FourD(int a, int b, int c, int d) { super(a, b, c); t = d;

Coords Sınıfı Birden fazla, TwoD ve türevlerini, bir dizi içerisinde tutan Coords jenerik sınıfını oluşturalım Coords sınıfının TwoD sınıfı ile sınırlandırılmış olduğuna dikkat edin // This class holds an array of coordinate objects. class Coords<T extends TwoD> { T[] coords; Coords(T[] o) { coords = o;

showxy( ) Metodu Her Coords nesnesindeki dizi içerisinde en az iki koordinatlı nesneler (TwoD ve türevleri) olduğundan bu metot sorunsuz çalışacaktır static void showxy(coords<?> c) { System.out.println("X Y Coordinates:"); for(int i=0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y); System.out.println();

showxyz(...) Metodu ThreeD ya da FourD nesnesinin X, Y ve Z koordinatlarını görüntüleyen bir metod yazmak isteyelim Coords nesnesindeki dizi içerisinde en az üç koordinatlı nesnelerin bulunması gerekir. Bu da sınırlı jokerler ile sağlanabilir. static void showxyz(coords<? extends ThreeD> c) { System.out.println("X Y Z Coordinates:"); for(int i=0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z); System.out.println();

showall(...) Metodu Sadece FourD nesnesinin X, Y, Z ve T koordinatlarını görüntüleyen metod Coords nesnesindeki dizi içerisinde en az dört koordinatlı nesnelerin bulunması gerekir static void showall(coords<? extends FourD> c) { System.out.println("X Y Z T Coordinates:"); for(int i=0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y + " " + c.coords[i].z + " " + c.coords[i].t); System.out.println();

Test Sınıfı: BoundedWildcard - Çıktı (1/5) class BoundedWildcard { static void showxy(coords<?> c) { System.out.println("X Y Coordinates:"); for (int i = 0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y); System.out.println();

Test Sınıfı: BoundedWildcard - Çıktı (2/5) static void showxyz(coords<? extends ThreeD> c) { " System.out.println("X Y Z Coordinates:"); for (int i = 0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y + " + c.coords[i].z); System.out.println();

Test Sınıfı: BoundedWildcard - Çıktı (3/5) static void showall(coords<? extends FourD> c) { System.out.println("X Y Z T Coordinates:"); for (int i = 0; i < c.coords.length; i++) System.out.println(c.coords[i].x + " " + c.coords[i].y + " «+ c.coords[i].z + " " + c.coords[i].t); System.out.println();

Test Sınıfı: BoundedWildcard - Çıktı (4/5) public static void main(string args[]) { TwoD td[] = { new TwoD(0, 0), new TwoD(7, 9), new TwoD(18, 4), new TwoD(-1, -23) ; Coords<TwoD> tdlocs = new Coords<TwoD>(td); System.out.println("Contents of tdlocs."); showxy(tdlocs); // OK, is a TwoD // showxyz(tdlocs); // Error, not a ThreeD // showall(tdlocs); // Error, not a FourD

Test Sınıfı: BoundedWildcard - Çıktı (5/5) // Now, create some FourD objects. FourD fd[] = { new FourD(1, 2, 3, 4), new FourD(6, 8, 14, 8), new FourD(22, 9, 4, 9), new FourD(3, -2, -23, 17) ; Coords<FourD> fdlocs = new Coords<FourD>(fd); System.out.println("Contents of fdlocs."); // These are all OK. showxy(fdlocs); showxyz(fdlocs); showall(fdlocs);

Sınırlı Jokerler Üst Sınır Bir joker için üst sınır belirlemek için aşağıdaki şekilde bir joker deyimi kullanılır <? extends sınıf-adı> Bu durumda sınıf-adı adlı sınıf ve bu sınıftan türetilmiş sınıflar kullanılabilir Bu deyimle kabul edilen sınıfların sınıf-adı nı da kapsadığına dikkat edin

Sınırlı Jokerler Alt Sınır Bir joker için alt sınır belirlemek için aşağıdaki şekilde bir joker deyimi kullanılır <? super sınıf-adı> Bu durumda sadece sınıf-adı nın türetildiği temel sınıflar kullanılabilir Bu deyimle kabul edilen sınıfların sınıf-adı nı da kapsamadığına dikkat edin

Jenerik Metotlar Önceki örneklerde, jenerik sınıflar içindeki metotlar, sınıf için tanımlı olan tip parametrelerini kullanmaktaydı Ancak, kendi başına veya daha çok tip parametresi kullanan jenerik metotlar tanımlamak da mümkündür Hatta, jenerik olmayan bir sınıf içinde bile jenerik bir metot oluşturulabilir Bir sonraki slaytta, jenerik olmayan GenMetDemo adlı jenerik olmayan sınıf içerisinde jenerik isin() metodu tanımlanmıştır isin() metodu, aranan nesne tipiyle uyumlu nesneler içerdiği sürece, her tipte nesneyle ve diziyle kullanılabilir

GenMetDemo class GenMethDemo { // Determine if an object is in an array. static <T, V extends T> boolean isin(t x, V[] y) { for (int i = 0; i < y.length; i++) if (x.equals(y[i])) return true; return false;

GenMetDemo Main Metotu (1/2) public static void main(string args[]) { // Use isin() on Integers. Integer nums[] = { 1, 2, 3, 4, 5 ; if (isin(2, nums)) System.out.println("2 is in nums"); if (!isin(7, nums)) System.out.println("7 is not in nums"); System.out.println();

GenMetDemo Main Metotu (2/2) // Use isin() on Strings. String strs[] = { "one", "two", "three", "four", "five" ; if (isin("two", strs)) System.out.println("two is in strs"); if (!isin("seven", strs)) System.out.println("seven is not in strs"); // Opps! Won't compile! Types must be compatible. // if(isin("two", nums)) // System.out.println("two is in strs");

ısin() Metodu İncelemesi static <T, V extends T> boolean isin(t x, V[] y) Tip prametrelerinin dönüş tipinden önce tanımlandığına dikkat edin V tipinin T ile üstten sınırlandırıldığına dikkat edin Böylece V, ya T ya da T nin bir alt sınıfı tipinde olmalıdır Bu ilişki metodun sadece birbiriyle uyumlu parametrelerle çağırılmasını sağlar <tip-param-list> donus-tipi metot-adi(param-list) { //...

Daha Karmaşık ısin() Metodu Örneği static <T extends Comparable<T>, V extends T> boolean isin(t x, V[] y) Bu örnekte T de sınırlandırılmıştır T, java.lang paketindeki Comparable arayüzünü gerçekleştiren bir sınıf olmalıdır Comparable jenerik arayüzünü gerçekleştiren sınıflarda tutulan nesneler sıralanabilirdir İlerideki slaytlarda jenerik arayüzler oluşturulması da gösterilecektir

Jenerik Yapıcılar GenCons Sınıfı Yapıcılar, sınıfları jenerik olmasa bile jenerik tanımlanabilirler // Use a generic constructor. class GenCons { private double val; <T extends Number> GenCons(T arg) { val = arg.doublevalue(); void showval() { System.out.println("val: " + val);

Jenerik Yapıcılar GenCons Demo class GenConsDemo { public static void main(string args[]) { GenCons test = new GenCons(100); GenCons test2 = new GenCons(123.5F); test.showval(); test2.showval();

Jenerik Arayüzler MinMax Arayüzü Bir nesneler kümesinin minimum ve maksimum değerlerini döndüren min() ve max() metotlarını içeren MinMax jenerik arayüzü: // A generic interface example. // A Min/Max interface. interface MinMax<T extends Comparable<T>> { T min(); T max();

MinMax Arayüzünün Gerçekleştirimi (1/2) // Now, implement MinMax class MyClass<T extends Comparable<T>> implements MinMax<T> { T[] vals; MyClass(T[] o) { vals = o; // Return the minimum value in vals. public T min() { T v = vals[0]; for (int i = 1; i < vals.length; i++) if (vals[i].compareto(v) < 0) v = vals[i]; return v;

MinMax Arayüzünün Gerçekleştirimi (2/2) // Return the maximum value in vals. public T max() { T v = vals[0]; for (int i = 1; i < vals.length; i++) if (vals[i].compareto(v) > 0) v = vals[i]; return v;

MinMax Arayüzü Kullanımı - GenIFDemo class GenIFDemo { public static void main(string args[]) { Integer inums[] = { 3, 6, 2, 8, 6 ; Character chs[] = { 'b', 'r', 'p', 'w' ; MyClass<Integer> iob = new MyClass<Integer>(inums); MyClass<Character> cob = new MyClass<Character>(chs); System.out.println("Max value in inums: " + iob.max()); System.out.println("Min value in inums: " + iob.min()); System.out.println("Max value in chs: " + cob.max()); System.out.println("Min value in chs: " + cob.min());

Arayüz Kullanımının Detaylı İncelemesi (1/4) class MyClass <T extends Comparable<T>> implements MinMax<T> { T tip parametresinin MyClass tarafından nasıl tanımlandığına ve sonra MinMax a aktarıldığına dikkat edin T yi arayüz için yeniden Comparable ile sınırlandırılmamalıdır: class MyClass <T extends Comparable<T>> implements MinMax<T extends Comparable<T>> { // HATA!

Arayüz Kullanımının Detaylı İncelemesi (2/4) Bir sınıf jenerik bir arabirimi gerçekleştiriyorsa, o sınıf da, en azından arayüze aktarılacak bir tip parametresi alacak şekilde jenerik olmalıdır Örneğin aşağıdaki tanım hatalıdır: class MyClass implements MinMax<T> { // HATA! Bu durumda T belirteci bilinmez ve derleyici bir hata bildirir

Arayüz Kullanımının Detaylı İncelemesi (3/4) Ancak, arayüzü gerçekleştiren sınıf jenerik olmak zorunda değildir Bu durumda arayüzü hangi tip üzerinden gerçekleştirdiğini aşağıdaki gibi belirtmelidir: class MyClass implements MinMax<Integer> { // OK

Arayüz Kullanımının Detaylı İncelemesi (4/4) Jenerik arayüzlerin tanımlanması: interface arayuz-adi<tip-param-list> { //... Buradaki tip-param-list parametrelerin virgülle ayrılmış bir listesidir Jenerik arayüzlerin gerçekleştirimi aşağıdaki gibi yapılır class sinif-adi<tip-param-list> implements arayuz-adi<tip-arg-list> {

Ham Tipler ve Eski Kodlar Jenerikler JDK5 ile gelmiştir JDK5 öncesi kodların, jenerik tabanlı yeni API ile uyumlu kalması için bir mekanizma sağlanmalıydı Mekanizma: Jenerik bir sınıfın herhangi bir tip argümanı olmadan kullanılabilmesi Sınıf için bir ham tip (raw type) oluşturulur Bu ham tip jenerikler hakkında bilgisi olmayan eski kodlarla uyumludur

Ham Tip Örneği (1/3) // Demonstrate a raw type. class Gen<T> { T ob; // declare an object of type T // Pass the constructor a reference to // an object of type T. Gen(T o) { ob = o; // Return ob. T getob() { return ob;

Ham Tip Örneği (2/3) // Demonstrate raw type. class RawDemo { public static void main(string args[]) { // Create a Gen object for Integers. Gen<Integer> iob = new Gen<Integer>(88); // Create a Gen object for Strings. Gen<String> strob = new Gen<String>("Generics Test"); // Create a raw-type Gen object and give it // a Double value. Gen raw = new Gen(new Double(98.6));

Ham Tip Örneği (3/3) // Cast here is necessary because type is unknown. double d = (Double) raw.getob(); System.out.println("value: " + d); // The use of a raw type can lead to run-time. // exceptions. Here are some examples. // The following cast causes a run-time error! // int i = (Integer) raw.getob(); // run-time error // This assigment overrides type safety. strob = raw; // OK, but potentially wrong // String str = strob.getob(); // run-time error // This assingment also overrides type safety. raw = iob; // OK, but potentially wrong // d = (Double) raw.getob(); // run-time error

Ham Tipler - Sonuç Ham tipler tip güvenliği mekanizmasını devre dışı bırakır ve çalışma zamanı hatalarına neden olabilir Derleyici çalışma zamanı hatası verebilecek pek çok durumda programcıyı uyarır Ham tipler, eski kodları, yeni jenerik tabanlı kodlarla kullanmak zorunda olduğunuz durumlarda kullanmalısınız Ham tipler sadece bir geçiş özelliğidir ve yeni kodlarda kullanılmaması gerekir

Jenerik Sınıf Hiyerarşileri Jenerik sınıflar, tıpkı jenerik olmayan sınıflar gibi sınıf hiyerarşisinin parçası olabilir Temel fark: bir jenerik hiyerarşide, jenerik üst sınıf tarafından ihtiyaç duyulan tüm parametre tiplerinin, tüm alt sınıflar tarafından hiyerarşide yukarı doğru aktarılması gerekir Bu, yapılandırıcı parametrelerinin hiyerarşide yukarı doğru aktarılmasına benzer

Jenerik Temel Sınıf (Gen) ve Alt Sınıfı (Gen2) // A simple generic class hierarchy. class Gen<T> { // A subclass of Gen. class Gen2<T> extends Gen<T> { T ob; Gen(T o) { ob = o; Gen2(T o) { super(o); // Return ob. T getob() { return ob; Gen2<Integer> num = new Gen2<Integer>(100);

Başka Bir Alt Sınıf: Gen2 Alt sınıf gerektiğinde kendi tip parametrelerini de ekleyebilir // A subclass of Gen that defines a second // type parameter, called V. class Gen2<T, V> extends Gen<T> { V ob2; Gen2(T o, V o2) { super(o); ob2 = o2; V getob2() { return ob2;

Gen2 Alt Sınıfı Kullanımı // Create an object of type Gen2. class HierDemo { public static void main(string args[]) { // Create a Gen2 object for String and Integer. Gen2<String, Integer> x = new Gen2<String, Integer>("Value is: ", 99); System.out.print(x.getob()); System.out.println(x.getob2());

Jenerik Olmayan Temel Sınıf ve Jenerik Alt Sınıf Jenerik olmayan bir sınıf, jenerik bir sınıfın temel sınıfı olabilir Jenerik olmayan temel sınıf: // A nongeneric class can be the superclass of a generic subclass. // A nongeneric class. class NonGen { int num; NonGen(int i) { num = i; int getnum() { return num;

Jenerik Alt Sınıf // A generic subclass. class Gen<T> extends NonGen { T ob; // declare an object of type T // Pass the constructor a reference to // an object of type T. Gen(T o, int i) { super(i); ob = o; // Return ob. T getob() { return ob;

Jenerik Alt Sınıf Kullanımı // Create a Gen object. class HierDemo2 { public static void main(string args[]) { // Create a Gen object for String. Gen<String> w = new Gen<String>("Hello", 47); System.out.print(w.getob() + " "); System.out.println(w.getnum());

Jenerik Sınıflarla Tip Karşılaştırması (1/4) // Use the instanceof operator // with a generic class hierarchy. class Gen<T> { T ob; Gen(T o) { ob = o; // A subclass of Gen. class Gen2<T> extends Gen<T> { Gen2(T o) { super(o); // Return ob. T getob() { return ob;

Jenerik Sınıflarla Tip Karşılaştırması (2/4) class HierDemo3 { public static void main(string args[]) { // Create a Gen object for Integers. Gen<Integer> iob = new Gen<Integer>(88); // Create a Gen2 object for Integers. Gen2<Integer> iob2 = new Gen2<Integer>(99); // Create a Gen2 object for Strings. Gen2<String> strob2 = new Gen2<String>("Generics Test");

Jenerik Sınıflarla Tip Karşılaştırması (3/4) // See if iob2 is some form of Gen2. if (iob2 instanceof Gen2<?>) System.out.println("iOb2 is instance of Gen2"); // See if iob2 is some form of Gen. if (iob2 instanceof Gen<?>) System.out.println("iOb2 is instance of Gen"); System.out.println(); // See if strob2 is a Gen2. if (strob2 instanceof Gen2<?>) System.out.println("strOb is instance of Gen2"); // See if strob2 is a Gen. if (strob2 instanceof Gen<?>) System.out.println("strOb is instance of Gen");

Jenerik Sınıflarla Tip Karşılaştırması (4/4) System.out.println(); // See if iob is an instance of Gen2, which it is not. if (iob instanceof Gen2<?>) System.out.println("iOb is instance of Gen2"); // See if iob is an instance of Gen, which it is. if (iob instanceof Gen<?>) System.out.println("iOb is instance of Gen"); // The following can't be compiled because // generic type info does not exist at run-time. // if(iob2 instanceof Gen2<Integer>) // System.out.println("iOb2 is instance of Gen2<Integer>");

Jenerik Sınıflarda Tip Dönüşümü Bir jenerik sınıfın referansının başka bir referans değişkenine atanması ancak bu iki referans değişkeni uyumluysa gerçekleşebilir Önceki örnek göz önüne alındığında: (Gen<Integer>) iob2 // geçerli (Gen<Long>) iob2 // geçersiz

Jenerik Sınıf Metotlarının Üzerine Yazmak (1/3) Jenerik bir sınıftaki metot, jenerik olmayan sınıflardaki gibi yeniden tanımlanabilir // Overriding a generic method in a generic class. class Gen<T> { T ob; // declare an object of type T // Pass the constructor a reference to an object of type T. Gen(T o) { ob = o; // Return ob. T getob() { System.out.print("Gen's getob(): "); return ob;

Jenerik Sınıf Metotlarının Üzerine Yazmak (2/3) // A subclass of Gen that overrides getob(). class Gen2<T> extends Gen<T> { Gen2(T o) { super(o); // Override getob(). T getob() { System.out.print("Gen2's getob(): "); return ob;

Jenerik Sınıf Metotlarının Üzerine Yazmak (3/3) // Demonstrate generic method override. class OverrideDemo { public static void main(string args[]) { // Create a Gen object for Integers. Gen<Integer> iob = new Gen<Integer>(88); // Create a Gen2 object for Integers. Gen2<Integer> iob2 = new Gen2<Integer>(99); // Create a Gen2 object for Strings. Gen2<String> strob2 = new Gen2<String>("Generics Test"); System.out.println(iOb.getob()); System.out.println(iOb2.getob()); System.out.println(strOb2.getob());

Jeneriklerde Tip Çıkarsama (1/4) JDK7 den itibaren, bir jenerik tipin örneğini oluşturmak için kullanılan söz dizimini kısaltmak mümkündür Aşağıdaki jenerik sınıf için bu özelliği irdeleyelim class MyClass<T, V> { T ob1; V ob2; MyClass(T o1, V o2) { ob1 = o1; ob2 = o2;

Jeneriklerde Tip Çıkarsama (2/4) JDK7 den önce MyClass ın bir örneğini oluşturmak için: MyClass<Integer,String> mcob = new MyClass<Integer, String>(98, A String ); JDK7 ve sonrasında, yukarıdaki ifade şu şekilde yazılabilir: MyClass<Integer, String> mcob = new MyClass<>(98, A String ); Elmas operatörü: <>

Jeneriklerde Tip Çıkarsama (3/4) Referans ve örnek oluşturma için kullanılan genel ifade: sinif-adi <tip-arg-list> degisken-adi = new sinif-adi<>(yap-arg-list); Tip çıkarsama parametre aktarımına da uyarlanabilir. Örneğin MyClass sınıfına aşağıdaki metot eklensin: boolean issame(myclass<t, V> o) { if (ob1 == o.ob1 && ob2 == o.ob2) return true;

Jeneriklerde Tip Çıkarsama (4/4) Bu metodu, JDK7 ve sonrasında, aşağıdaki şekilde çağırabilirsiniz: if (mcob.issame(new MyClass<>(1, "test"))) System.out.println("Same");

Silme Jeneriklerin JDK5 öncesi versiyonlarla uyumlu olması için silme (erasure) mekanizması kullanılmaktadır Mekanizma: Java kodu derlenirken, tüm jenerik tip bilgisi ortadan kaldırılır(silinir) Sınırlı tip belirtilmişse: Tip parametreleri (örn: T), sınırlı tipleriyle değiştirilir Sınırlı tip açıkça belirtilmemişse: Sınırlı tip yerine Object sınıfı kullanılır Derleyici, aynı zamanda derleme aşamasında bu sınırlı tip uyumluluğunu zorlar Daha detaylı incelemek için Gen ve GenStr isimli iki sınıf kullanalım

Gen ve GenStr Sınıfları class Gen<T> { T ob; // declare an object of type T class GenStr<T extends String> { T str; // Pass the constructor a reference to // an object of type T. Gen(T o) { ob = o; // Return ob. T getob() { return ob; GenStr(T o) { str = o; T getstr() { return str;

Gen ve GenStr Sınıfları ile Silme Bu iki sınıf derlendikten sonra Gen deki T yerine Object GenStr deki T yerine de String geçer Gen<Integer> iob = new Gen<Integer>(99); int x = iob.getob(); Yukarıdaki nesne kullanım ise aslında aşağıdaki gibi yazılmış gibi derlenir: Gen iob = new Gen(99); int x = (Integer)iOb.getob();

Silme Mekanizmasını Gösteren Örnek public static void main() { Gen<Integer> iob = new Gen<Integer>(99); Gen<Float> fob = new Gen<Float>(102.2F); System.out.println(iOb.getClass().getName()); System.out.println(fOb.getClass().getName()); Çıktı: Gen Gen

Belirsizlik Hataları Jeneriklerin JDK5 e eklenmesi yeni bir hata tipini ortaya çıkardı Belirsizlik hataları, silmenin görünüşte iki farklı jenerik tanımı aynı silinmiş tipe çözümlemesi ve bir çakışmaya neden olması ile ortaya çıkar Bu hatanın gözlenebileceği, iki aşırı yüklenmiş metodu bulunan MyGenClass sınıfını inceleyelim

Belirsizlik Hataları - MyGenClass // Ambiguity caused by erasure on overloaded methods. class MyGenClass<T, V> { T ob1; V ob2; //... // These two overloaded methods are ambiguous // and will not compile. void set(t o) { ob1 = o; void set(v o) { ob2 = o;

MyGenClass Sınıfı Belirsizlik Hatası MyGenClass sınıfında T ve V adlı iki jenerik tip tanımlı Set metotu ise biri T parametresi, diğeri ise V parametresi alacak şekilde iki kere tanımlı (aşırı yükleme) Aşağıdaki şekilde bir MyGenClass nesnesi oluşturmak prensipte doğrudur: MyGenClass<String, String> obj = new MyGenClass<String><String>();

MyGenClass Sınıfı Belirsizlik Hatası Ancak bu kullanımda iki hata vardır: 1. Hem T hem de V, String ile değiştirilir. Bu set metodunun her iki versiyonunu da aynı kılar ve elbette hatalıdır 2. Daha temel sorun, tip silinmesi sonucu set metodunun her iki versiyonunun da aşağıdakine indirgenmesidir: void set(object o) { //...

MyGenClass Sınıfı Belirsizlik Hatasının Düzeltilmesi Belirsizlik hatalarının onarılması zor olabilir Belirsizlik çoğunlukla kodunuzdaki kavramsal bir hataya işaret eder Çoğunlukla belirsizliğin çözümü kodun yeniden yapılandırılmasını (refactoring) gerektirir Bir sonraki slaytta sorunu çözmeye çalışalım.

MyGenClass Sınıfı Belirsizlik Hatasının Düzeltilmesi MyGenClass ı aşağıdaki gibi tanımlamayı deneyebiliriz: class MyGenClass<T, V extends String> { // Neredeyse tamam! Bu değişiklik sayesinde aşağıdaki gibi nesne örnekleri oluşturabilirsiniz MyGenClass<Integer, String> x = new MyGenClass<Integer, String>();

MyGenClass Sınıfı Belirsizlik Hatasının Düzeltilmesi Ancak, aşağıdaki kod satırı denendiğinde belirsizlik geri gelir MyGenClass<String, String> obj = new MyGenClass<String><String>(); Bu durumda sorunu çözmek için set() metodunu aşırı yüklemek yerine, ayrı metot adları kullanmalıyız

Jenerik Kısıtlamaları Tip parametrelerinin örnekleri oluşturulamaz Statik üyelerle ilgili kısıtlamalar Jenerik dizi kısıtlamaları Jenerik istisna kısıtlaması Jenerik bir sınıf Throwable arayüzünü gerçekleştiremez Yani, jenerik istisna sınıfları oluşturulamaz

Tip parametrelerinin örnekleri oluşturulamaz Aşağıdaki örnekte, derleyici, T için hangi tipte nesne oluşturacağını bilemez // Can't create an instance of T. class Gen<T> { T ob; Gen() { ob = new T(); // Illegal!!!

Statik üyelerle ilgili kısıtlamalar Hiçbir static üye, kendisini kapsayan sınıf tarafından tanımalanmış bir tip prametresi tipinde tanımlanamaz Ancak, daha önce gördüğümüz gibi, static metot kendi tanımladığı tip paramtresini kullanabilir class Wrong<T> { // Wrong, no static variables of type T. static T ob; // Wrong, no static method can use T. static T getob() { return ob;

Jenerik dizi kısıtlamaları Dizilerle ilgili iki önemli kısıtlama vardır: Temel tipi bir tip paramtresi olan bir dizi oluşturulamaz Tipe özgü jenerik referanslardan oluşan bir dizi oluşturulamaz Bu kısıtlamalarla ilgili iki örnek sonraki slaytlarda verilmiştir

Temel tipi bir tip paramtresi olan bir dizi oluşturulamaz // Generics and arrays. class Gen<T extends Number> { T ob; T vals[]; // OK Gen(T o, T[] nums) { ob = o; // This statement is illegal. // vals = new T[10]; // can't create an array of T // But, this statement is OK. vals = nums; // OK to assign reference to existent array

Tipe özgü jenerik referanslardan oluşan bir dizi oluşturulamaz class GenArrays { public static void main(string args[]) { Integer n[] = { 1, 2, 3, 4, 5 ; Gen<Integer> iob = new Gen<Integer>(50, n); // Can't create an array of type-specific generic references. // Gen<Integer> gens[] = new Gen<Integer>[10]; // Wrong! // This is OK. Gen<?> gens[] = new Gen<?>[10]; // OK