Static은 고정된이라는 의미로, 객체 생성없이 사용할 수 있는 필드와 메서드를 생성할 때 사용되는 키워드이다.
객체 참조 없이 바로 사용할 수 있기 때문에 인스턴스 필드나, 메서드, 그리고 this 키워드를 사용할 수 없다.
메모리 절약
static 필드와 메서드는 클래스 로드 시 메모리에 한 번만 할당되므로 여러 인스턴스에서 공유되기 때문에 메모리 사용량을 줄여준다.
공용 자원
모든 인스턴스가 공유해야 하는 값을 static 필드로 선언하여 여러 인스턴스 간에 공통 자원을 쉽게 관리할 수 있다.
클래스 레벨 유틸리티 메서드
static 메서드는 객체 생성 없이 클래스 이름으로 호출할 수 있어 유틸리티 메서드를 정의하는 데 유용하다.
예를 들면, Math 클래스의 메서드들 (Math.sqrt(), Math.random()) 등이 있다.
상태 관리의 어려움
static 필드는 모든 인스턴스가 공유하기 때문에 동시성 문제가 발생할 수 있있다.
멀티스레드 환경에서 static 필드를 수정하는 경우 특별한 주의가 필요하다.
객체 지향 원칙 위반
static 필드와 메서드는 객체 지향 프로그래밍의 기본 원칙인 캡슐화와 다형성을 약화시킬 수 있다.
테스트 어려움
static 메서드는 객체의 상태에 의존하지 않기 때문에 단위 테스트가 복잡해질 수 있다.
Final 키워드는 최종적인이라는 의미로 해당 키워드가 붙으면 최종적인 값이 되고 수정이 불가능하다는 의미이다.
이 키워드는 변수와 메서드, 클래스에 적용될 수 있다.
Final로 선언된 변수는 한번 초기화 된 이후에는 값을 변경할 수 없으며 선언과 동시에 초기화하거나 생성자로 초기화하는 방법을 사용한다.
Final 메서드는 서브 클래스에서 오버라이딩 할 수 없으며, Final 클래스는 더 이상 확장될 수 없다.
불변성 보장
final 필드는 한 번 초기화되면 변경할 수 없기 때문에 불변 객체를 만들 수 있다. 이는 코드의 안정성을 높이고 디버깅을 쉽게 만든다.
상속 방지
final 클래스를 선언하면 다른 클래스가 이를 상속할 수 없게 된다. 이는 의도치 않은 클래스 확장을 방지하고 보안을 강화할 수 있다.
오버라이드 방지
final 메서드를 선언하면 서브클래스에서 해당 메서드를 오버라이드할 수 없기 때문에 중요한 메서드의 동작을 변경하지 않도록 보장할 수 있다.
성능 최적화
JIT 컴파일러는 final 키워드를 사용하여 성능 최적화를 할 수 있다.
final 변수는 변경되지 않으므로, 컴파일러가 특정 최적화 기술을 적용할 수 있다.
유연성 감소
final 키워드는 변경 불가능성을 보장하므로, 필요에 따라 값을 변경해야 하는 상황에서는 불편할 수 있다.
상속 제한
final 클래스를 상속할 수 없으므로 재사용성이 떨어질 수 있으며 확장 가능한 설계를 방해할 수 있다.
초기화의 어려움
final 필드는 반드시 초기화해야 하므로 복잡한 초기화 로직이 필요한 경우 설정이 어려울 수 있다.
마지막으로 Static과 Final을 함께 사용하는 경우가 있는데 이 경우는 해당 변수가 클래스 레벨에서 고정된 상수임을 의미한다.
Final만 사용했을 경우, 생성자 초기화로 객체마다 다른 값을 가질 수 있기 때문에 Static과 Final을 같이 사용해주어야 상수라고 볼 수 있다.