자바 리플렉션
자바 리플렉션- 구체적인 타입의 클래스를 알지 못해도 그 클래스의 메소드,타입,변수에 접근할 수 있도록 해주는 API
리플렉션을 쓰는 이미 쓰고있는 것들
리플렉션을 쓰는 이미 쓰고있는 것들
- JUnit – uses reflection to parse @Test annotation to get the test methods and then invoke it.
- Spring – dependency injection, read more at Spring Dependency Injection
- Tomcat web container to forward the request to correct module by parsing their web.xml files and request URI.
- Eclipse auto completion of method names
- Struts
- Hibernate
리플렉션을 쓰면 안되는 상황
- Poor Performance – Since java reflection resolve the types dynamically, it involves processing like scanning the classpath to find the class to load, causing slow performance.
- Security Restrictions – Reflection requires runtime permissions that might not be available for system running under security manager. This can cause you application to fail at runtime because of security manager.
- Security Issues – Using reflection we can access part of code that we are not supposed to access, for example we can access private fields of a class and change it’s value. This can be a serious security threat and cause your application to behave abnormally.
- High Maintenance – Reflection code is hard to understand and debug, also any issues with the code can’t be found at compile time because the classes might not be available, making it less flexible and hard to maintain.
package reflection; import java.lang.reflect.*;import java.util.Arrays;import java.util.HashMap;import java.util.Map; /** * Created by jihun.im on 2017-04-24. */public class ReflectionMain { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException { Class<?> concreteClass = ConcreteClass.class; System.out.println(concreteClass.getCanonicalName()); //concreteClass = new ConcreteClass(5).getClass(); System.out.println(concreteClass.getCanonicalName()); try { // below method is used most of the times in frameworks like JUnit //Spring dependency injection, Tomcat web container //Eclipse auto completion of method names, hibernate, Struts2 etc. //because ConcreteClass is not available at compile time concreteClass = Class.forName("reflection.ConcreteClass"); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(concreteClass.getCanonicalName()); //for primitive types, wrapper classes and arrays Class<?> booleanClass = boolean.class; System.out.println(booleanClass.getCanonicalName()); Class<?> intClass = int.class; System.out.println(intClass.getCanonicalName()); Class<?> cDouble = Double.TYPE; System.out.println(cDouble.getCanonicalName()); // prints double Class<?> cDoubleArray = null; try { cDoubleArray = Class.forName("[D"); System.out.println(cDoubleArray.getCanonicalName()); //prints double[] } catch (ClassNotFoundException e) { e.printStackTrace(); } Class<?> twoDStringArray = String[][][].class; System.out.println(twoDStringArray.getCanonicalName()); // prints java.lang.String[][] //Super Class Test Class<?> superClass = null; Class<?> superSuperClass = null; try { superClass = Class.forName("reflection.ConcreteClass").getSuperclass(); superSuperClass = superClass.getSuperclass(); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(superClass); // prints "class reflection.BaseClass" System.out.println(superSuperClass); // prints "class java.lang.Object" //Get Public Member Classes Class<?>[] classes = concreteClass.getClasses(); System.out.println(Arrays.toString(classes)); //Get Declared Classes (+Private Classes) Class<?>[] explicitClasses = concreteClass.getDeclaredClasses(); System.out.println(Arrays.toString(explicitClasses)); //Get Declaring Classes Class<?> innerClass = Class.forName("reflection.ConcreteClass$ConcreteClassDefaultClass");//prints com.journaldev.reflection.ConcreteClass System.out.println(innerClass.getDeclaringClass().getCanonicalName()); System.out.println(innerClass.getEnclosingClass().getCanonicalName()); //Get Package Name System.out.println(innerClass.getPackage().getName()); //Modifier System.out.println(concreteClass.getModifiers()); System.out.println(Modifier.toString(concreteClass.getModifiers())); //Get Type parameters (generics) TypeVariable<?>[] typeParameters = Class.forName("java.util.HashMap").getTypeParameters(); for (TypeVariable<?> t : typeParameters) System.out.println(t.getName() + ","); //Get interfaces System.out.println(Arrays.toString(Class.forName("java.util.HashMap").getGenericInterfaces())); System.out.println(Arrays.toString(Class.forName("java.util.HashMap").getInterfaces())); //get methods Method[] publicMethods = Class.forName("reflection.ConcreteClass").getMethods(); //prints public methods of ConcreteClass, BaseClass, Object System.out.println(Arrays.toString(publicMethods)); //get public constructors Constructor<?>[] publicConstructors = Class.forName("reflection.ConcreteClass").getConstructors(); System.out.println(Arrays.toString(publicConstructors)); //Get All public fields Field[] publicFields = Class.forName("reflection.ConcreteClass").getFields(); //prints public fields of ConcreteClass, it's superclass and super interfaces System.out.println(Arrays.toString(publicFields)); try { Field field = Class.forName("reflection.ConcreteClass").getField("interfaceInt"); System.out.println(field); Class<?> classA = field.getDeclaringClass(); System.out.println("classA : " + classA); System.out.println("getType : " + field.getType()); ConcreteClass concreteClass2 = new ConcreteClass(5); field = Class.forName("reflection.ConcreteClass").getField("publicInt"); try { System.out.println(field.get(concreteClass2)); //prints 5 field.setInt(concreteClass2, 10); //setting field value to 10 in object System.out.println(field.get(concreteClass2)); //prints 10 } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } Field privateField = Class.forName("reflection.ConcreteClass").getDeclaredField("privateString"); //turning off access check with below method call privateField.setAccessible(true); ConcreteClass objTest = new ConcreteClass(1); System.out.println(privateField.get(objTest)); // prints "private string" privateField.set(objTest, "private string updated"); System.out.println(privateField.get(objTest)); //prints "private string updated" java.lang.annotation.Annotation[] annotations = Class.forName("reflection.ConcreteClass").getAnnotations(); //prints [@java.lang.Deprecated()] System.out.println(Arrays.toString(annotations)); //Invoking public method Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class); Map<String, String> hm = new HashMap<>(); hm.put("key2","value2"); method.invoke(hm, "key", "value"); System.out.println(hm); // prints {key=value} //Instantiate Object using Constructor Constructor<?> constructor = Class.forName("reflection.ConcreteClass").getConstructor(int.class); //getting constructor parameters System.out.println(Arrays.toString(constructor.getParameterTypes())); // prints "[int]" Object myObj = constructor.newInstance(10); Method myObjMethod = myObj.getClass().getMethod("method1", null); myObjMethod.invoke(myObj, null); //prints "Method1 impl." System.out.println("((ConcreteClass)myObj).publicInt : " + ((ConcreteClass)myObj).publicInt); Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null); System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes())); // prints "[]" HashMap<String,String> myMap = (HashMap<String,String>) hashMapConstructor.newInstance(null); } }
댓글
댓글 쓰기