etc./StackOverFlow

리플렉션이란 무엇이며 왜 유용한가요?

청렴결백한 만능 재주꾼 2021. 11. 29. 22:34
반응형

질문자 :Lehane


리플렉션이란 무엇이며 왜 유용한가요?

저는 특히 Java 관심이 있지만 원칙은 모든 언어에서 동일하다고 가정합니다.



이름 리플렉션은 동일한 시스템(또는 자체)에서 다른 코드를 검사할 수 있는 코드를 설명하는 데 사용됩니다.

예를 들어, Java에 알 수 없는 유형의 객체가 있고 존재하는 경우 'doSomething' 메소드를 호출하고 싶다고 가정하십시오. Java의 정적 유형 지정 시스템은 객체가 알려진 인터페이스를 준수하지 않는 한 실제로 이를 지원하도록 설계되지 않았습니다. 그러나 리플렉션을 사용하면 코드에서 객체를 보고 'doSomething'이라는 메서드가 있는지 확인한 다음 호출할 수 있습니다. 고 싶어요.

따라서 Java에서 이에 대한 코드 예제를 제공하려면(문제의 객체가 foo라고 상상해 보세요):

 Method method = foo.getClass().getMethod("doSomething", null); method.invoke(foo, null);

Java의 매우 일반적인 사용 사례 중 하나는 주석과 함께 사용하는 것입니다. 예를 들어 JUnit 4는 리플렉션을 사용하여 @Test 주석으로 태그가 지정된 메서드에 대한 클래스를 살펴본 다음 단위 테스트를 실행할 때 이를 호출합니다.

http://docs.oracle.com/javase/tutorial/reflect/index.html 에서 시작하는 데 도움이 되는 몇 가지 좋은 리플렉션 예제가 있습니다.

그리고 마지막으로, 그 개념은 (C#과 같은) 리플렉션을 지원하는 다른 정적으로 형식화된 언어에서 매우 유사합니다. 동적으로 유형이 지정된 언어에서 위에서 설명한 사용 사례는 덜 필요하지만(컴파일러가 모든 개체에서 메서드를 호출할 수 있도록 허용하므로 존재하지 않는 경우 런타임에 실패함) 표시되거나 표시된 메서드를 찾는 두 번째 경우입니다. 특정 방식으로 작업하는 것은 여전히 일반적입니다.

댓글에서 업데이트:

시스템의 코드를 검사하고 객체 유형을 확인하는 기능은 반영이 아니라 유형 내성입니다. 그런 다음 리플렉션은 내부 성찰을 사용하여 런타임에 수정할 수 있는 기능입니다. 일부 언어는 내성을 지원하지만 리플렉션은 지원하지 않으므로 구별이 필요합니다. 그러한 예 중 하나는 C++입니다.


Matt Sheppard

리플렉션 은 런타임에 클래스, 메서드, 속성 등을 검사하고 동적으로 호출하는 언어의 기능입니다.

예를 들어, Java의 모든 객체에는 getClass() Object 로 선언한 경우) 객체의 클래스를 결정할 수 있습니다. 이것은 사소해 보일 수 있지만, C++ 와 같이 덜 동적인 언어에서는 리플렉션이 불가능합니다. 고급 사용을 통해 메서드, 생성자 등을 나열하고 호출할 수 있습니다.

리플렉션을 사용하면 컴파일 타임에 모든 것을 "알" 필요가 없는 프로그램을 작성할 수 있으므로 런타임에 함께 묶일 수 있으므로 보다 동적으로 만들 수 있으므로 리플렉션이 중요합니다. 코드는 알려진 인터페이스에 대해 작성할 수 있지만 사용되는 실제 클래스는 구성 파일의 리플렉션을 사용하여 인스턴스화할 수 있습니다.

많은 현대 프레임워크가 바로 이러한 이유로 리플렉션을 광범위하게 사용합니다. 대부분의 다른 현대 언어도 리플렉션을 사용하며 스크립팅 언어(예: Python)에서는 해당 언어의 일반 프로그래밍 모델 내에서 더 자연스럽게 느껴지기 때문에 훨씬 더 긴밀하게 통합됩니다.


Liedman

내가 가장 좋아하는 리플렉션 사용 중 하나는 아래 Java 덤프 방법입니다. 모든 객체를 매개변수로 사용하고 Java 리플렉션 API를 사용하여 모든 필드 이름과 값을 출력합니다.

 import java.lang.reflect.Array; import java.lang.reflect.Field; public static String dump(Object o, int callCount) { callCount++; StringBuffer tabs = new StringBuffer(); for (int k = 0; k < callCount; k++) { tabs.append("\t"); } StringBuffer buffer = new StringBuffer(); Class oClass = o.getClass(); if (oClass.isArray()) { buffer.append("\n"); buffer.append(tabs.toString()); buffer.append("["); for (int i = 0; i < Array.getLength(o); i++) { if (i < 0) buffer.append(","); Object value = Array.get(o, i); if (value.getClass().isPrimitive() || value.getClass() == java.lang.Long.class || value.getClass() == java.lang.String.class || value.getClass() == java.lang.Integer.class || value.getClass() == java.lang.Boolean.class ) { buffer.append(value); } else { buffer.append(dump(value, callCount)); } } buffer.append(tabs.toString()); buffer.append("]\n"); } else { buffer.append("\n"); buffer.append(tabs.toString()); buffer.append("{\n"); while (oClass != null) { Field[] fields = oClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { buffer.append(tabs.toString()); fields[i].setAccessible(true); buffer.append(fields[i].getName()); buffer.append("="); try { Object value = fields[i].get(o); if (value != null) { if (value.getClass().isPrimitive() || value.getClass() == java.lang.Long.class || value.getClass() == java.lang.String.class || value.getClass() == java.lang.Integer.class || value.getClass() == java.lang.Boolean.class ) { buffer.append(value); } else { buffer.append(dump(value, callCount)); } } } catch (IllegalAccessException e) { buffer.append(e.getMessage()); } buffer.append("\n"); } oClass = oClass.getSuperclass(); } buffer.append(tabs.toString()); buffer.append("}\n"); } return buffer.toString(); }

Ben Williams

반사의 사용

리플렉션은 일반적으로 Java 가상 머신에서 실행되는 애플리케이션의 런타임 동작을 검사하거나 수정하는 기능이 필요한 프로그램에서 사용됩니다. 이것은 비교적 고급 기능이며 언어의 기본 사항을 잘 알고 있는 개발자만 사용해야 합니다. 이러한 경고를 염두에 두고 리플렉션은 강력한 기술이며 애플리케이션이 그렇지 않으면 불가능한 작업을 수행할 수 있도록 합니다.

확장성 기능

응용 프로그램은 정규화된 이름을 사용하여 확장성 개체의 인스턴스를 만들어 외부 사용자 정의 클래스를 사용할 수 있습니다. 클래스 브라우저 및 시각적 개발 환경 클래스 브라우저는 클래스의 멤버를 열거할 수 있어야 합니다. 시각적 개발 환경은 개발자가 올바른 코드를 작성하는 데 도움이 되도록 리플렉션에서 사용할 수 있는 형식 정보를 사용함으로써 이점을 얻을 수 있습니다. 디버거 및 테스트 도구 디버거는 클래스의 개인 멤버를 검사할 수 있어야 합니다. 테스트 하네스는 리플렉션을 사용하여 클래스에 정의된 검색 가능한 세트 API를 체계적으로 호출하여 테스트 스위트에서 높은 수준의 코드 커버리지를 보장할 수 있습니다.

반사의 단점

리플렉션은 강력하지만 무분별하게 사용해서는 안 됩니다. 리플렉션을 사용하지 않고 작업을 수행할 수 있다면 사용을 피하는 것이 좋습니다. 리플렉션을 통해 코드에 액세스할 때 다음 사항에 유의해야 합니다.

  • 성능 오버헤드

리플렉션에는 동적으로 해결되는 유형이 포함되기 때문에 특정 Java 가상 머신 최적화를 수행할 수 없습니다. 결과적으로 반사 작업은 반사되지 않는 작업보다 성능이 느리고 성능에 민감한 응용 프로그램에서 자주 호출되는 코드 섹션에서는 피해야 합니다.

  • 보안 제한

리플렉션에는 보안 관리자에서 실행할 때 존재하지 않을 수 있는 런타임 권한이 필요합니다. 이것은 애플릿과 같이 제한된 보안 컨텍스트에서 실행되어야 하는 코드에 대한 중요한 고려 사항입니다.

  • 내부 노출

리플렉션을 사용하면 개인 필드 및 메서드에 액세스하는 것과 같이 반사되지 않는 코드에서 불법적인 작업을 코드에서 수행할 수 있으므로 리플렉션을 사용하면 예기치 않은 부작용이 발생할 수 있으며, 이로 인해 코드가 제대로 작동하지 않고 이식성이 손상될 수 있습니다. 반사 코드는 추상화를 깨뜨리므로 플랫폼 업그레이드에 따라 동작이 변경될 수 있습니다.

출처: 리플렉션 API


Desmond Smith

리플렉션은 애플리케이션이나 프레임워크가 아직 작성되지 않은 코드로 작업할 수 있도록 하는 핵심 메커니즘입니다!

일반적인 web.xml 파일을 예로 들어 보겠습니다. 여기에는 중첩된 서블릿 클래스 요소가 포함된 서블릿 요소 목록이 포함됩니다. 서블릿 컨테이너는 web.xml 파일을 처리하고 리플렉션을 통해 각 서블릿 클래스의 새 인스턴스를 생성합니다.

또 다른 예로 JAXP( Java API for XML Parsing)가 있습니다. XML 파서 공급자가 리플렉션을 통해 새 인스턴스를 구성하는 데 사용되는 잘 알려진 시스템 속성을 통해 '플러그인'되는 경우.

마지막으로 가장 포괄적인 예는 리플렉션을 사용하여 빈을 생성하고 프록시를 많이 사용하는 Spring입니다.


toolkit

모든 언어가 리플렉션을 지원하는 것은 아니지만 원칙은 일반적으로 리플렉션을 지원하는 언어에서 동일합니다.

반영은 프로그램의 구조를 "반영"하는 능력입니다. 또는 더 구체적입니다. 가지고 있는 객체와 클래스를 살펴보고 구현하는 메서드, 필드 및 인터페이스에 대한 정보를 프로그래밍 방식으로 다시 가져옵니다. 주석과 같은 것을 볼 수도 있습니다.

많은 상황에서 유용합니다. 클래스를 코드에 동적으로 플러그인할 수 있기를 원하는 모든 곳. 많은 객체 관계형 매퍼는 어떤 객체를 사용할지 미리 알지 않고도 데이터베이스에서 객체를 인스턴스화할 수 있도록 리플렉션을 사용합니다. 플러그인 아키텍처는 리플렉션이 유용한 또 다른 장소입니다. 코드를 동적으로 로드하고 플러그인으로 사용할 올바른 인터페이스를 구현하는 유형이 있는지 확인하는 것은 이러한 상황에서 중요합니다.


Mendelt

리플렉션을 사용하면 구현에 대한 사전 지식 없이 런타임에 동적으로 새 개체의 인스턴스화, 메서드 호출 및 클래스 변수에 대한 get/set 작업을 수행할 수 있습니다.

 Class myObjectClass = MyObject.class; Method[] method = myObjectClass.getMethods(); //Here the method takes a string parameter if there is no param, put null. Method method = aClass.getMethod("method_name", String.class); Object returnValue = method.invoke(null, "parameter-value1");

위의 예에서 null 매개 변수는 메서드를 호출하려는 개체입니다. 메서드가 정적이면 null을 제공합니다. 메서드가 정적이 아닌 경우 호출하는 동안 null 대신 유효한 MyObject 인스턴스를 제공해야 합니다.

리플렉션을 사용하면 클래스의 비공개 멤버/메서드에 액세스할 수도 있습니다.

 public class A{ private String str= null; public A(String str) { this.str= str; } }

.

 A obj= new A("Some value"); Field privateStringField = A.class.getDeclaredField("privateString"); //Turn off access check for this field privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(obj); System.out.println("fieldValue = " + fieldValue);
  • 클래스 검사(introspection이라고도 함)를 위해 리플렉션 패키지( java.lang.reflect )를 가져올 필요가 없습니다. java.lang.Class 통해 액세스할 수 있습니다.

리플렉션은 매우 강력한 API이지만 런타임에 모든 유형을 해결하기 때문에 과도하게 사용하면 애플리케이션 속도가 느려질 수 있습니다.


Nikhil Shekhar

Java Reflection은 매우 강력하며 매우 유용할 수 있습니다. Java Reflection을 사용하면 컴파일 타임에 클래스, 메서드 등의 이름을 몰라도 런타임에 클래스, 인터페이스, 필드 및 메서드를 검사할 수 있습니다. 또한 리플렉션을 사용하여 새 개체를 인스턴스화하고 메서드를 호출하고 필드 값을 가져오거나 설정할 수 있습니다.

리플렉션을 사용하는 방법을 보여주는 빠른 Java 리플렉션 예제:

 Method[] methods = MyObject.class.getMethods(); for(Method method : methods){ System.out.println("method = " + method.getName()); }

이 예제에서는 MyObject라는 클래스에서 Class 개체를 가져옵니다. 클래스 개체를 사용하여 예제에서는 해당 클래스의 메서드 목록을 가져오고 메서드를 반복하고 이름을 출력합니다.

이 모든 것이 정확히 어떻게 작동하는지 여기에 설명되어 있습니다.

편집 : 거의 1년 후에 리플렉션에 대해 읽는 동안 리플렉션을 거의 사용하지 않았기 때문에 이 답변을 편집하고 있습니다.

  • Spring은 다음과 같은 빈 구성을 사용합니다.


 <bean id="someID" class="com.example.Foo"> <property name="someField" value="someValue" /> </bean>

Spring 컨텍스트가 이 < bean> 요소를 처리할 때 "com.example.Foo" 인수와 함께 Class.forName(String)을 사용하여 해당 클래스를 인스턴스화합니다.

그런 다음 다시 리플렉션을 사용하여 < property > 요소에 대한 적절한 setter를 가져오고 해당 값을 지정된 값으로 설정합니다.

  • Junit은 특히 Private/Protected 메소드를 테스트하기 위해 Reflection을 사용합니다.

Private 메서드의 경우

 Method method = targetClass.getDeclaredMethod(methodName, argClasses); method.setAccessible(true); return method.invoke(targetObject, argObjects);

개인 필드의 경우,

 Field field = targetClass.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value);

VeKe

예시:

API 메소드를 사용하여 얻은 객체를 애플리케이션에 제공하는 원격 애플리케이션을 예로 들어 보겠습니다. 이제 개체를 기반으로 일종의 계산을 수행해야 할 수도 있습니다.

공급자는 객체가 3가지 유형이 될 수 있음을 보장하며 우리는 객체의 유형에 따라 계산을 수행해야 합니다.

따라서 우리는 각각 다른 논리를 포함하는 3개의 클래스로 구현할 수 있습니다. 분명히 개체 정보는 런타임에 사용할 수 있으므로 계산을 수행하기 위해 정적으로 코딩할 수 없으므로 반사는 기반으로 계산을 수행하는 데 필요한 클래스의 개체를 인스턴스화하는 데 사용됩니다. 제공자로부터 받은 객체.


human.js

반사에 대한 간단한 예입니다. 체스 게임에서는 런타임에 사용자가 무엇을 움직일지 모릅니다. 리플렉션을 사용하여 런타임에 이미 구현된 메서드를 호출할 수 있습니다.

 public class Test { public void firstMoveChoice(){ System.out.println("First Move"); } public void secondMOveChoice(){ System.out.println("Second Move"); } public void thirdMoveChoice(){ System.out.println("Third Move"); } public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Test test = new Test(); Method[] method = test.getClass().getMethods(); //firstMoveChoice method[0].invoke(test, null); //secondMoveChoice method[1].invoke(test, null); //thirdMoveChoice method[2].invoke(test, null); } }

Isuru Jayakantha

리플렉션 은 런타임 에 메서드, 클래스, 인터페이스 의 동작을 검사하거나 수정하는 데 사용되는 API입니다.

  1. 리플렉션에 필요한 클래스는 java.lang.reflect package 제공됩니다.
  2. 리플렉션은 객체가 속한 클래스에 대한 정보와 객체를 사용하여 실행할 수 있는 해당 클래스의 메서드에 대한 정보를 제공합니다.
  3. 리플렉션을 통해 사용된 액세스 지정자와 상관없이 런타임에 메서드를 호출할 수 있습니다.

java.langjava.lang.reflect 패키지는 자바 리플렉션을 위한 클래스를 제공합니다.

Reflection 은 다음에 대한 정보를 얻는 데 사용할 수 있습니다.

  1. 클래스 getClass() 메서드는 객체가 속한 클래스의 이름을 가져오는 데 사용됩니다.

  2. 생성자 getConstructors() 메서드는 객체가 속한 클래스의 공용 생성자를 가져오는 데 사용됩니다.

  3. 메소드 getMethods() 메소드는 객체가 속한 클래스의 공용 메소드를 가져오는 데 사용됩니다.

Reflection API 는 주로 다음에서 사용됩니다.

IDE(통합 개발 환경) 예: Eclipse, MyEclipse, NetBeans 등
디버거 및 테스트 도구 등

리플렉션 사용의 장점:

확장 기능: 응용 프로그램은 정규화된 이름을 사용하여 확장 개체의 인스턴스를 만들어 외부 사용자 정의 클래스를 사용할 수 있습니다.

디버깅 및 테스트 도구: 디버거는 리플렉션 속성을 사용하여 클래스의 비공개 멤버를 검사합니다.

단점:

성능 오버헤드: 반사 작업은 비 반사 작업보다 성능이 느리고 성능에 민감한 응용 프로그램에서 자주 호출되는 코드 섹션에서는 피해야 합니다.

내부 노출: 반사 코드는 추상화를 깨뜨리므로 플랫폼 업그레이드에 따라 동작이 변경될 수 있습니다.

참조: 자바 리플렉션 javarevisited.blogspot.in


roottraveller

내 이해에 따라 :

리플렉션을 사용하면 프로그래머가 프로그램의 엔터티에 동적으로 액세스할 수 있습니다. 즉, 프로그래머가 클래스나 해당 메서드에 대해 알지 못하는 경우 응용 프로그램을 코딩하는 동안 리플렉션을 사용하여 런타임에 해당 클래스를 동적으로 사용할 수 있습니다.

클래스 이름이 자주 변경되는 시나리오에서 자주 사용됩니다. 이러한 상황이 발생하면 프로그래머가 응용 프로그램을 다시 작성하고 클래스 이름을 계속해서 변경하는 것이 복잡합니다.

대신 리플렉션을 사용하면 클래스 이름이 변경될 가능성에 대해 걱정할 필요가 있습니다.


pramod

리플렉션은 프로그램의 런타임 정보에 액세스하고 프로그램의 동작을 수정할 수 있도록 하는 함수 집합입니다(일부 제한 있음).

프로그램의 메타 정보에 따라 런타임 동작을 변경할 수 있기 때문에 유용합니다. 즉, 함수의 반환 유형을 확인하고 상황을 처리하는 방식을 변경할 수 있습니다.

예를 들어 C#에서는 어셈블리(.dll)를 런타임에 로드하여 검사하고, 클래스를 탐색하고, 발견한 내용에 따라 조치를 취할 수 있습니다. 또한 런타임에 클래스의 인스턴스를 만들고 해당 메서드를 호출하는 등의 작업을 수행할 수 있습니다.

어디에 유용할까요? 매번 유용하지는 않지만 구체적인 상황에 유용합니다. 예를 들어 로깅 목적으로 클래스 이름을 가져오고 구성 파일에 지정된 내용에 따라 이벤트 핸들러를 동적으로 생성하는 데 사용할 수 있습니다.


Jorge Córdoba

나는 단지 나열된 모든 것에 몇 가지 요점을 추가하고 싶습니다.

Reflection API 를 사용하면 모든 객체에 대한 toString() 메서드를 작성할 수 있습니다.

디버깅에 유용합니다.

다음은 몇 가지 예입니다.

 class ObjectAnalyzer { private ArrayList<Object> visited = new ArrayList<Object>(); /** * Converts an object to a string representation that lists all fields. * @param obj an object * @return a string with the object's class name and all field names and * values */ public String toString(Object obj) { if (obj == null) return "null"; if (visited.contains(obj)) return "..."; visited.add(obj); Class cl = obj.getClass(); if (cl == String.class) return (String) obj; if (cl.isArray()) { String r = cl.getComponentType() + "[]{"; for (int i = 0; i < Array.getLength(obj); i++) { if (i > 0) r += ","; Object val = Array.get(obj, i); if (cl.getComponentType().isPrimitive()) r += val; else r += toString(val); } return r + "}"; } String r = cl.getName(); // inspect the fields of this class and all superclasses do { r += "["; Field[] fields = cl.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); // get the names and values of all fields for (Field f : fields) { if (!Modifier.isStatic(f.getModifiers())) { if (!r.endsWith("[")) r += ","; r += f.getName() + "="; try { Class t = f.getType(); Object val = f.get(obj); if (t.isPrimitive()) r += val; else r += toString(val); } catch (Exception e) { e.printStackTrace(); } } } r += "]"; cl = cl.getSuperclass(); } while (cl != null); return r; } }

catch23

반사는 대상이 자신의 모습을 볼 수 있도록 하는 것입니다. 이 주장은 반성과 관련이 없는 것 같습니다. 사실, 이것은 "자기 식별" 능력입니다.

리플렉션 자체는 Java 및 C#과 같이 자기 인식 및 자기 감지 기능이 부족한 언어를 가리키는 단어입니다. 그들은 자기 지식의 능력이 없기 때문에 우리가 그것이 어떻게 생겼는지 관찰하고 싶을 때 우리는 그것이 어떻게 생겼는지에 대해 반성할 또 다른 것이 있어야 합니다. Ruby 및 Python과 같은 뛰어난 동적 언어는 다른 개인의 도움 없이도 자신의 반영을 인식할 수 있습니다. Java의 객체는 리플렉션 클래스의 객체인 거울 없이는 어떻게 생겼는지 인지할 수 없지만 Python의 객체는 거울 없이 인지할 수 있습니다. 그래서 자바에서 리플렉션이 필요합니다.


Marcus Thornton

자바 문서 페이지에서

java.lang.reflect 패키지는 클래스와 객체에 대한 반사 정보를 얻기 위한 클래스와 인터페이스를 제공합니다. 리플렉션을 사용하면 로드된 클래스의 필드, 메서드 및 생성자에 대한 정보에 프로그래밍 방식으로 액세스할 수 있으며, 보안 제한 내에서 기본 대응 항목에서 작동하기 위해 반사된 필드, 메서드 및 생성자를 사용할 수 있습니다.

AccessibleObject ReflectPermission 이 사용 가능한 경우 액세스 검사를 억제할 수 있습니다.

java.lang.Class 와 함께 이 패키지의 클래스는 디버거, 인터프리터, 개체 검사기, 클래스 브라우저와 같은 응용 프로그램과 대상 개체의 공용 멤버에 액세스해야 하는 Object SerializationJavaBeans 런타임 클래스) 또는 지정된 클래스에서 선언한 멤버

다음과 같은 기능을 포함합니다.

  1. 클래스 객체 획득,
  2. 클래스의 속성(필드, 메서드, 생성자) 검사,
  3. 필드 값 설정 및 가져오기,
  4. 호출 방법,
  5. 개체의 새 인스턴스 만들기.

Class 클래스에 의해 노출된 메소드에 대한 이 문서 링크를 살펴보십시오.

기사 (Dennis Sosnoski, Sosnoski Software Solutions, Inc 사장) 및 이 기사 (security-explorations pdf):

Reflection을 사용하는 것보다 상당한 단점을 볼 수 있습니다.

반사 사용자:

  1. 프로그램 구성 요소를 동적으로 연결하는 매우 다양한 방법을 제공합니다.
  2. 매우 일반적인 방식으로 개체와 함께 작동하는 라이브러리를 만드는 데 유용합니다.

반사의 단점:

  1. 리플렉션은 필드 및 메서드 액세스에 사용할 때 직접 코드보다 훨씬 느립니다.
  2. 코드 내부에서 실제로 무슨 일이 일어나고 있는지 불명확할 수 있습니다.
  3. 소스 코드를 우회하면 유지 관리 문제가 발생할 수 있습니다.
  4. 리플렉션 코드는 해당 직접 코드보다 복잡합니다.
  5. 데이터 액세스 보호 및 유형 안전과 같은 주요 Java 보안 제약 조건을 위반할 수 있습니다.

일반적인 남용:

  1. 제한된 클래스 로드,
  2. 제한된 클래스의 생성자, 메소드 또는 필드에 대한 참조 얻기,
  3. 새로운 객체 인스턴스 생성, 메소드 호출, 제한된 클래스의 필드 값 가져오기 또는 설정.

반사 기능 남용에 관한 이 SE 질문을 살펴보십시오.

Java에서 개인 필드를 어떻게 읽습니까?

요약:

시스템 코드 내에서 수행되는 기능의 안전하지 않은 사용은 또한 Java 보안 모드의 손상으로 쉽게 이어질 수 있습니다 . l. 따라서 이 기능을 아껴서 사용하십시오.


Ravindra babu

이름 자체에서 알 수 있듯이 런타임에 인스턴스를 동적으로 생성하는 메서드를 호출하는 기능을 제공하는 것과는 별개로 클래스 메서드 등을 포함하는 것을 반영합니다.

실제로 코드를 알지 못하는 상태에서 서비스를 호출하기 위해 많은 프레임워크 및 애플리케이션에서 사용됩니다.


Mohammed Sarfaraz

리플렉션을 사용하면 보다 일반적인 코드를 작성할 수 있습니다. 이를 통해 런타임에 개체를 만들고 런타임에 해당 메서드를 호출할 수 있습니다. 따라서 프로그램을 고도로 매개변수화할 수 있습니다. 또한 외부 세계에 노출된 변수와 메서드를 감지하기 위해 개체와 클래스를 내부 검사할 수 있습니다.


saumik gupta

Reflection 에는 많은 용도가 있습니다. 내가 더 익숙한 것은 즉석에서 코드를 생성할 수 있다는 것입니다.

IE: 동적 클래스, 함수, 생성자 - 모든 데이터 기반(xml/array/sql results/hardcoded/etc..)


Ess Kay

나는 예를 들어 이 질문에 대답하고 싶다. 무엇보다도 Hibernate 프로젝트는 Reflection API 를 사용하여 실행 중인 애플리케이션과 지속성 저장소 사이의 틈을 연결하는 CRUD 도메인에서 사물이 변경되면 Hibernate 는 데이터 저장소에 유지하기 위해 그것에 대해 알아야 하며 그 반대의 경우도 마찬가지입니다.

Lombok Project 작동합니다. 컴파일 타임에 코드를 삽입하기만 하면 코드가 도메인 클래스에 삽입됩니다. (게터와 세터는 괜찮다고 생각합니다)

Hibernate 는 애플리케이션의 빌드 프로세스에 최소한의 영향을 미치기 때문에 reflection 선택했습니다.

그리고 Java 7에는 Reflection API 로 작동하는 MethodHandles 가 있습니다. 프로젝트에서 로거로 작업하기 위해 다음 코드를 복사하여 붙여넣습니다.

 Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

이 경우 오타를 내기 어렵기 때문입니다.


BSeitkazin

예를 들어 설명하는 것이 가장 좋으며 어떤 답변도 그렇게하지 않는 것 같습니다 ...

리플렉션을 사용하는 실용적인 예는 Java로 작성된 Java 언어 서버 또는 PHP로 작성된 PHP 언어 서버 등입니다. 언어 서버는 자동 완성, 정의로 이동, 컨텍스트 도움말, 힌트 유형 등과 같은 IDE 기능을 제공합니다. 모든 태그 이름(자동 완성될 수 있는 단어)을 사용하여 입력할 때 가능한 모든 일치 항목을 표시하려면 언어 서버가 문서 블록 및 개인 멤버를 포함하여 클래스에 대한 모든 것을 검사해야 합니다. 이를 위해서는 해당 클래스의 반영이 필요합니다.

다른 예는 개인 메서드의 단위 테스트입니다. 그렇게 하는 한 가지 방법은 테스트 설정 단계에서 리플렉션을 만들고 메서드의 범위를 공개로 변경하는 것입니다. 물론 개인 메서드를 직접 테스트해서는 안 된다고 주장할 수 있지만 그게 요지는 아닙니다.


cprn

중요한

Java 9부터 package-info.java가 모듈을 리플렉션 액세스로 열지 않는 한 더 이상 리플렉션을 사용할 수 없습니다.

기본적으로 모듈의 모든 패키지에 대한 리플렉션 액세스는 거부됩니다.

Java 9 모듈 이해를 참조하십시오.


RSG

출처 : http:www.stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful

반응형