Programing

정적 변수가 왜 나쁜 것으로 간주됩니까?

lottogame 2020. 10. 3. 09:43
반응형

정적 변수가 왜 나쁜 것으로 간주됩니까?


저는 기업 세계에 익숙하지 않은 Java 프로그래머입니다. 최근에 Groovy 와 Java를 사용하여 애플리케이션을 개발했습니다 . 내가 작성한 코드 전체에서 꽤 많은 통계를 사용했습니다. 나는 사용되는 통계의 수를 줄 이도록 선임 기술 부지로부터 요청을 받았습니다. 나는 거의 같은 것을 봤는데 많은 프로그래머들이 정적 변수를 사용하는 것에 상당히 반대한다는 것을 알았다.

정적 변수를 사용하는 것이 더 편리하다고 생각합니다. 그리고 나는 그것들도 효율적이라고 생각한다 (내가 틀렸다면 나를 고쳐주세요). 왜냐하면 내가 클래스 내의 함수를 10,000 번 호출해야한다면, 나는 메소드를 정적으로 만들고 Class.methodCall()대신에 간단하게 사용하는 것이 기쁠 것이기 때문 이다. 10,000 개의 클래스 인스턴스로 메모리를 어수선하게 만들죠?

또한 정적은 코드의 다른 부분에 대한 상호 종속성을 줄입니다. 그들은 완벽한 주 보유자 역할을 할 수 있습니다. 이것에 추가하여 정적이 SmalltalkScala같은 일부 언어로 널리 구현되어 있음을 발견했습니다 . 그렇다면 정적에 대한 이러한 억압이 프로그래머들 사이에서 만연한 이유는 무엇입니까 (특히 Java 세계에서)?

추신 : 통계에 대한 내 가정이 잘못된 경우 저를 수정하십시오.


정적 변수는 전역 상태를 나타냅니다. 추론하기도 어렵고 테스트하기도 어렵습니다. 객체의 새 인스턴스를 생성하면 테스트 내에서 새 상태에 대해 추론 할 수 있습니다. 정적 변수를 사용하는 코드를 사용하면 모든 상태가 될 수 있으며 어떤 것이 든 수정할 수 있습니다.

나는 꽤 오랫동안 계속할 수 있지만 더 큰 개념은 무언가의 범위가 좁을수록 추론하기가 더 쉽다는 것입니다. 우리는 작은 것에 대해 잘 생각하지만, 모듈성이 없다면 백만 라인 시스템의 상태를 추론하기 어렵습니다. 그건 그렇고 정적 변수뿐만 아니라 모든 종류의 것에 적용됩니다.


그다지 객체 지향적이지 않습니다. 일부 사람들이 정적을 "악"으로 간주 할 수있는 한 가지 이유는 정적이 객체 지향 패러다임에 위배된다는 입니다. 특히 데이터가 객체에 캡슐화된다는 원칙 (확장 가능, 정보 숨김 등)을 위반합니다. 정적을 사용하여 설명하는 방식은 본질적으로 범위와 같은 문제를 처리하지 않도록 전역 변수로 사용하는 것입니다. 그러나 전역 변수는 "좋은"객체 지향 코드의 특성이 아니라 절차 적 또는 명령형 프로그래밍 패러다임의 정의 특성 중 하나입니다. 이것은 절차 적 패러다임이 나쁘다는 것을 말하는 것이 아닙니다.하지만 감독자가 "좋은 객체 지향 코드"를 작성하기를 기대하고 실제로 "

항상 즉시 명확하지 않은 정적을 사용하기 시작할 때 Java에는 많은 문제가 있습니다. 예를 들어, 동일한 VM에서 실행중인 프로그램의 두 복사본이있는 경우 정적 변수의 값을 깎아서 서로의 상태를 엉망으로 만들까요? 또는 클래스를 확장하면 어떻게됩니까? 정적 멤버를 재정의 할 수 있습니까? 엄청나게 많은 정적 데이터가 있고 필요한 다른 인스턴스 개체에 대해 메모리를 회수 할 수 없기 때문에 VM의 메모리가 부족합니까?

객체 수명 : 또한 정적은 프로그램의 전체 런타임과 일치하는 수명을 갖습니다. 즉, 일단 클래스 사용을 마치더라도 모든 정적 변수의 메모리는 가비지 수집 될 수 없습니다. 예를 들어, 대신 변수를 비 정적으로 만들고 main () 함수에서 클래스의 단일 인스턴스를 만든 다음 10,000 번 호출이 완료되면 클래스에 특정 함수를 10,000 번 실행하도록 요청한 경우 , 단일 인스턴스에 대한 참조를 삭제하면 모든 정적 변수가 가비지 수집되어 재사용 될 수 있습니다.

특정 재사용 방지 : 또한 정적 메서드는 인터페이스를 구현하는 데 사용할 수 없으므로 정적 메서드는 특정 객체 지향 기능을 사용하지 못하게 할 수 있습니다.

다른 옵션:효율성이 주요 관심사라면 일반적으로 생성보다 빠른 호출의 이점만을 고려하는 것보다 속도 문제를 해결하는 다른 더 좋은 방법이있을 수 있습니다. 일시적 또는 휘발성 수정자가 어디에서나 필요한지 고려하십시오. 인라인 기능을 유지하기 위해 메서드를 정적 대신 최종으로 표시 할 수 있습니다. 메소드 매개 변수 및 기타 변수는 해당 변수를 변경할 수있는 항목에 대한 가정을 기반으로 특정 컴파일러 최적화를 허용하기 위해 final로 표시 할 수 있습니다. 인스턴스 객체는 매번 새 인스턴스를 만드는 대신 여러 번 재사용 할 수 있습니다. 일반적으로 앱에 대해 켜야하는 컴파일러 최적화 스위치가있을 수 있습니다. 아마도 10,000 개의 실행이 다중 스레드가 될 수 있고 다중 프로세서 코어를 활용할 수 있도록 설계를 설정해야합니다. 이식성이 아닌 경우

어떤 이유로 한 개체의 여러 복사본을 원하지 않는 경우 단일 디자인 패턴, 스레드 안전성 (싱글 톤이 잘 코딩 된 것으로 가정), 지연 초기화 허용, 객체가 사용될 때 제대로 초기화되었는지 보장, 하위 클래스 화, 코드 테스트 및 리팩토링의 이점과 같은 정적 객체에 비해 장점이 있습니다. 말할 것도없이, 어떤 시점에서 객체의 한 인스턴스 만 원한다는 마음이 바뀌면 인스턴스 변수를 사용하도록 모든 정적 변수 코드를 리팩터링하는 것보다 중복 인스턴스를 방지하기 위해 코드를 제거하는 것이 훨씬 쉽습니다. 이전에 그렇게해야했지만 재미 있지 않았고 결국 더 많은 클래스를 편집해야하므로 새로운 버그를 도입 할 위험이 높아집니다. 처음에 "올바르게"설정하는 것이 훨씬 낫습니다. 단점이있는 것 같더라도. 나를 위해 여러 복사본이 필요한 길을 결정할 때 필요한 재 작업은 정적을 가능한 한 자주 사용하지 않는 가장 강력한 이유 중 하나 일 것입니다. 그래서 나는 또한 정적이 상호 의존성을 감소 시킨다는 당신의 진술에 동의하지 않을 것입니다. 당신이 "방법을 아는 객체가 아니라 직접 접근 할 수있는 많은 정적을 가지고 있다면 더 결합 된 코드로 끝날 것이라고 생각합니다." 무엇인가 "라고합니다.


악은 주관적인 용어입니다.

생성 및 파괴 측면에서 정적을 제어하지 않습니다. 그들은 프로그램 로딩 및 언 로딩의 요청에 따라 생활합니다.

정적은 하나의 공간에 있기 때문에이를 사용하려는 모든 스레드는 관리해야하는 액세스 제어를 거쳐야합니다. 이것은 프로그램이 더 결합되어 있고 이러한 변화를 예상하고 관리하기가 더 어렵다는 것을 의미합니다 (J Skeet이 말한 것처럼). 이로 인해 변경 영향 격리 문제가 발생하여 테스트 관리 방식에 영향을 미칩니다.

이것이 제가 그들과 함께 가지고있는 두 가지 주요 문제입니다.


아니요. 글로벌 국가는 그 자체로 악하지 않습니다. 그러나 우리는보고가 당신의 당신이 그것을 제대로 사용하면 코드를 볼 수 있습니다. 초보자가 글로벌 주를 학대 할 가능성이 매우 높습니다. 그가 모든 언어 기능을 남용하는 것처럼.

글로벌 상태는 절대적으로 필요합니다. 우리는 글로벌 상태를 피할 수 없습니다. 우리는 글로벌 상태에 대한 추론을 피할 수 없습니다. -우리가 우리의 애플리케이션 의미를 이해하고 싶다면.

그것을 위해 글로벌 상태를 제거하려는 사람들은 필연적으로 훨씬 더 복잡한 시스템으로 끝납니다. 그리고 글로벌 상태는 여전히 거기에 있습니다. 그리고 우리는 모든 간접적 인 것들을 풀어 낸 후에도 여전히 글로벌 상태에 대해 추론해야합니다.

XML로 글로벌 상태를 아낌없이 선언하고 어떻게 든 우월하다고 생각하는 Spring 사람들처럼.

@Jon Skeet if I create a new instance of an object이제 두 가지 추론 할 수 있습니다. 객체 내의 상태와 객체를 호스팅하는 환경의 상태입니다.


정적 변수에는 두 가지 주요 문제가 있습니다.

  • 스레드 안전성-정적 자원은 정의상 스레드로부터 안전하지 않습니다.
  • 코드 암시-정적 변수가 인스턴스화되는시기와 다른 정적 변수보다 먼저 인스턴스화되는지 여부를 알 수 없습니다.

'final'키워드없이 'static'키워드를 사용하는 경우 이는 디자인을 신중하게 고려해야한다는 신호입니다. '최종'의 존재조차도 자유 패스가 아닙니다. 변경 가능한 정적 최종 객체도 마찬가지로 위험 할 수 있기 때문입니다.

나는 '결승전'없이 '정적'을 보는 시간의 약 85 % 정도를 추정 할 것이다. 그것은 잘못된 것이다. 종종 이러한 문제를 숨기거나 숨길 수있는 이상한 해결 방법을 찾습니다.

정적 변경 가능 항목을 생성하지 마십시오. 특히 컬렉션. 일반적으로 컬렉션은 포함 개체가 초기화 될 때 초기화되어야하며 포함 개체가 잊혀 질 때 재설정되거나 잊혀지도록 디자인해야합니다.

정적을 사용하면 엔지니어에게 고통을주는 매우 미묘한 버그가 발생할 수 있습니다. 저는이 버그를 만들고 사냥했기 때문에 압니다.

더 자세한 정보를 원하시면 다음을 읽어주세요…

정적을 사용하지 않는 이유는 무엇입니까?

테스트 작성 및 실행, 즉시 명확하지 않은 미묘한 버그 등 정적 문제가 많습니다.

정적 개체에 의존하는 코드는 쉽게 단위 테스트 할 수 없으며 정적을 쉽게 모의 할 수 없습니다 (일반적으로).

정적을 사용하는 경우 더 높은 수준의 구성 요소를 테스트하기 위해 클래스 구현을 교체 할 수 없습니다. 예를 들어, 데이터베이스에서로드하는 Customer 개체를 반환하는 정적 CustomerDAO를 상상해보십시오. 이제 일부 Customer 개체에 액세스해야하는 CustomerFilter 클래스가 있습니다. CustomerDAO가 정적 인 경우 먼저 데이터베이스를 초기화하고 유용한 정보를 채우지 않고는 CustomerFilter에 대한 테스트를 작성할 수 없습니다.

그리고 데이터베이스 채우기와 초기화에는 오랜 시간이 걸립니다. 제 경험상 DB 초기화 프레임 워크는 시간이 지남에 따라 변경되므로 데이터가 변형되고 테스트가 중단 될 수 있습니다. IE, 고객 1이 VIP 였지만 DB 초기화 프레임 워크가 변경되어 이제 고객 1이 더 이상 VIP가 아니지만 테스트가 고객 1을로드하도록 하드 코딩되었다고 가정합니다.

더 나은 접근 방식은 CustomerDAO를 인스턴스화하고 생성 될 때 CustomerFilter에 전달하는 것입니다. (더 나은 접근 방식은 Spring 또는 다른 Inversion of Control 프레임 워크를 사용하는 것입니다.

이 작업을 수행하면 CustomerFilterTest에서 대체 DAO를 빠르게 모의하거나 스텁 할 수 있으므로 테스트를 더 많이 제어 할 수 있습니다.

정적 DAO가 없으면 테스트가 더 빠르고 (db 초기화 없음) 더 안정적입니다 (db 초기화 코드가 변경 될 때 실패하지 않기 때문입니다). 예를 들어,이 경우 테스트에 관한 한 고객 1이 항상 VIP가되도록 보장합니다.

테스트 실행

정적은 단위 테스트 모음을 함께 실행할 때 실제 문제를 일으 킵니다 (예 : Continuous Integration 서버 사용). 한 테스트에서 다른 테스트로 열려있는 네트워크 소켓 개체의 정적 맵을 상상해보십시오. 첫 번째 테스트는 포트 8080에서 소켓을 열 수 있지만 테스트가 해체 될 때 맵을 지우는 것을 잊었습니다. 이제 두 번째 테스트가 시작될 때 포트가 여전히 사용 중이기 때문에 포트 8080에 대한 새 소켓을 만들려고 할 때 충돌 할 가능성이 있습니다. 또한 정적 컬렉션의 소켓 참조가 제거되지 않고 (WeakHashMap 제외) 가비지 수집 대상이되지 않아 메모리 누수가 발생한다고 상상해보십시오.

이것은 지나치게 일반화 된 예이지만 대규모 시스템에서는이 문제가 항상 발생합니다. 사람들은 동일한 JVM에서 반복적으로 소프트웨어를 시작하고 중지하는 단위 테스트를 생각하지 않지만 소프트웨어 디자인에 대한 좋은 테스트이며 고 가용성에 대한 열망이 있다면 알아야 할 사항입니다.

이러한 문제는 종종 DB 액세스, 캐싱, 메시징 및 로깅 계층과 같은 프레임 워크 개체에서 발생합니다. Java EE 또는 최상의 프레임 워크를 사용하는 경우 이러한 프레임 워크를 많이 관리 할 수 ​​있지만 저처럼 레거시 시스템을 다루는 경우 이러한 계층에 액세스 할 수있는 많은 사용자 정의 프레임 워크가있을 수 있습니다.

이러한 프레임 워크 구성 요소에 적용되는 시스템 구성이 단위 테스트간에 변경되고 단위 테스트 프레임 워크가 구성 요소를 분해하고 다시 빌드하지 않으면 이러한 변경 사항이 적용되지 않으며 테스트가 이러한 변경 사항에 의존하면 실패합니다. .

프레임 워크가 아닌 구성 요소도이 문제의 영향을받습니다. OpenOrders라는 정적 맵을 상상해보십시오. 몇 개의 미결 주문을 생성하는 하나의 테스트를 작성하고 모든 주문이 올바른 상태인지 확인한 다음 테스트가 종료됩니다. 다른 개발자는 필요한 주문을 OpenOrders 맵에 넣는 두 번째 테스트를 작성한 다음 주문 수가 정확하다고 주장합니다. 개별적으로 실행하면 이러한 테스트는 둘 다 통과되지만 한 제품군에서 함께 실행하면 실패합니다.

더 나쁜 것은 테스트가 실행 된 순서에 따라 실패 할 수 있다는 것입니다.

이 경우 정적을 피하면 테스트 인스턴스간에 데이터가 지속되는 위험을 피하여 테스트 안정성을 높일 수 있습니다.

미묘한 버그

고 가용성 환경 또는 스레드가 시작 및 중지 될 수있는 모든 곳에서 작업하는 경우 코드가 프로덕션에서 실행될 때도 단위 테스트 제품군에 대해 위에서 언급 한 동일한 문제가 적용될 수 있습니다.

스레드를 다룰 때는 정적 개체를 사용하여 데이터를 저장하는 것보다 스레드 시작 단계에서 초기화 된 개체를 사용하는 것이 좋습니다. 이러한 방식으로 스레드가 시작될 때마다 개체의 새 인스턴스 (잠재적으로 새로운 구성 포함)가 생성되고 스레드의 한 인스턴스에서 다음 인스턴스로 흘러가는 데이터를 방지 할 수 있습니다.

스레드가 죽으면 정적 객체는 재설정되거나 가비지 수집되지 않습니다. "EmailCustomers"라는 스레드가 있고 시작될 때 정적 문자열 컬렉션을 이메일 주소 목록으로 채운 다음 각 주소를 이메일로 보내기 시작한다고 상상해보십시오. 스레드가 중단되거나 취소되어 고 가용성 프레임 워크가 스레드를 다시 시작한다고 가정 해 보겠습니다. 그런 다음 스레드가 시작되면 고객 목록을 다시로드합니다. 그러나 컬렉션은 정적이기 때문에 이전 컬렉션의 이메일 주소 목록을 유지할 수 있습니다. 이제 일부 고객은 중복 이메일을받을 수 있습니다.

제쳐두고 : 정적 결승

기술적 인 구현 차이가 있지만 "정적 최종"의 사용은 사실상 Java C #define과 동일합니다. AC / C ++ #define은 컴파일 전에 전처리기에 의해 코드에서 스왑됩니다. Java "정적 최종"은 스택에 상주하는 메모리가됩니다. 그런 식으로 #define보다 C ++의 "정적 const"변수와 더 유사합니다.

요약

이것이 통계가 문제가되는 몇 가지 기본적인 이유를 설명하는 데 도움이되기를 바랍니다. Java EE 또는 Spring 등과 같은 최신 Java 프레임 워크를 사용하는 경우 이러한 상황이 많이 발생하지 않을 수 있지만 많은 레거시 코드로 작업하는 경우 훨씬 더 자주 발생할 수 있습니다.


아무도 * 언급하지 않았으므로 동시성입니다. 정적 변수를 읽고 쓰는 스레드가 여러 개인 경우 정적 변수가 놀라 울 수 있습니다. 이것은 웹 응용 프로그램 (예 : ASP.NET)에서 일반적이며 다소 미친 버그를 일으킬 수 있습니다. 예를 들어, 페이지에 의해 업데이트되는 정적 변수가 있고 두 사람이 "거의 동시에"페이지를 요청하면 한 사용자가 다른 사용자가 예상 한 결과를 얻거나 더 나빠질 수 있습니다.

정적은 코드의 다른 부분에 대한 상호 종속성을 줄입니다. 그들은 완벽한 주 보유자 역할을 할 수 있습니다

잠금을 사용하고 경합을 처리 할 준비가 되었기를 바랍니다.

* 사실 Preet Sangha가 언급했습니다.


if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, Right?

You have to balance the need for encapsulating data into an object with a state, versus the need of simply computing the result of a function on some data.

Moreover statics reduce the inter-dependencies on the other parts of the code.

So does encapsulation. In large applications, statics tend to produce spaghetti code and don't easily allow refactoring or testing.

The other answers also provide good reasons against excessive use of statics.


Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming. In object-oriented programming, each object has its own state, represented by instance (non-static) variables. Static variables represent state across instances which can be much more difficult to unit test. This is mainly because it is more difficult to isolate changes to static variables to a single test.

That being said, it is important to make a distinction between regular static variables (generally considered bad), and final static variables (AKA constants; not so bad).


Summarising few basic Advantages & Disadvantages of using Static methods in Java:

Advantages:

  1. Globally accessible i.e. not tied with any particular object instance.
  2. One instance per JVM.
  3. Can be accessed by using class name (No object require).
  4. Contains a single value applicable to all instances.
  5. Load up on JVM startup and dies when JVM shuts down.
  6. They doesn't modify state of Object.

Disadvantages:

  1. Static members are always part of memory whether they are in use or not.
  2. You can not control creation and destruction of static variable. Usefully they have been created at program loading and destroyed when program unload (or when JVM shuts down).
  3. You can make statics thread safe using synchronize but you need some extra efforts.
  4. If one thread change value of a static variable that can possibly break functionality of other threads.
  5. You must know “static“ before using it.
  6. You cannot override static methods.
  7. Serialization doesn't work well with them.
  8. They don't participate in runtime polymorphism.
  9. There is a memory issue (to some extent but not much I guess) if a large number of static variables/methods are used. Because they will not be Garbage Collected until program ends.
  10. Static methods are hard to test too.

In my opinion it's hardly ever about performance, it's about design. I don't consider the use of static methods wrong as apposed of the use of static variables (but I guess you are actually talking about method calls).

It's simply about how to isolate logic and give it a good place. Sometimes that justifies using static methods of which java.lang.Math is a good example. I think when you name most of your classes XxxUtil or Xxxhelper you'd better reconsider your design.


I have just summarized some of the points made in the answers. If you find anything wrong please feel free to correct it.

Scaling: We have exactly one instance of a static variable per JVM. Suppose we are developing a library management system and we decided to put the name of book a static variable as there is only one per book. But if system grows and we are using multiple JVMs then we dont have a way to figure out which book we are dealing with?

Thread-Safety: Both instance variable and static variable need to be controlled when used in multi threaded environment. But in case of an instance variable it does not need protection unless it is explicitly shared between threads but in case of a static variable it is always shared by all the threads in the process.

Testing: Though testable design does not equal to good design but we will rarely observe a good design that is not testable. As static variables represent global state and it gets very difficult to test them.

Reasoning about state: If I create a new instance of a class then we can reason about the state of this instance but if it is having static variables then it could be in any state. Why? Because it is possible that the static variable has been modified by some different instance as static variable is shared across instances.

Serialization: Serialization also does not work well with them.

Creation and destruction: Creation and destruction of static variables can not be controlled. Usually they are created and destroyed at program loading and unloading time. It means they are bad for memory management and also add up the initialization time at start up.

But what if we really need them?

But sometimes we may have a genuine need of them. If we really feel the need of many static variables that are shared across the application then one option is to make use of Singleton Design pattern which will have all these variables. Or we can create some object which will have these static variable and can be passed around.

Also if the static variable is marked final it becomes a constant and value assigned to it once cannot be changed. It means it will save us from all the problems we face due to its mutability.


Static variables most importantly creates problem with security of data (any time changed,anyone can change,direct access without object, etc.)

For further info read this Thanks.


It might be suggested that in most cases where you use a static variable, you really want to be using the singleton pattern.

The problem with global states is that sometimes what makes sense as global in a simpler context, needs to be a bit more flexible in a practical context, and this is where the singleton pattern becomes useful.


Seems to me that you're asking about static variables but you also point out static methods in your examples.

Static variables are not evil - they have its adoption as global variables like constants in most cases combined with final modifier, but as it said don't overuse them.

Static methods aka utility method. It isn't generally a bad practice to use them but major concern is that they might obstruct testing.

As a example of great java project that use a lot of statics and do it right way please look at Play! framework. There is also discussion about it in SO.

Static variables/methods combined with static import are also widely used in libraries that facilitate declarative programming in java like: make it easy or Hamcrest. It wouldn't be possible without a lot of static variables and methods.

So static variables (and methods) are good but use them wisely!


Yet another reason: fragility.

If you have a class, most people expect to be able to create it and use it at will.

You can document it's not the case, or protect against it (singleton/factory pattern) - but that's extra work, and therefore an additional cost. Even then, in a big company, chances are someone will try at some point to use your class without fully paying attention to all the nice comments or the factory.

If you're using static variables a lot, that will break. Bugs are expensive.

Between a .0001% performance improvement and robustness to change by potentially clueless developers, in a lot of cases robustness is the good choice.


I find static variables more convenient to use. And I presume that they are efficient too (Please correct me if I am wrong) because if I had to make 10,000 calls to a function within a class, I would be glad to make the method static and use a straightforward class.methodCall() on it instead of cluttering the memory with 10,000 instances of the class, Right?

I see what you think, but a simple Singleton pattern will do the same without having to instantiate 10 000 objects.

static methods can be used, but only for functions that are related to the object domain and do not need or use internal properties of the object.

ex:

public class WaterContainer {
    private int size;
    private int brand;
    ...etc

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}

The issue of 'Statics being evil' is more of an issue about global state. The appropriate time for a variable to be static, is if it does not ever have more than one state; IE tools that should be accessible by the entire framework and always return the same results for the same method calls are never 'evil' as statics. As to your comment:

I find static variables more convenient to use. And I presume that they are efficient too

Statics are the ideal and efficient choice for variables/classes that do not ever change.

The problem with global state is the inherent inconsistency that it can create. Documentation about unit tests often address this issue, since any time there is a global state that can be accessed by more than multiple unrelated objects, your unit tests will be incomplete, and not 'unit' grained. As mentioned in this article about global state and singletons, if object A and B are unrelated (as in one is not expressly given reference to another), then A should not be able to affect the state of B.

There are some exceptions to the ban global state in good code, such as the clock. Time is global, and--in some sense--it changes the state of objects without having a coded relationship.


My $.02 is that several of these answers are confusing the issue, rather than saying "statics are bad" I think its better to talk about scoping and instances.

What I would say is that a static is a "class" variables - it represenst a value that is shared across all instances of that class. Typically it should be scoped that way as well (protected or private to class and its instances).

If you plan to put class-level behavior around it and expose it to other code, then a singleton may be a better solution to support changes in the future (as @Jessica suggested). This is because you can use interfaces at the instance/singleton level in ways that you can not use at the class level - in particular inheritance.

Some thoughts on why I think some of the aspects in other answers are not core to the question...

Statics are not "global". In Java scoping is controlled separately from static/instance.

Concurrency is no less dangerous for statics than instance methods. It's still state that needs to be protected. Sure you may have 1000 instances with an instance variable each and only one static variable, but if the code accessing either isn't written in a thread-safe way you are still screwed - it just may take a little longer for you to realize it.

Managing life cycle is an interesting argument, but I think it's a less important one. I don't see why its any harder to manage a pair of class methods like init()/clear() than the creation and destroying of a singleton instance. In fact, some might say a singleton is a little more complicated due to GC.

PS, In terms of Smalltalk, many of its dialects do have class variables, but in Smalltalk classes are actually instances of Metaclass so they are really are variables on the Metaclass instance. Still, I would apply the same rule of thumb. If they are being used for shared state across instances then ok. If they are supporting public functionality you should look at a Singleton. Sigh, I sure do miss Smalltalk....


There's nothing wrong with static variables per se. It's just the Java syntax that's broken. Each Java class actually defines two structures- a singleton object which encapsulates static variables, and an instance. Defining both in the same source block is pure evil, and results in a code that's hard to read. Scala did that right.


a) Reason about programs.

If you have a small- to midsize-program, where the static variable Global.foo is accessed, the call to it normally comes from nowhere - there is no path, and therefore no timeline, how the variable comes to the place, where it is used. Now how do I know who set it to its actual value? How do I know, what happens, if I modify it right now? I have grep over the whole source, to collect all accesses, to know, what is going on.

If you know how you use it, because you just wrote the code, the problem is invisible, but if you try to understand foreign code, you will understand.

b) Do you really only need one?

Static variables often prevent multiple programs of the same kind running in the same JVM with different values. You often don't foresee usages, where more than one instance of your program is useful, but if it evolves, or if it is useful for others, they might experience situations, where they would like to start more than one instance of your program.

Only more or less useless code which will not be used by many people over a longer time in an intensive way might go well with static variables.


There are two main questions in your post.

First, about static variables. Static variables are completelly unnecesary and it's use can be avoided easily. In OOP languajes in general, and in Java particularlly, function parameters are pased by reference, this is to say, if you pass an object to a funciont, you are passing a pointer to the object, so you dont need to define static variables since you can pass a pointer to the object to any scope that needs this information. Even if this implies that yo will fill your memory with pointers, this will not necesary represent a poor performance because actual memory pagging systems are optimized to handle with this, and they will maintain in memory the pages referenced by the pointers you passed to the new scope; usage of static variables may cause the system to load the memory page where they are stored when they need to be accessed (this will happen if the page has not been accesed in a long time). A good practice is to put all that static stuf together in some little "configuration clases", this will ensure the system puts it all in the same memory page.

Second, about static methods. Static methods are not so bad, but they can quickly reduce performance. For example, think about a method that compares two objects of a class and returns a value indicating which of the objects is bigger (tipical comparison method) this method can be static or not, but when invoking it the non static form will be more eficient since it will have to solve only two references (one for each object) face to the three references that will have to solve the static version of the same method (one for the class plus two, one for each object). But as I say, this is not so bad, if we take a look at the Math class, we can find a lot of math functions defined as static methods. This is really more eficient than putting all these methods in the class defining the numbers, because most of them are rarelly used and including all of them in the number class will cause the class to be very complex and consume a lot of resources unnecesarilly.

In concluson: Avoid the use of static variables and find the correct performance equilibrium when dealing with static or non static methods.

PS: Sorry for my english.


everything (can:) have its purpose, if you have bunch of threads that needs to share/cache data and also all accessible memory (so you dont split into contexts within one JVM) the static is best choice

-> of course you can force just one instance, but why?
i find some of the comments in this thread evil, not the statics ;)


All the answers above show why statics are bad. The reason they are evil is because it gives the false impression that you are writing object oriented code, when in fact you are not. That is just plain evil.


Static variables are not good nor evil. They represent attributes that describe the whole class and not a particular instance. If you need to have a counter for all the instances of a certain class, a static variable would be the right place to hold the value.

Problems appear when you try to use static variables for holding instance related values.


There are plenty of good answers here, adding to it,

Memory: Static variables are live as long as the class loader lives[in general till VM dies], but this is only in-case of bulk objects/references stored as static.

Modularization: consider concepts like IOC, dependencyInjection, proxy etc.. All are completely against tightly coupling/static implementations.

Other Con's: Thread Safety, Testability


Think that if you have an application with many users and you have define a static form, then every user will modify all other forms of other users too.


I think excessive uses of global variables with static keyword will also leads to memory leakage at some point of instance in the applica


From my point of view static variable should be only read only data or variables created by convention.

For example we have a ui of some project, and we have a list of countries, languages, user roles, etc. And we have class to organize this data. we absolutely sure that app will not work without this lists. so the first that we do on app init is checking this list for updates and getting this list from api (if needed). So we agree that this data is "always" present in app. It is practically read only data so we don't need to take care of it's state - thinking about this case we really don't want to have a lot of instances of those data - this case looks a perfect candidate to be static.

참고URL : https://stackoverflow.com/questions/7026507/why-are-static-variables-considered-evil

반응형