Strona główna > Java > Manipulowanie obiektem poprzez refleksje

Manipulowanie obiektem poprzez refleksje

Jest to opis tworzenia kodu/narzędzia. Jego główny cel to odczytywanie i manipulowanie stanem obiektu w sytuacji kiedy on sam nie udostępnia takich metod. Kod taki zdarzało mi się głównie stosować/używać w testach (większy opis o tym w następnym poście).
Do realizacji tej funkcjonalności jest użyta refleksja, co w podstawowej wersji wygląda tak:

	public static void setFiledValue(Object target, String filedName, Object value) {
		try {
			Field field = getFiled(target.getClass(), filedName);
			field.set(target, value);
		} catch (Exception e) {
			throw new RuntimeException("Exception in setFiledValue for: " + filedName, e);
		}
	}

	public static Object getFiledValue(Object target, String filedName) {
		try {
			Field field = getFiled(target.getClass(), filedName);
			Object object = field.get(target);
			return object;
		} catch (Exception e) {
			throw new RuntimeException("Exception in getFiledValue for: " + filedName, e);
		}
	}

	private static Field getFiled(Class<? extends Object> clazz, String filedName) {
		try {
			Field field = clazz.getDeclaredField(filedName);
			field.setAccessible(true);
			return field;
		} catch (Exception e) {
			throw new RuntimeException("Exception in getFiled for: "  + filedName, e);
		} 
	}


Najważniejsza cześć jest w metodzie getFiled. Metoda getDeclaredField zwraca pole danej klasy po nazwie (także prywatne). Metoda setAccessible zdejmuje restrykcje (jeśli jest zdefiniowane jako prywatne) z tego pola i umożliwia późniejszy odczyt i zapis do niego.

Dzięki temu dla przykładowej klasy (pozbawionej możliwością manipulacji jej stanem):

public class Person {
	private String name;
}

Można zrobić coś takiego

		Person person = new Person();
		
		setFiledValue(person, "name", "newName");
		String name = (String)getFiledValue(person, "name");

Taki podstawowy zestaw metod jest już przydatnym narzędziem i bazą do rozwoju innych narzędzi wykorzystujących refleksje. Dzięki czemu można zrobić prosto wiele drobnych operacji, jak i także zrobić sobie krzywdę😉 lub zaciemnić obraz innym.

Na koniec jeszcze usprawnienie do początkowej wersji. Metoda getDeclaredField zwraca pola prywatne danej klasy, ale już nie odnajdzie pola zdefiniowanego w klasie nadrzędnej. Dla takiej klasy.

	public Citizen extends Person {
		private String country;
	}

pole z klasy nadrzędnej się nie odnajdzie.

		Citizen person = new Citizen();
		
		setFiledValue(person, "name", "newName");
		String name = (String)getFiledValue(person, "name");

Dlatego też metodę getFiled można przepisać do postaci:

	private static Field getFiled(Class<? extends Object> clazz, String filedName) {
		if (clazz != null) {
			Field[] declaredFields = clazz.getDeclaredFields();
			for (int i = 0; i < declaredFields.length; i++) {
				Field field = declaredFields[i];
				if (field.getName().equals(filedName)) {
					field.setAccessible(true);
					return field;
				}
			}
			return getFiled((Class) clazz.getGenericSuperclass(), filedName);
		}
		throw new RuntimeException("No filed for name: "  + filedName);
	}

teraz się odnajdzie.

Kategorie:Java Tags:
  1. Brak komentarzy.
  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: