2009-08-03 6 views
2

추상 클래스가 있습니다 :Java에서 abstract 클래스의 private 필드를 변경하는 방법?

public abstract class AbstractAny { 
    private long period; 

    public void doSomething() { 
    // blah blah blah 
    period = someHardcodedValue; 
    // blah blah blah 
    } 
} 

추상 클래스의 소스를 변경하고 싶지는 않지만 필드 기간 설정 방법에 약간의 유연성을 추가해야합니다. 오버라이드 된 메소드에서 필드 기간의 값을 변경할 수 있습니까? 예를 들면 다음과 같습니다.

public class ConcreteSome extends AbstractAny{ 
    @Override 
    public void doSomething() { 
    try { 
     Field p = super.getClass().getDeclaredField("period"); 
     p.setAccessible(true); 
     p.setLong(this, 10L); 
    } catch (SecurityException e) { 
     throw new RuntimeException(e); 
    } catch (NoSuchFieldException e) { 
     throw new RuntimeException(e); 
    } catch (IllegalArgumentException e) { 
     throw new RuntimeException(e); 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException(e); 
    } 
    } 
} 

이 코드를 실행하려고하면 super.getClass().getDeclaredField("period")java.lang.NoSuchFieldException: period

을 throw합니다.

답변

20

을 던져 당신은 슈퍼 클래스가 아닌 super.getClass()를 얻을 수 getClass().getSuperclass()이 필요합니다.

그러나 정말로은 권장하지 않습니다. 당신은 기본적으로 추상적 인 클래스의 캡슐화를 파괴하고 있습니다. 추상 클래스가 자손에게 충분한 유연성을 제공하지 않는다면 문제가 해결되어야합니다. 이 클래스가 수행 할 때마다 추상 클래스의 다른 멤버를 변경해야한다면 어떨까요? 개인 상태를 갖는 전체 요점은 클래스가 자신의 데이터를 보호 할 수 있도록하는 것입니다. 이 같은 반사를 사용하면 절대 마지막 리조트해야합니다 정말 못생긴 해킹입니다.

0

ConcreteSome은 AbstractAny 추상 클래스를 확장하지 않습니다.

public class ConcreteSome { 
    @Override 
    public void doSomething() { 
     Class<?> clazz = getClass().getSuperclass(); 
     System.out.println(clazz); 
     Field p = clazz.getDeclaredField("period"); 
     ... 

는 java.lang.Object 상위

+0

고쳐 주셔서 감사합니다. –

2

나는 존 소총과 함께 해요 반환해야보십시오. 장기적으로 수퍼 클래스의 소스 코드를 변경하여이 필드를 보호하거나 대체 메서드에 변형을 위임하는 것이 더 쉽습니다. 리플렉션을 사용하여 값을 변경하면 이제는 제대로 작동하지만 시간이 지남에 따라 유지 관리가 잘 수행되면 확장되지 않습니다.

관련 문제