문제

나는 다음과 같이 설정된 수업을 가로 질러 달렸다.

public class MyClass {

  private static boolean started = false;

  private MyClass(){
  }

  public static void doSomething(){
    if(started){
      return;
    }
    started = true;
    //code below that is only supposed to run
    //run if not started
  }
}

정적 방법에 대한 나의 이해는 클래스 변수가 일정하지 않고 변경되지 않는 한 클래스 변수를 사용해서는 안된다는 것입니다. 대신 매개 변수를 사용해야합니다. 내 질문은 왜 myclass.dosomething ()을 수행하여 여러 번 전화 할 때 깨지지 않는 이유입니다. 작동하지 않아야하는 것처럼 보입니다. if 문을 한 번만 통과합니다.

그래서 왜 이것이 깨지지 않는지 설명 할 수 있습니까?

도움이 되었습니까?

해결책

방법 doSomething() 그리고 변수 started 둘 다 정적이므로 변수의 사본이 하나 뿐이며 doSomething(). 처음 doSomething() 호출됩니다. started 거짓이므로 설정합니다 started 진실하고 ... 글쎄, 뭔가. 두 번째와 후속 시간은 started 사실이므로 아무것도하지 않고 돌아옵니다.

다른 팁

정적 변수를 사용하는 것이 작동하지 않는 이유는 없습니다. 나는 그것이 특히 좋은 연습이라고 말하는 것이 아니라 효과가있을 것입니다.

일어날 일은 다음과 같습니다.

  1. 첫 번째 호출이 이루어집니다. 수업이 초기화되고 시작된 것은 거짓입니다.
  2. 복용량이 호출됩니다. IF가 실패하고 코드가 우회합니다. 시작은 True로 설정되고 다른 코드는 실행됩니다.
  3. 복용량이 다시 호출됩니다. IF 패스 및 실행 중지.

주목할만한 점은 여기에 동기화가 없다는 것입니다. 따라서 Dosomething ()가 별도의 스레드에서 엄청나게 가깝게 호출되면 각 스레드는 거짓으로 시작하여 IF 문을 우회하고 작업을 수행 할 수 있습니다. 즉, 경주 조건이 있습니다.

주어진 코드는 스레드 안전하지 않습니다. 이 코드 스레드를 안전하게 만드는 쉬운 방법은

public class MyClass {

  private static AtomicBoolean started = new AtomicBoolean(false);

  private MyClass(){
  }

  public static void doSomething(){
    boolean oldValue = started.getAndSet(true);
    if (oldValue)
      return;
    }

    //code below that is only supposed to run
    //run if not started
  }
}

AtomicBoolean getAndset이 동기화되므로 스레드 안전해야합니다.

스레드를 사용하지 않으면 문제가되지 않습니다 (WebApp은 그 사실을 인식하지 않고 다양한 요청을 처리하는 많은 스레드를 사용할 수 있습니다).

특히 좋은 코드는 아닙니다. 일반적으로 디자인은 상태가 변경되는 객체 인스턴스를 사용해야하지만 불법적 인 것은 없습니다.

정적 방법에 대한 나의 이해는 클래스 변수가 일정하지 않고 변경되지 않는 한 클래스 변수를 사용해서는 안된다는 것입니다.

디자인 가이드 라인에서 언어 기능으로 추정 한 것 같습니다. 언어에서 실제로 허용되는 내용에 대해 라인에서 사용할 수있는 많은 Java 튜토리얼 중 하나를 읽으십시오. 너 ~할 수 있다 정적 메소드에서 비정형 정적 필드를 자유롭게 사용하지만 객체 지향 코드보다는 절차로 이어집니다.

대신 매개 변수를 사용해야합니다.

방법을보기가 어렵습니다 started 매개 변수가 사용될 것입니다 - 발신자가 프로세스가 시작되었다는 것을 알면 왜 방법을 호출합니까?

정적 방법 내에서 동일한 클래스 내에서 정적 멤버를 호출하거나 액세스 할 수 있습니다.

여러 스레드 시나리오를 무시하면 Dosomething에 대한 첫 번째 호출은 부울 정적 변수를 true로 만듭니다. 따라서 두 번째 호출은 단순히 메소드를 종료하는 if 블록의 코드를 실행합니다.

You static method is talking to a static class variable, so it should be fine. You could think of this as global code and a global variable, tho it IS in the namespace of the class.

If you tried to access a non-static member variable:

private int foo = 0;

from within the static method, the compiler will and should complain.

started is false - initial state.
MyClass.doSomething() - statered is now true
MyClass.doSomething() - started is STILL true

MyClass foo = new MyClass();
foo.started -> it's STILL true, because it's static
foo.doSomething() - not sure you can do this in Java, but if you can, it's be STILL TRUE!

Now, there are issues in the above code with thread safety, but aside from that, it appears to be working as designed.

Just remember the thumb rule that "Static variables are class-level variables and all non-static variables are instance variables". Then you won't have any confusion at all!

i.e. For static variable, All references made in code to the variable point to same memory location. And for non-static variable, new memory allocation is done whenever new instance of that class is created (so every reference made in code to the variable points to a different memory location allocated for calling class instance).

The code above works completely well (unless it runs in a multithreaded environment). Why do you think it should break?

My understanding with static methods is that you should not use class variables in them unless they are constant, and do not change

I guess only static members can be accessed. It need not be constant!

My question is why is this not breaking when called multiple times by doing MyClass.doSomething(). It seems to me like it should not work but does. It will only go pass the if statement once

Per the existing logic. Only the first call runs the //code to be run part

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top