Pure Java – 77 Generics & Collections – Generics – 02

Merhaba Arkadaslar
Bu bolumde Generics konusuna devam edecegiz.

Generics Methods
Polymorphism kavraminin bize sagladigi en onemli faydalardan birtanesi, bir metot parametresi calisma zamaninda/runtime kendi tipinde ya da subtype tipinde bir objeye referansta bulunabilir. Polymorphism ve override konusunu kisaca hatirlayalim

class Animal {
	public void eat() {
		System.out.println("Animal eat");
	}
}

class Dog extends Animal {
	public void eat() {
		System.out.println("Dog eat");
	}
}

class Cat extends Animal {
	public void eat() {
		System.out.println("Cat eat");
	}
}

public class Test {

	public static void main(String[] args) {
		Dog dog = new Dog();
		Animal animal = new Animal();
		Animal animalCat = new Cat();

		polymorphismTest(dog);
		polymorphismTest(animal);
		polymorphismTest(animalCat);
		
	}

	public static void polymorphismTest(Animal a) {
		a.eat();
	}
}

polymorphismTest metodu parametre olarak Animal tipinde bir degisken almaktadir. Hatirlayacagimiz gibi override metotlarda objenin tipi onemlidir. Objenin tipine gore ilgili sinifa ait metot calisacaktir.

Bu durum isin icine Collection girdiginde nasil olacaktir peki ?

import java.util.ArrayList;
import java.util.List;

class Animal {
	public void eat() {
		System.out.println("Animal eat");
	}
}

class Dog extends Animal {
	public void eat() {
		System.out.println("Dog eat");
	}
}

public class CollectionGenericsMethodTest {

	public static void main(String[] args) {
		List<Animal> animalList = new ArrayList<Animal>();
		List<Dog> dogList = new ArrayList<Dog>();

		// List animalDogList = new ArrayList();
		// Derleme hatasi verir! Referans degisken  olarak tanimliysa ,
		// new anahtar kelimesinden sonra  olmalidir.

		genericsRules(animalList);
		// genericsRules(dogList);
		// dogList'i arguman olarak veremeyiz. Ilgili metot List tipinde
		// bir parametre almaktadir.
		// Dog IS-A Animal olsa da buraya List tipine bir degisken
		// gonderemeyiz !
	}

	public static void genericsRules(List<Animal> myAnimals) {
		System.out.println("test");
	}
}

Peki benzer durumu array/dizi ile yaparsak ne olur ?

import java.util.ArrayList;
import java.util.List;

class Animal {
	public void eat() {
		System.out.println("Animal eat");
	}
}

class Dog extends Animal {
	public void eat() {
		System.out.println("Dog eat");
	}
}

public class ArrayTestMethod {

	public static void main(String[] args) {
		Animal[] animalArray = new Animal[5];
		Dog[] dogArray = new Dog[5];

		Animal[] animalDogArray = new Dog[5];

		arrayRules(animalArray);
		arrayRules(dogArray);
		arrayRules(animalDogArray);
	}

	public static void arrayRules(Animal[] animal) {
		System.out.println("test");
	}
}

Burada kodumuz sorunsucaz calisacaktir. Animal[] tipinde parametre alan bir metoda Dog[] tipinde bir referans degisken gonderebiliriz. (Dog IS-A Animal)

Peki neden array icin calisan bu durum collection icin calismamaktadir;

import java.util.List;

class Animal {
}

class Dog extends Animal {
}

class Cat extends Animal {
}

public class Test {

	public static void main(String[] args) {
		Cat[] catArray = { new Cat(), new Cat() };

		addAnimal(catArray);
		// Cat[] tipindeki referans degiskenimiz Animal[] tipinde parametre alan
		// metoda gonderebiliriz.
	}

	public static void addAnimal(Animal[] animalArray) {
		animalArray[0] = new Dog();
		//bu metoda arguman olarak Cat[] tipinde bir arguman gonderdik. 
		// java.lang.ArrayStoreException: hatasi verecektir!
	}

}

Eger metoda Animal sinifin alt sinif tipinde bir dizi argumani gecersek sorunsuzca caliscaktir , fakat Cat[] tipindeki bir diziye/array’e Dog tipinde bir obje ekledigimizde calisma zamaninda hata verecektir.

Bu senaryo onune gecmek istedigimiz bir durumdur. Iste bu nedenle List<Dog> tipindeki bir degiskeni List<Animal> tipinde bir parametre alan bir metoda gonderemeyiz.

import java.util.ArrayList;
import java.util.List;

class Animal {
}

class Dog extends Animal {
}

class Cat extends Animal {
}

public class Test {

	public static void main(String[] args) {
		Cat[] catArray = { new Cat(), new Cat() };

		addAnimal(catArray);
		// Cat[] tipindeki referans degiskenimiz Animal[] tipinde parametre alan
		// metoda gonderebiliriz.

		List animalList = new ArrayList();
		addAnimal(animalList);
	}

	public static void addAnimal(Animal[] animalArray) {
		animalArray[0] = new Dog();
		// bu metoda arguman olarak Cat[] tipinde bir arguman gonderdik.
		// java.lang.ArrayStoreException: hatasi verecektir!
	}

	// Bu metoda sadece List<Animal> tipinde bir arguman gecebiliriz.
	public static void addAnimal(List<Animal> animalList) {
		animalList.add(new Dog());
		animalList.add(new Cat());
		// Burada subclass tipinde objeler ekleyebiliriz. Bu metot sadece
		// List<Animal> tipinde arguman alabilir. Dolayisiyla burada
		// guvendeyiz. Calisma zamaninda problem olmayacaktir.
	}

}

Generics ? wildcard
Generics yapisinda ? wildcard olarak kullanilmaktadir. List<? extends Animal> seklinde kullanabiliriz.

import java.util.ArrayList;
import java.util.List;

class Animal {
}

class Dog extends Animal {
}

class Cat extends Animal {
}

public class GenericsWildcard {

	public static void main(String[] args) {
		List<Animal> animalList = new ArrayList<Animal>();

		List<Dog> dogList = new ArrayList<Dog>();

		addAnimal(animalList);
		addAnimal(dogList);

	}

	public static void addAnimal(List<? extends Animal> animalList) {
		// <? extends Animal> olarak tanimli oldugu zaman yeni bir elaman
		// ekleyemeyiz. sadece null ekleyebiliriz.

		// animalList.add(new Animal());
		// animalList.add(new Dog());

		animalList.add(null);

	}
}

List tipinde parametre alan bir metoda sadece tipinde bir degiskeni arguman olarak verebiliriz, fakat List<? extends Animal> tipinde parametre alan bir metoda sinifin altsinifi tipinde de bir arguman verebiliriz fakat bu metot icerisinde yeni bir eleman ekleyemeyiz. Sadece null eleman ekleyebiliriz.

? wildcard ile extends anahtar kelimesini kullanabiliriz. Burada ? karakterini bir arabirimle kullansak da extends anahtar kelimesi ile kullanabiliriz ? implements seklinde bir generics tanimi yoktur.

import java.util.List;

interface Speedy {
}

public class WildcardInterface {

	public void wildcard(List<? extends Speedy> test) {
		
	}
}

Bir diger kullanim sekli olarak super anahtar kelimesi kullanilabilir. <? super Dog> ifadesi , Dog veya ust sinif tipini kabul eder , alt sinifi kabul etmez.  <? super Dog> generics yapisi eleman eklemeye izin verir ,  Dog tipinde ya da alt sinif tipinde obje ekleyebiliriz fakat ust sinif tipinde bir eleman ekleyemeyiz.

import java.util.ArrayList;
import java.util.List;

class Animal {
}

class Dog extends Animal {
}

class Kangal extends Dog {

}

public class GenericsWildcardSuper {

	public static void main(String[] args) {

		List<Animal> animalList = new ArrayList<Animal>();
		List<Dog> dogList = new ArrayList<Dog>();
		List<Kangal> kangalList = new ArrayList<Kangal>();
		addAnimal(animalList);
		addAnimal(dogList);

		// addAnimal(kangalList);
		// derleme hatasi verir.

	}

	// ? super Dog , buraya Dog ve super/ust sinif tipinde arguman kabul eder.
	public static void addAnimal(List<? super Dog> dogList) {
		dogList.add(new Kangal());
		dogList.add(new Dog());
		//Burada Dog veya alt sinif tipinde obje ekleyebiliriz.
		
		// dogList.add(new Animal());
	}
}

List ve List tipinde degiskeni metoda gectigimizde sorun teskil etmez. Ekledegimiz elemanlar calisma zamaninda exceptiona neden olmaz.

Sadece ? wildcard’i kullandigimizda buraya herhangi bir tip kabul edilebilir.

import java.util.ArrayList;
import java.util.List;

class Car {

}

public class GenericsWildCardTest {

	public static void main(String[] args) {
		List<Integer> integerList = new ArrayList <Integer>();
		List<String> stringList = new ArrayList <String>();
		List<Car> carList = new ArrayList <Car>();
		List<Object> objectList = new ArrayList<Object>();

		wildcard(integerList);
		wildcard(stringList);
		wildcard(carList);
		wildcard(objectList);
	}

	// Sadece ? wildcard'i kullandigimizda buraya herhangi bir tipte tip kabul
	// edilebilir anlamina gelmektedir.
	public static void wildcard(List<?> myList) {
		System.out.println("wildcard ?");
		// myList.add("Compile Error");
		// ? tek basina kullanildiginda burada eleman eklenemez.
		// sadece null eklenir
		myList.add(null);

	}

}

Metot paramertesi List<Object> ise sadece <Object> tipinde arguman alabilir.

import java.util.ArrayList;
import java.util.List;

class Car {

}

public class GenericsObjectTest {

	public static void main(String[] args) {
		List<Integer> integerList = new ArrayList<Integer>();
		List<String> stringList = new ArrayList<String>();
		List<Car> carList = new ArrayList<Car>();
		List<Object> objectList = new ArrayList<Object>();

		// wildcard(integerList);
		// wildcard(stringList);
		// wildcard(carList);
		wildcard(objectList);
	}

	public static void wildcard(List <Object> myList) {
		System.out.println("Object");
		myList.add(10);
		myList.add("test");
		myList.add(new Car());
	}

}

<? extends Object> ile <?> aynidir.

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *