Java 반사:변수 이름을 얻는 방법?
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에서 함수에 전달된 변수의 이름을 찾을 수 있는 방법이 있는가?다른 질문(허용된 답안 포함)은 변수의 값 검사에 더 집중되는 반면, 로컬 변수의 이름을 결정하기 위해 반사를 사용할 수 있는지에 대한 질문은 더 순수하게 묻는다는 점에서.
자바 8을 기준으로 반성을 통해 일부 로컬 변수 이름 정보를 이용할 수 있다.아래 "업데이트" 섹션을 참조하십시오.
완전한 정보는 종종 클래스 파일에 저장된다.컴파일 시간 최적화는 그것을 제거하고 공간을 절약하는 것이다(그리고 약간의 모호함을 제공한다).그러나 그것이 존재하는 경우, 각 방법에는 로컬 변수의 유형과 이름, 그리고 해당 변수의 범위에 해당하는 지시 범위를 나열하는 로컬 변수 테이블 속성이 있다.
아마도 ASM과 같은 바이트 코드 엔지니어링 라이브러리는 당신이 런타임에 이 정보를 검사할 수 있게 해줄 것이다.내가 이 정보가 필요하다고 생각할 수 있는 유일한 합리적인 장소는 개발 도구에 있으며, 따라서 바이트 코드 공학은 다른 목적에도 유용할 것 같다.
업데이트: 이에 대한 제한된 지원이 Java 8에 추가됨.매개변수(로컬 변수의 특수 클래스) 이름은 이제 반사를 통해 사용할 수 있다.다른 목적들 중에서, 이것은 대체하는데 도움이 될 수 있다.@ParameterName
Annotations 의존성 주입 용기에 의해 사용하였습니다.종속성 주입 컨테이너가사용하는 주석.
그것은 전혀 가능하지 않다.변수 이름은 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
아니면 동일한 추천을 받아 왔습니다 다른 들판이 있다.또는 동일한 참조를 가진 다른 필드가 있다.
질문이 명확해진 후 이제 EDIT 불필요
(편집: 이전 답변 두 개를 삭제했는데, 하나는 편집 전에 있었던 질문에 대답하기 위한 것이고, 하나는 절대적으로 틀리지는 않더라도 최소한 그것에 근접하기 위한 것이다.)
에 대한 디버그 정보를 사용하여 컴파일하는 경우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 사양에 따르면 다음과 같은 이점을 얻을 수 있으며,
그
LocalVariableTable
속성은 의 선택적 가변 길이 속성이다.Code
(제4.7.3항) 속성.디버거가 메서드를 실행하는 동안 지정된 로컬 변수의 값을 결정하는 데 사용할 수 있다.
그LocalVariableTable
각 슬롯에 변수의 이름과 유형을 저장하므로 바이트 코드와 일치시킬 수 있다.디버거는 이렇게 '평가표현'을 할 수 있다.
그러나 에릭슨이 말했듯이, 정상적인 반성을 통해 이 테이블에 접근할 수 있는 방법은 없다.아직 이 일을 하기로 마음먹었다면, 나는 Java Platform Debugger Architecture(JPDA)가 도움이 될 것이라고 믿는다(하지만 나는 직접 사용해 본 적은 없다).
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));
}
}
}
이렇게 하면 된다.
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());
}
당신이 해야 할 일은 필드 배열을 만든 다음 아래 보이는 것과 같이 당신이 원하는 클래스로 설정하기만 하면 된다.
Field fld[] = (class name).class.getDeclaredFields();
for(Field x : fld)
{System.out.println(x);}
예를 들어, 만약 그랬다면
Field fld[] = Integer.class.getDeclaredFields();
for(Field x : fld)
{System.out.println(x);}
당신은 얻을 수 있을 것이다
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
@Marcel Jackwerth의 대답을 일반에 대해 업데이트한다.
클래스 속성으로만 작업하고 메서드 변수로는 작업하지 않음.
/**
* get variable name as string
* only work with class attributes
* not work with method variable
*
* @param headClass variable name space
* @param vars object variable
* @throws IllegalAccessException
*/
public static void printFieldNames(Object headClass, Object... vars) throws IllegalAccessException {
List<Object> fooList = Arrays.asList(vars);
for (Field field : headClass.getClass().getFields()) {
if (fooList.contains(field.get(headClass))) {
System.out.println(field.getGenericType() + " " + field.getName() + " = " + field.get(headClass));
}
}
}
다음 예제를 참조하십시오.
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' 카테고리의 다른 글
VueJS에서 Angular Service와 동등한 것은? (0) | 2022.05.18 |
---|---|
Vuex 저장소의 슬라이더 설정 값 확인 (0) | 2022.05.18 |
2자바 날짜 인스턴스의 차이를 계산 중입니다 (0) | 2022.05.17 |
Vue.js의 다른 구성 요소에서 호출 방법 (0) | 2022.05.17 |
JS 파일의 Nuxt 액세스 저장소(모듈 모드) (0) | 2022.05.17 |