Java 변수에 대한 동적 캐스팅을 수행하고 싶습니다. 캐스팅 유형은 다른 변수에 저장됩니다.
이것은 일반 캐스팅입니다.
String a = (String) 5;
이것이 내가 원하는거야:
String theType = 'String';
String a = (theType) 5;
이것이 가능합니까? 그렇다면 어떻게해야합니까? 감사!
최신 정보
HashMap
받은 클래스를 채우려 고합니다 .
이것은 생성자입니다.
public ConnectParams(HashMap<String,Object> obj) {
for (Map.Entry<String, Object> entry : obj.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
여기서 문제는 클래스의 일부 변수가 유형 Double
이고 숫자 3이 수신되면 Integer
유형 문제가 있다는 것입니다.
답변
업데이트와 관련하여 Java에서이 문제를 해결하는 유일한 방법은 많은
if
및else
및instanceof
표현식으로 모든 경우를 다루는 코드를 작성하는 것입니다 . 당신이 시도하는 것은 마치 동적 언어로 프로그래밍하는 데 익숙한 것처럼 보입니다. 정적 언어에서는 시도하는 것이 거의 불가능하며 시도하려는 작업에 대해 완전히 다른 접근 방식을 선택할 것입니다. 정적 언어는 동적 언어만큼 유연하지 않습니다. 🙂Java 모범 사례의 좋은 예는 BalusC 의 답변 (예 🙂
ObjectConverter
과 Andreas_D 의 답변 (예 :Adapter
아래)입니다.
말이 안 돼요
String a = (theType) 5;
의 유형 a
은 정적으로 바인딩되어 있으므로이 정적 유형에 String
대한 동적 캐스트를 갖는 것은 의미가 없습니다.
추신 : 예제의 첫 번째 줄은 다음과 같이 작성할 수 Class<String> stringClass = String.class;
있지만 여전히 stringClass
변수를 캐스팅 하는 데 사용할 수 없습니다 .
답변
예 Reflection을 사용하여 가능합니다.
Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
그러나 결과 객체는 Object
유형 의 변수에 저장되어야하므로 그다지 의미가 없습니다 . 주어진 클래스의 변수가 필요한 경우 해당 클래스로 캐스트 할 수 있습니다.
Number
예를 들어 , 주어진 클래스를 얻으려면 :
Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
하지만 여전히 그렇게 할 필요가 없습니다 Number
..
개체를 캐스팅해도 아무것도 변경되지 않습니다. 그것은 단지 인 방법 컴파일러 취급 그것.
이와 같은 작업을 수행하는 유일한 이유는 객체가 주어진 클래스 또는 그 하위 클래스의 인스턴스인지 확인하는 것입니다. 그러나 instanceof
또는 사용하는 것이 더 좋습니다 Class.isInstance()
.
최신 정보
마지막에 따라 업데이트가 진짜 문제는 당신이이 때문이다 Integer
에서 HashMap
A를 할당해야합니다 Double
. 이 경우 할 수있는 일은 필드의 유형을 확인하고 다음 xxxValue()
방법을 사용하는 것 입니다.Number
...
Field f = this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
(내가에서 잘못된 유형을 갖는 아이디어를 좋아하는지 확실하지 않음 Map
)
답변
이를 위해 일종의 작성이 필요합니다 ObjectConverter
. 변환하려는 객체가 있고 변환 할 대상 클래스를 알고있는 경우이 작업을 수행 할 수 있습니다. 이 특별한 경우에는 Field#getDeclaringClass()
.
당신은 찾을 수 있습니다 여기에 이러한 예를 ObjectConverter
. 기본 아이디어를 제공해야합니다. 더 많은 변환 가능성을 원한다면 원하는 인수와 반환 유형을 사용하여 더 많은 메서드를 추가하십시오.
답변
Class.cast()
제공된 매개 변수를 보유한 클래스 인스턴스의 유형으로 동적으로 캐스트 하는 메소드를 사용하여이를 수행 할 수 있습니다. 특정 필드의 클래스 인스턴스를 얻으려면 getType()
해당 필드에서 메서드 를 사용합니다 . 아래에 예제를 주었지만 모든 오류 처리를 생략하고 수정하지 않고 사용해서는 안됩니다.
public class Test {
public String var1;
public Integer var2;
}
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("var1", "test");
map.put("var2", 1);
Test t = new Test();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Field f = Test.class.getField(entry.getKey());
f.set(t, f.getType().cast(entry.getValue()));
}
System.out.println(t.var1);
System.out.println(t.var2);
}
}
답변
아래와 같이 간단한 castMethod를 작성할 수 있습니다.
private <T> T castObject(Class<T> clazz, Object object) {
return (T) object;
}
귀하의 방법에서 다음과 같이 사용해야합니다.
public ConnectParams(HashMap<String,Object> object) {
for (Map.Entry<String, Object> entry : object.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, castObject(entry.getValue().getClass(), entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
답변
작동하며 접근 방식에 대한 일반적인 패턴 인 어댑터 패턴도 있습니다. 그러나 물론 (1) 자바 프리미티브를 객체로 캐스팅하는 데는 작동하지 않으며 (2) 클래스는 적응 가능해야합니다 (보통 사용자 정의 인터페이스를 구현하여).
이 패턴으로 다음과 같이 할 수 있습니다.
Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
Wolf 클래스의 getAdapter 메소드 :
public Object getAdapter(Class clazz) {
if (clazz.equals(Sheep.class)) {
// return a Sheep implementation
return getWolfDressedAsSheep(this);
}
if (clazz.equals(String.class)) {
// return a String
return this.getName();
}
return null; // not adaptable
}
당신에게 특별한 아이디어는 불가능합니다. 캐스팅에 문자열 값을 사용할 수 없습니다.
답변
당신의 문제는 “동적 캐스팅”의 부족이 아닙니다. 주조 Integer
로하는 것은 Double
전혀 불가능하다. Java에 한 유형의 객체, 호환되지 않을 수있는 유형의 필드를 제공하고 유형간에 변환하는 방법을 자동으로 파악하도록하는 것 같습니다.
이런 종류의 것은 Java 및 IMO와 같은 강력한 유형의 언어에 대한 혐오입니다.
실제로 무엇을하려고합니까? 반사의 모든 사용은 꽤 비린내처럼 보입니다.
