2010-07-01 2 views
0

II는 다음과 같이 몇 가지 문제가 점점 STH 자바에서 일해야 :이 개체에 대한 참조가 정적 인 경우 개체에서 비 정적 메서드에 액세스하는 방법은 무엇입니까?

public class ClassA { 
    public static ClassB PointerToB; 
    public static ClassC PointerToC; 

    public ClassA() { 
     PointerToB = new ClassB(); 
     PointerToC = new ClassC(); 

     PointerToB.doSthB(); 
    } 
} 

public class ClassB { 
    public void doSthB() { 
     ClassA.PointerToC.doSthC(); 
    } 
} 

public class ClassC { 
    public void doSthC() { 
     // ... 
    } 
} 

내가 내 "기본"클래스 ("A")은 여러 회원이이 수업을 말한다. 이러한 다른 객체 ("B", "C")에 대한 포인터는 정적으로 만들어 지므로 "B"의 코드는 "C"의 (정적이 아닌) 메소드에 액세스 할 수 있습니다.

정적 메서드는 다른 정적 메서드 및/또는 변수에만 액세스 할 수 있지만 이러한 클래스에 대한 REFERENCE는 정적이므로 실제 클래스 자체는 아니므로이 방법으로 제대로 작동해야합니다. 그렇지 않아야합니까?

나는 이러한 종류의 액세스가 내 응용 프로그램 내가 액세스 ClassB가 필요한 모든 시간 :(

충돌 때문에 조금 ClassC에서 (비 정적) 방법 A 또는 모든 참조를 통과하지 않고, 여기에 붙어있어 C는 함께. 내가 이렇게 어떻게? ClassA에 대한 생성자가 아닌 다른

+0

코드가 컴파일/의미가 없습니다. 두 번째'public ClassA'는 public ClassA()입니다 (ClassA의 생성자입니다)? 그렇다면 왜 클래스를 인스턴스화 할 때마다 정적 참조를 재설정합니까? 그게 무슨 말이야? 참조를 선언 할 때 참조를 초기화하는 것이 더 일반적입니다. –

+0

또한 변수가 일부 * REALLY STRONG * 명명 규칙을 따르지 않습니다. 예를 들어 변수 이름은 항상 소문자로 시작합니다.클래스, 인터페이스 및 열거 형과 같은 유형의 이름 만 대문자로 시작해야합니다. –

+1

) 1.) 예 - 생성자가되어야합니다 ... 편집했습니다 ... 2.)이 코드는 의미가 없습니다. 그것은 예제로 게시 된 코드입니다. 중요하다면 : 그것은 안드로이드 프로젝트이고, 클래스 a는 원격 서비스입니다 (그리고 런타임 당 한번만 인스턴스화됩니다). 클래스 a와 b는 일부 데이터에 대한 컨테이너 클래스입니다. b는 데이터 C 저장소에 대한 액세스가 필요한 데이터에서 일부 기능을 실행합니다. – xenonite

답변

5

음은, 그 코드 을 컴파일 (당신이 브래킷을 놓치고), 부정되고 ...하지만 당신까지 모두 ClassA의 인스턴스를 생성 PointerToBPointerToC은 null이됩니다. 한 번 초기화하려면 초 tier 초기화 도구 - 예 : 선언과 함께 :

public static ClassB PointerToB = new ClassB(); 
public static ClassC PointerToC = new ClassC(); 

그럼에도 불구하고, 여기에 (IMO) 디자인의 두 가지 불쾌한 비트가있다 : 모든 ClassA.PointerToB 등을 사용하는 경우

  • 공공 변경할 필드는 거의 항상 실수
  • 있습니다 ClassA.PointerToC, 당신은 효과적으로 단점을 가지고 싱글 톤을 얻었습니다. 대신 의존성 삽입을 고려하십시오.
+0

끝에있는 글 머리 기호는 +1입니다. –

0

난 액세스 따라 A 또는 C에 대한 모든 참조를 통하지 않고 ClassC에서 (비 고정)하는 방법에 ClassB가 필요하다. 어떻게해야합니까?

그러면 ClassB는 C 인스턴스에 대한 참조가 필요합니다.

A에서 정적 참조를 통해 C에 액세스하는 ClassB 대신 B를 약간 다르게 작성하지 않으시겠습니까?

public class ClassB { 
    public void doSthB(ClassC c) { 
     c.doSthC(); 
    } 
} 
0

이것은 결코 작동하지 않습니다. static은 클래스의 다른 인스턴스가 필드에 대해 서로 다른 값을 가질 수는 없다는 것을 의미합니다. PointerToB을 정적으로 만드는 대신 직접 사용하는 개체에 필요한 공동 작업자에 대한 참조를 제공하십시오.

(또한 클래스와 객체 사이의 차이에 대해 혼란스러워 보인다. 여기에 더 유용한 도움을받을 수있는 비 일반적인 예를 제공하기 위해보십시오!)

당신은, "당신이 붙어있어"당신 말은 할 말을
3

당신은 NullPointerException s를 얻고 있습니까?

변수 PointerToBPointerToC정적이며 실제로 ClassA의 생성자에 의해 설정 될 것이다.그러나 ClassA의 인스턴스이 만들어 질 때만 실행됩니다. 당신이이 변수에 접근 할 때마다

public class ClassA { 
    public static ClassB PointerToB; 
    public static ClassC PointerToC; 

    static { 
     PointerToB = new ClassB(); 
     PointerToC = new ClassC(); 
    } 

    public ClassA() { 
     PointerToB.doSthB(); 
    } 
} 

지금 그들이 널이 아닌 것 :

당신이 아마 대신 생각으로하는 클래스가 을로드 될 때 실행됩니다 정적 initialiser 블록이다. 이 특정한 경우에, 당신은 복잡한 아무것도하지 않는 때문에, 당신은뿐만 아니라 선언을 초기화 할 수 있습니다

public class ClassA { 
    public static ClassB PointerToB = new ClassB(); 
    public static ClassC PointerToC = new ClassC(); 
} 

이 기능적으로 동일하지만 틀림없이 작성하고 이해하기 쉽다.


편집 : 제쳐두고, 코드가 실제로 지금처럼 아주 불쾌한 것을 참고로 - 올바르게 너무 긴 코드의 일부 비트 인스턴스를 구축으로 작동하는 것처럼 보일 것이라고에 숨겨진 시간적 의존도가있다 정적 변수에 액세스하기 전에 ClassA의 누군가가 약간의 변화 (예 : 열정적 인 것이 아니라 필요에 따라 ClassA 생성)를하고 갑자기 완전히 관련이없는 코드가 깨어지기 전에 몇 달 동안 아주 우연히 (우연히) 일할 수있었습니다.

이 시간 종속성보다 훨씬 더 나쁜 경우에도 고려하지 않은 경쟁 조건에 자신을 열어 놓을 수 있습니다. 위의 두 버전 모두 클래스에서 어떤 작업을 수행하기 전에 정적 변수가 초기화된다는 것을 보장하지만 이는 버전에 해당하지 않습니다. 클래스가 구성 될 때마다 각각에 을 설정하고 있습니다. 다른 스레드가 변수에 액세스하는 동안 한 스레드가 생성자를 호출하는 경우 결과가 정의되지 않고 "임의"충돌, 이상한 데이터 문제 또는 기타 문제로 나타날 수 있습니다.

실제 피사체 참조는 시간이 지남에 따라 변경되므로 PointerToC.doSthC()과 같은 식으로 호출 할 수 있습니다 (C에서 카운터를 증가 시키려고합니다). 그러면 정확하게 카운터가 1이되지만 나중에 작성하게됩니다. 프로그램에서 PointerToCClassC의 새 인스턴스로 재설정되었으며 카운터가 다시 0으로 돌아 왔습니다!

데이터 일관성 문제에 대해 생각하는 것이 중요하고 어떻게 컴파일되고 실제로는 이 작동하더라도 (올바른 지금) 반드시 이 맞지 않습니다.입니다.

+0

시간 종속성 : A - 및 A가 아닌 다른 클래스 나 메서드로 B 또는 C에 액세스 할 수 없으므로 A가 자체 init 중에 B와 C를 초기화합니다. – xenonite

+0

@xenonite - ** 지금은 안됩니다 ** 없습니다. 당신이 유용한 것을하고 있다면, 다른 누군가가 미래에 비슷한 것을 할 필요가 있음을 보장 할 수 있으며, 현명한 방법은 수업을 재사용하는 것입니다. 내 의견은 지금 당장은 작동 될 것이지만 프로젝트의 일환으로 "멋지게"행동하지 않으며 그 점에서 변화와 관련하여 믿을 수 없을 정도로 약하다. 심각한 소프트웨어에 대한 죽음의 키스입니다. –

0

난 당신이 찾고있는 솔루션은 싱글 톤 패턴 생각 :

public class ClassA{ 

    private static final class InstanceHolder{ 

     private static final ClassA INSTANCE = new ClassA(); 

     private InstanceHolder(){ 
     } 

    } 

    public static ClassA getInstance(){ 
     return InstanceHolder.INSTANCE; 
    } 

} 

public class ClassB{ 

    private static final class InstanceHolder{ 

     private static final ClassB INSTANCE = new ClassB(); 

     private InstanceHolder(){ 
     } 

    } 

    public static ClassB getInstance(){ 
     return InstanceHolder.INSTANCE; 
    } 

} 

그 방법은, 클래스가 (조금) 서로 분리되어, 당신은 독립적으로 액세스 할 수 있습니다

// inside ClassA 
public void doSthB() { 
    ClassB.getInstance().doSthC(); 
} 

그러나 Singletons are evil이므로 수행중인 작업에주의하십시오. (하지만 지금 당신이하고있는 것은 논란의 여지없이 훨씬 더 악합니다.)

관련 문제