Java Reflection : 변수 이름을 얻는 방법?
Java Reflection을 사용하면 로컬 변수의 이름을 얻을 수 있습니까? 예를 들어, 내가 이것을 가지고 있다면 :
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
다음과 같이 해당 변수의 이름을 찾을 수있는 메소드를 구현할 수 있습니까?
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
편집 :이 질문과 다릅니다 Java에 함수에 전달 된 변수의 이름을 찾는 방법이 있습니까? 리플렉션을 사용하여 지역 변수의 이름을 결정할 수 있는지에 대한 질문을 더 순수하게 요구하는 반면, 다른 질문 (허용 된 답변 포함)은 변수 값을 테스트하는 데 더 중점을 둡니다.
Java 8부터 일부 로컬 변수 이름 정보는 리플렉션을 통해 사용할 수 있습니다. 아래의 "업데이트" 섹션을 참조하십시오.
완전한 정보는 종종 수업 파일에 저장됩니다. 컴파일 타임 최적화 중 하나는이를 제거하여 공간을 절약하고 약간 난독 화를 제공하는 것입니다. 그러나 존재하는 경우 각 메소드에는 로컬 변수의 유형과 이름 및 범위 내 명령 범위를 나열하는 로컬 변수 테이블 속성이 있습니다.
아마도 ASM 과 같은 바이트 코드 엔지니어링 라이브러리를 사용하면 런타임에이 정보를 검사 할 수 있습니다. 이 정보가 필요하다고 생각할 수있는 유일한 장소는 개발 도구에 있기 때문에 바이트 코드 엔지니어링은 다른 목적에도 유용 할 것입니다.
업데이트 : 이에 대한 지원이 Java 8 에 추가되었습니다 . 이제 매개 변수 (특별한 로컬 변수 클래스) 이름을 리플렉션을 통해 사용할 수 있습니다. 다른 목적으로, 이것은 @ParameterName
의존성 주입 컨테이너에서 사용되는 주석 을 대체하는 데 도움이 될 수 있습니다 .
그것은 것입니다 하지 모두 가능합니다. 변수 이름은 Java 내에서 통신되지 않으며 컴파일러 최적화로 인해 제거 될 수도 있습니다.
편집 (의견 관련) :
함수 매개 변수로 사용해야한다는 생각에서 물러 나면 대안이 있습니다 (사용하지 않을 것입니다-아래 참조).
public void printFieldNames(Object obj, Foo... foos) {
List<Foo> fooList = Arrays.asList(foos);
for(Field field : obj.getClass().getFields()) {
if(fooList.contains(field.get()) {
System.out.println(field.getName());
}
}
}
a == b, a == r, or b == r
동일한 참조를 가진 다른 필드가 있거나 문제가있는 경우 문제가 발생합니다 .
질문이 명확 해 졌으므로 지금 수정하지 않아도됩니다.
( 편집 : 두 개의 이전 답변이 제거되었습니다. 하나는 편집 전에 서있는 질문에 대답하고 다른 하나는 절대적으로 잘못되지 않은 경우 적어도 그것에 가깝습니다. )
( javac -g
) 에 디버그 정보를 사용하여 컴파일하면 로컬 변수의 이름이 .class 파일에 유지됩니다. 예를 들어 다음과 같은 간단한 수업을 들으십시오.
class TestLocalVarNames {
public String aMethod(int arg) {
String local1 = "a string";
StringBuilder local2 = new StringBuilder();
return local2.append(local1).append(arg).toString();
}
}
로 컴파일 한 후 javac -g:vars TestLocalVarNames.java
로컬 변수의 이름은 이제 .class 파일에 있습니다. javap
의 -l
플래그 ( "인쇄 라인 번호 및 로컬 변수 테이블")가이를 표시 할 수 있습니다.
javap -l -c TestLocalVarNames
보여줍니다 :
class TestLocalVarNames extends java.lang.Object{
TestLocalVarNames();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestLocalVarNames;
public java.lang.String aMethod(int);
Code:
0: ldc #2; //String a string
2: astore_2
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
10: astore_3
11: aload_3
12: aload_2
13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: iload_1
17: invokevirtual #6; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: areturn
LocalVariableTable:
Start Length Slot Name Signature
0 24 0 this LTestLocalVarNames;
0 24 1 arg I
3 21 2 local1 Ljava/lang/String;
11 13 3 local2 Ljava/lang/StringBuilder;
}
VM 사양은 우리가 여기서보고있는 것을 설명합니다 :
The
LocalVariableTable
attribute is an optional variable-length attribute of aCode
(§4.7.3) attribute. It may be used by debuggers to determine the value of a given local variable during the execution of a method.
The LocalVariableTable
stores the names and types of the variables in each slot, so it is possible to match them up with the bytecode. This is how debuggers can do "Evaluate expression".
As erickson said, though, there's no way to access this table through normal reflection. If you're still determined to do this, I believe the Java Platform Debugger Architecture (JPDA) will help (but I've never used it myself).
import java.lang.reflect.Field;
public class test {
public int i = 5;
public Integer test = 5;
public String omghi = "der";
public static String testStatic = "THIS IS STATIC";
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
test t = new test();
for(Field f : t.getClass().getFields()) {
System.out.println(f.getGenericType() +" "+f.getName() + " = " + f.get(t));
}
}
}
You can do like this:
Field[] fields = YourClass.class.getDeclaredFields();
//gives no of fields
System.out.println(fields.length);
for (Field field : fields) {
//gives the names of the fields
System.out.println(field.getName());
}
All you need to do is make an array of fields and then set it to the class you want like shown below.
Field fld[] = (class name).class.getDeclaredFields();
for(Field x : fld)
{System.out.println(x);}
For example if you did
Field fld[] = Integer.class.getDeclaredFields();
for(Field x : fld)
{System.out.println(x);}
you would get
public static final int java.lang.Integer.MIN_VALUE
public static final int java.lang.Integer.MAX_VALUE
public static final java.lang.Class java.lang.Integer.TYPE
static final char[] java.lang.Integer.digits
static final char[] java.lang.Integer.DigitTens
static final char[] java.lang.Integer.DigitOnes
static final int[] java.lang.Integer.sizeTable
private static java.lang.String java.lang.Integer.integerCacheHighPropValue
private final int java.lang.Integer.value
public static final int java.lang.Integer.SIZE
private static final long java.lang.Integer.serialVersionUID
see this example :
PersonneTest pt=new PersonneTest();
System.out.println(pt.getClass().getDeclaredFields().length);
Field[]x=pt.getClass().getDeclaredFields();
System.out.println(x[1].getName());
참고URL : https://stackoverflow.com/questions/744226/java-reflection-how-to-get-the-name-of-a-variable
'programing tip' 카테고리의 다른 글
XMLHttpRequest에서 진행하는 방법 (0) | 2020.07.01 |
---|---|
Javascript의 문자열에서 $ {} (달러 기호 및 중괄호)의 의미는 무엇입니까? (0) | 2020.07.01 |
데이터 매퍼, 테이블 데이터 게이트웨이 (게이트웨이), 데이터 액세스 개체 (DAO) 및 리포지토리 패턴의 차이점은 무엇입니까? (0) | 2020.07.01 |
Git : Repository, fork, branch, clone, track에서이 단어의 의미는 무엇입니까? (0) | 2020.07.01 |
Java 휘발성 참조 대 AtomicReference (0) | 2020.07.01 |