source

java: 어떤 유형에서 다른 유형으로 변수를 동적으로 캐스팅하려면 어떻게 해야 합니까?

manysource 2023. 1. 27. 21:22

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으로 볼 수 Integer을 사용하다

예, 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에 할당되어야 한다.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이걸 위해서.변환할 오브젝트가 있고 변환할 타겟클래스를 알고 있는 경우 이 작업을 수행할 수 있습니다.이 경우 타깃클래스는 에 의해 취득할 수 있습니다.

여기서 이러한 예시를 찾을 수 있습니다.ObjectConverter기본적인 생각이 떠오를 겁니다.변환 가능성을 높이려면 원하는 인수와 반환 유형을 사용하여 메서드를 추가합니다.

관해 이은 모든 입니다.if ★★★★★★★★★★★★★★★★★」else ★★★★★★★★★★★★★★★★★」instanceof할 때 하는 것처럼 .실행하려는 작업은 동적 언어로 프로그래밍하는 데 사용되는 것처럼 보입니다.정적 언어에서는 시도하려는 작업이 거의 불가능하며 시도하려는 작업에 대해 완전히 다른 방법을 선택할 수 있습니다. : ) 。

Java의 베스트 프랙티스의 좋은 예는 BalusC의 답변입니다.ObjectConverterAndreas_D의 답변(예:Adapter를 참조해 주세요.를 참조해 주세요.


그건 말이 안 돼요

String a = (theType) 5;

의 of의 a.String따라서 이 스태틱타입에 다이내믹캐스트를 하는 것은 의미가 없습니다.

PS: 의 첫 번째 은 '아까보다'로 쓸 수.Class<String> stringClass = String.class;'어울리지 않다', '어울리지 않다'는 쓸 수 요.stringClass변수를 캐스팅합니다.

이 작업은 지정된 파라미터를 보유하고 있는 클래스인스턴스 유형에 동적으로 캐스팅하는 메서드를 사용하여 수행할 수 있습니다.특정 필드의 클래스 인스턴스를 가져오려면 해당 필드에서 메서드를 사용합니다.아래에 예를 제시하겠습니다만, 에러 처리는 모두 생략되어 있기 때문에, 수정하지 않고 사용할 수 없습니다.

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) Java 프리미티브를 오브젝트에 캐스팅하는 데는 효과가 없으며 (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에 한 가지 유형의 오브젝트, 호환되지 않을 수 있는 유형의 필드를 부여하여 이러한 유형의 변환 방법을 자동으로 알아내려고 하는 것 같습니다.

자바나 IMO와 같은 강력한 타입의 언어에는 매우 타당한 이유로 이러한 종류의 것이 거부됩니다.

정말 뭘 하려고 하는 거야?성찰의 모든 사용은 꽤 수상해 보인다.

이러지마세요.대신 적절한 매개 변수화된 생성자를 사용하십시오.접속 파라미터의 세트와 유형은 모두 고정되어 있기 때문에 이 모든 것을 동적으로 실행하는 것은 의미가 없습니다.

즉, 대부분의 스크립트 언어(Perl 등)와 비정적 컴파일 시간 언어(Pick 등)는 자동 런타임 동적 문자열에서 객체(상대적 임의)로의 변환을 지원합니다.이는 Java에서도 활자 안전성을 잃지 않고 달성할 수 있으며, 정적으로 타이핑된 좋은 언어들은 동적 캐스팅으로 나쁜 짓을 하는 다른 언어들의 불쾌한 부작용 없이 제공할 수 있다.몇 가지 의심스러운 계산을 수행하는 Perl의 예:

print ++($foo = '99');  # prints '100'
print ++($foo = 'a0');  # prints 'a1'

Java에서는, 이것을 「크로스 캐스팅」이라고 하는 방법을 사용하는 것으로, IMHO 를 보다 잘 실행할 수 있습니다.크로스캐스팅에서는 리플렉션은 다음 정적 방법을 통해 동적으로 검출되는 컨스트럭터 및 메서드의 느린 로드 캐시에서 사용됩니다.

Object fromString (String value, Class targetClass)

안타깝게도 Class.cast()와 같은 임베디드 Java 메서드는 String에서 BigDecimal로, String에서 Integer로, 또는 지원되는 클래스 계층이 없는 다른 변환에 대해 이 작업을 수행하지 않습니다.저로서는, 이것을 실현하기 위한 완전히 동적인 방법을 제공하는 것이 포인트입니다.이것에 대해서는, 이전의 레퍼런스가 올바른 어프로치라고는 생각하지 않습니다만, 모든 변환을 코드화할 필요가 있습니다.간단히 말해서, 구현은 합법적/가능성이 있는 경우 스트링에서 캐스트하는 것입니다.

따라서 해결책은 다음 중 하나의 공공 구성원을 찾는 단순한 반영입니다.

STRING_CLASS_ARRAY = (새 클래스[] {String.class});

a) 멤버 = targetClass.getMethod(method.getName(), STRING_CLASS_ARray), b) 멤버 = targetClass.getConstructor(STRING_CLASS_ARray);

모든 프리미티브(Integer, Long 등)와 모든 기본(BigInteger, BigDecimal 등) 및 java.regex도 있습니다.패턴은 모두 이 접근방식으로 커버됩니다.저는 이것을 보다 엄격한 확인이 필요한 임의의 String 값 입력이 많은 프로덕션 프로젝트에서 큰 성공을 거두었습니다.이 접근법에서는 메서드가 존재하지 않거나 메서드가 호출되었을 때 예외가 느려집니다(BigDecimal에 대한 비숫자 입력이나 패턴에 대한 부정한 RegEx 등의 값이기 때문에).이러한 예외는 타깃클래스 고유의 로직을 체크합니다.

여기에는 몇 가지 단점이 있습니다.

1) 반성을 잘 이해할 필요가 있다(이것은 조금 복잡하고 초보자용이 아니다).2) 일부 Java 클래스 및 실제로 서드파티 라이브러리가 올바르게 코딩되지 않았습니다.즉, 단일 문자열 인수를 입력으로 사용하여 대상 클래스의 인스턴스를 반환하는 메서드가 있지만, 이는 사용자가 생각하는 것과 다릅니다.Integer 클래스를 고려합니다.

static Integer getInteger(String nm)
      Determines the integer value of the system property with the specified name.

위의 메서드는 원래 int를 래핑하는 개체로서의 Integrates와는 전혀 관계가 없습니다.Reflection에서는 String에서 Integer를 잘못 작성할 수 있는 후보로서 디코드, value of 및 constructor Members를 찾습니다.이 모든 것은 입력 데이터를 제어할 수 없지만 Integer가 가능한지 알고 싶은 대부분의 임의 String 변환에 적합합니다.

위의 문제를 해결하려면 예외를 슬로우하는 메서드를 찾는 것이 좋습니다.이러한 객체의 인스턴스를 생성하는 잘못된 입력 값이 예외를 슬로우해야 하기 때문입니다.유감스럽게도 예외의 체크 표시가 되어 있는지 여부에 따라 구현이 달라집니다.Integer.valueOf(String)가 체크 마크를 붙입니다.예를 들어 FormatException은 리플렉션 조회 중 Pattern.compile() 예외를 찾을 수 없습니다.이 동적 "크로스 캐스팅" 접근법의 실패가 아니라 오브젝트 작성 방법의 예외 선언에 대한 매우 비표준적인 구현이라고 생각합니다.

위의 구현 방법에 대해 더 자세한 내용을 알고 싶은 사람이 있으면 알려주세요.그러나 이 솔루션은 훨씬 유연하고 확장성이 뛰어나고 타입 안전의 좋은 부분을 잃지 않고 코드를 줄일 수 있다고 생각합니다.물론, 항상 「데이터를 아는 것」이 최선입니다만, 많은 사람들이 알고 있듯이, 델은 관리 대상외의 컨텐츠의 수신자일 뿐이며, 적절히 사용하기 위해서 전력을 다하지 않으면 안 되는 경우가 있습니다.

건배.

오래된 글이지만 뭔가 기여할 수 있을 것 같아요.

항상 다음과 같은 작업을 수행할 수 있습니다.

package com.dyna.test;  

import java.io.File;  
import java.lang.reflect.Constructor;  

public class DynamicClass{  

  @SuppressWarnings("unchecked")  
  public Object castDynamicClass(String className, String value){  
    Class<?> dynamicClass;  

    try  
    {  
      //We get the actual .class object associated with the specified name  
      dynamicClass = Class.forName(className);  



    /* We get the constructor that received only 
     a String as a parameter, since the value to be used is a String, but we could
easily change this to be "dynamic" as well, getting the Constructor signature from
the same datasource we get the values from */ 


      Constructor<?> cons =  
        (Constructor<?>) dynamicClass.getConstructor(new Class<?>[]{String.class});  

      /*We generate our object, without knowing until runtime 
 what type it will be, and we place it in an Object as 
 any Java object extends the Object class) */  
      Object object = (Object) cons.newInstance(new Object[]{value});  

      return object;  
    }  
    catch (Exception e)  
    {  
      e.printStackTrace();  
    }  
    return null;  
  }  

  public static void main(String[] args)  
  {   
    DynamicClass dynaClass = new DynamicClass();  

    /* 
 We specify the type of class that should be used to represent 
 the value "3.0", in this case a Double. Both these parameters 
 you can get from a file, or a network stream for example. */  
    System.out.println(dynaClass.castDynamicClass("java.lang.Double", "3.0"));  

    /* 
We specify a different value and type, and it will work as 
 expected, printing 3.0 in the above case and the test path in the one below, as the Double.toString() and 
 File.toString() would do. */  
    System.out.println(dynaClass.castDynamicClass("java.io.File", "C:\\testpath"));  
  }  

물론 다른 언어(예를 들어 Python)와 같이 동적 캐스팅은 아닙니다.java는 정적 형식의 언어이기 때문입니다.단, 이를 통해 식별자에 따라 실제로 다른 방법으로 데이터를 로드해야 하는 일부 프린지 사례를 해결할 수 있습니다.또한 String 매개 변수를 사용하여 생성자를 얻는 부분은 해당 매개 변수를 동일한 데이터 원본에서 전달함으로써 보다 유연하게 만들 수 있습니다.예를 들어, 파일에서 사용할 생성자 서명과 사용할 값 목록을 얻을 수 있습니다. 예를 들어, 첫 번째 매개 변수는 String이고, 첫 번째 개체는 String으로 캐스팅되며, 다음 개체는 Integer 등으로 캐스팅됩니다. 그러나 일부 개체는 프로그램 실행 중에 먼저 파일 개체를 얻은 다음 이중화됩니다.

이렇게 하면 이러한 사례를 설명하고 다소 "동적인" 캐스팅을 즉석에서 할 수 있습니다.

이것이 구글 검색에서 계속 나타나기 때문에 누구에게나 도움이 되기를 바랍니다.

저도 최근에 이 작업을 해야겠다고 생각했습니다만, 그 후 코드를 깔끔하게 보이게 하고 OOP를 더 잘 사용할 수 있는 다른 방법을 찾았습니다.

개 각각 하고 있습니다.doSomething()이 메서드에 액세스하려면 먼저 해당 클래스의 인스턴스가 있어야 하는데 모든 형제 클래스에 대해 슈퍼 클래스를 만들고 슈퍼 클래스에서 메서드에 액세스할 수 있게 되었습니다.

아래에서는 "다이나믹 캐스팅"을 대체할 수 있는 두 가지 방법을 보여 줍니다.

// Method 1.
mFragment = getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
switch (mUnitNum) {
case 0:
    ((MyFragment0) mFragment).sortNames(sortOptionNum);
    break;
case 1:
    ((MyFragment1) mFragment).sortNames(sortOptionNum);
    break;
case 2:
    ((MyFragment2) mFragment).sortNames(sortOptionNum);
    break;
}

그리고 현재 사용하고 있는 방법,

// Method 2.
mSuperFragment = (MySuperFragment) getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
mSuperFragment.sortNames(sortOptionNum);

제가 꽤 유용하고 비슷한 요구를 겪고 있는 사람에게도 가능할 것 같은 글을 올려야겠다고 생각했어요.

다음 메서드는 컨트롤러가 반환될 때마다 오브젝트 b 문의 오브젝트 x 인스턴스가 있는 경우 캐스트를 회피하고 쓰기를 회피하기 위해 JavaFX 어플리케이션용으로 작성한 메서드입니다.

public <U> Optional<U> getController(Class<U> castKlazz){
    try {
        return Optional.of(fxmlLoader.<U>getController());
    }catch (Exception e){
        e.printStackTrace();
    }
    return Optional.empty();
}

컨트롤러를 취득하기 위한 메서드 선언은 다음과 같습니다.

public <T> T getController()

클래스 오브젝트를 통해 메서드에 전달된 유형 U를 사용함으로써 메서드 get 컨트롤러로 전송하여 반환해야 할 오브젝트의 유형을 지정할 수 있습니다.잘못된 클래스가 제공된 경우 옵션 객체가 반환되고 예외 발생 시 빈 옵션이 반환되므로 확인할 수 있습니다.

메서드에 대한 최종 호출은 다음과 같습니다(반환되는 옵션오브젝트가 있는 경우 컨슈머가 됩니다).

getController(LoadController.class).ifPresent(controller->controller.onNotifyComplete());

다이나믹 캐스팅에 사용해 보세요.될 거야!!!

    String something = "1234";
    String theType = "java.lang.Integer";
    Class<?> theClass = Class.forName(theType);
    Constructor<?> cons = theClass.getConstructor(String.class);
    Object ob =  cons.newInstance(something);
    System.out.println(ob.equals(1234));

언급URL : https://stackoverflow.com/questions/2127318/java-how-can-i-do-dynamic-casting-of-a-variable-from-one-type-to-another