Παραμετρικοί τύποι δεδομένων (Generics)

Τα Generics προσθέτουν σταθερότητα και εύκολη εύρεση λαθών από τον μεταγλωττιστή σε θέματα που έχουν να κάνουν με:

  • Έλεγχο για τύπο δεδομένων (Type checking)
  • Casting
  • Παραμετροποίηση κώδικα και ελαχιστοποίηση επανάληψης
  • Ευρεία χρήση στις συλλογές (Collections)

Μπορούμε να έχουμε:

  1. παραμετρικές συναρτήσεις (generic functions)
  2. παραμετρικές κλάσεις (generic classes)

Παραμετρικές συναρτήσεις (generic functions)

Για να γίνει κατανοητή η λειτουργία των παραμετρικών συναρτήσεων, δίνεται αρχικά το παράδειγμα χωρίς παραμετρικές και στη συνέχεια με παραμετρικές.

Παράδειγμα χωρίς παραμετρικές.

public class Main {

	public static void main(String[] args) {

		Integer intArray[] = {5, 6, 3, 1, 8, 7, 9};
		Double doubleArray[] = {2.4, 6.5, 8.2};
		String stringArray[] = {"one", "two", "three"};
		
		displayArrayIntegers(intArray);
		displayArrayDoubles(doubleArray);
		displayArrayStrings(stringArray);
	}
	
	public static void displayArrayIntegers(Integer[] array ) {
		for(Integer x: array) {
			System.out.println(x); 
		}
	}
	public static void displayArrayDoubles(Double[] array ) {
		for(Double x: array) {
			System.out.println(x); 
		}
	}
	public static void displayArrayStrings(String[] array ) {
		for(String x: array) {
			System.out.println(x); 
		}
	}	
}

Παράδειγμα με παραμετρικές.

public class GenFuncion {
	public static void main(String[] args) {

		Integer intArray[] = {5, 6, 3, 1, 8, 7, 9};
		Double doubleArray[] = {2.4, 6.5, 8.2};
		String stringArray[] = {"one", "two", "three"};

		displayArray(intArray);
		displayArray(doubleArray);
		displayArray(stringArray);
		
		System.out.println(returnFirst(intArray));
		System.out.println(returnFirst(doubleArray));
		System.out.println(returnFirst(stringArray));	

	
		System.out.println(hasElement(intArray, 7));
		System.out.println(hasElement(doubleArray, 8.2));
		System.out.println(hasElement(stringArray, "two"));	
	}
	
	public static <T> void displayArray(T[] array) {
		for(T x : array) {
			System.out.println(x);
		}
	}
	
	public static <T> T returnFirst(T[] array) {
		return array[0];
	}
	
	public static <M> boolean hasElement(M[] array, M element) {
		boolean b = false;
		for(M i : array) {
			if(i.equals(element)) {
				b = true;
				break;
			}
		}
		return b;
	}
}

Παραμετρικές κλάσεις (generic classes)

Για να γίνει κατανοητή η λειτουργία των παραμετρικών κλάσεων, δίνεται αρχικά το παράδειγμα χωρίς παραμετρικές και στη συνέχεια με παραμετρικές.

Παράδειγμα χωρίς παραμετρικές.

public class NoGenClass {

	public static void main(String[] args) {
		MyIntegerClass myInt = new MyIntegerClass(123);
		MyDoubleClass myDouble = new MyDoubleClass(3.14);
		MyStringClass myString = new MyStringClass("hello");
		
		System.out.println(myInt.getValueX());
		System.out.println(myDouble.getValueX());
		System.out.println(myString.getValueX());
		
		myInt.setValueX(321);
		myDouble.setValueX(3.21);
		myString.setValueX("Hi");

		System.out.println(myInt.getValueX());
		System.out.println(myDouble.getValueX());
		System.out.println(myString.getValueX());
	}
}

class MyIntegerClass {
	int x;
	MyIntegerClass(int x) {
		setValueX(x);
	}
	
	void setValueX(int x) {
		this.x = x;
	}
	
	int getValueX() {
		return this.x;
	}
}

class MyDoubleClass {
	double x;
	
	MyDoubleClass(double x) {
		setValueX(x);
	}
	
	void setValueX(double x) {
		this.x = x;
	}
	
	double getValueX() {
		return this.x;
	}
}

class MyStringClass {
	String x;
	
	MyStringClass(String x) {
		setValueX(x);
	}
	
	void setValueX(String x) {
		this.x = x;
	}
	
	String getValueX() {
		return this.x;
	}
}

Παράδειγμα με παραμετρικές.

public class GenClass {

	public static void main(String[] args) {
		MyGenericClass<Integer> myInt = new MyGenericClass<>(123);
		MyGenericClass<Double> myDouble = new MyGenericClass<>(3.14);
		MyGenericClass<String> myString = new MyGenericClass<>("hello");
		
		System.out.println(myInt.getValueX());
		System.out.println(myDouble.getValueX());
		System.out.println(myString.getValueX());
		
		myInt.setValueX(321);
		myDouble.setValueX(3.21);
		myString.setValueX("Hi");

		System.out.println(myInt.getValueX());
		System.out.println(myDouble.getValueX());
		System.out.println(myString.getValueX());
	}
}

class MyGenericClass <T> {
	T x;
	MyGenericClass(T x) {
		this.setValueX(x);
	}
	
	public T getValueX() {
		return x;
	}
	
	public void setValueX(T x) {
		this.x = x;
	}
}

Πολυ-Παραμετρικές συναρτήσεις και κλάσεις

Μπορούμε να έχουμε πολυ-παραμετρικές κλάσεις και μεθόδους όπως στο παράδειγμα.

public class Pair<K, V> {

	private K key;
	private V value;

	public Pair(K key, V value) {
		this.key = key;
		this.value = value;
	}

	public void setKey(K key) {
		this.key = key;
	}
	public void setValue(V value) {
		this.value = value;
	}
	public K getKey() {
		return key;
	}
	public V getValue() {
		return value;
	}
}

Υλοποιημένο παράδειγμα με την Pair

public class Main {

	public static void main(String[] args) {
		
		Pair <String, Double> product = new Pair<>("mobile", 299.99);
		
		System.out.println(product.getKey());
		System.out.println(product.getValue());
		
		product.setKey("tv set");
		product.setValue(399.99);
		
		System.out.println(product.getKey());
		System.out.println(product.getValue());	
		
		product.setKeyValue("laptop", 499.99);
		
		System.out.println(product.getKey());
		System.out.println(product.getValue());			
	}
}

class Pair <K, V> {

	private K key;
	private V value;

	public Pair(K key, V value) {
		setKey(key);
		setValue(value);
	}

	public void setKey(K key) {
		this.key = key;
	}
	public void setValue(V value) {
		this.value = value;
	}
	
	public void setKeyValue(K key, V value) {
		setKey(key);
		setValue(value);
	}
	
	public K getKey() {
		return key;
	}
	public V getValue() {
		return value;
	}
}