Final Keyword 란
Java 에서 final keyword 는 유저(사용자) 를 제한한다.
final keyword 는 많은 부분에서 사용되는데 final keyword 는 아래 나온 내용에서 사용된다.
- 변수
- 메소드
- 클래스
final keyword 는 변수와 함께 적용될 수 있는데, 값이 없는 final 변수를 공백 final 변수 또는 초기화 되지 않은 final 변수라고 한다.
이때는 생성자에서만 초기화 할 수 있다.
public class FinalKeyword{
final String uninitializedValue;
FinalKeyWord() {
this.uninitializedValue = "Hello World";
}
}
...
public class FinalKeyWordTest() {
FinalKeyword fkw = new FinalKeyWord();
System.out.println(fkw.uninitializedValue);
}
...
출력 결과물 : Hello World
또한 공백 final 변수는 정적 블록에서만 초기화되는 정적 변수일 수도 있음. 아래에서 자세하게 보자.
1. Java Final Variable
임의의 변수를 final 로 만들면 final variable 의 값을 변경할 수 있음.(상수가 되..)
ex)
public class Bike9 {
final int speedLimit = 90; // final variable
void run() {
speedLimit = 400;
}
public static void main(String args[]) {
Bike9 obj = new Bike9();
obj.run();
}
}
출력 : Compile Time Error남
2. Java Final Method
메소드를 final 로 만들면 이를 재정의 할 수 없음.
ex)
public class Bike{
final void run() {System.out.println("running");}
}
public class Honda extends Bike{
void run(){System.out.println("running safely with 100kmph");}
public static void main(String args[]) {
Honda honda = new Honda();
honda.run();
}
}
출력 : Compile Time Error
3. Java Final Class
final class Bike{}
class Honda1 extends Bike{
void run() {
System.out.println("running safely with 100kmph");
}
public static void main(String args[]) {
Honda1 honda = new Honda1();
honda.run();
}
}
출력 : Compile Time Error
그러면 final method 는 상속됨?
ㅇㅇ
public class Bike{
final void run() {
System.out.println("running...");
}
}
class Honda2 extends Bike{
public static void main(String args[]) {
new Honda2().run();
}
}
출력: running...
그러면 static final 도 공백 final 변수이면 초기화 가능?
ㅇㅇ 가능. 대신에 static 안에서 초기화 해야함.
class A{
static final int data; // static blank final variable
static{ data = 50; }
public static void main(String args[]){
System.out.println(A.data);
}
}
final parameter 라는 것도 있는데...
class Bike11{
int cute(final int n) {
n = n + 2; // n 이 final 이므로 변경이 안됨.
n *= n;
}
public static void main(String args[]) {
Bike11 b = new Bile11();
b.cute(5);
}
}
Compile Error
생성자 final 로 만들 수 있음?
?
Static
Static 이란?
- 사전적 정의로는
정적인
이라는 뜻을 가지고 있음.- 사전적인 의미로만 봐도 불변한다는 걸 알 수 있다.. 막 건들면 에러날거 같은...
- Java 에서는 최초 클래스를 로드할 때 메모리에 할당해 종료될 때 해제 되는 것을 의미한다.
메모리 할당?
JVM
위 글의 Runtime Data 영역을 보면 method area, heap area 가 보이는데 method area 설명을 보면
클래스 정보를 처음 메모리에 올릴 때 초기화 되는 대상을 저장하기 위한 영역
- 올라가는 정보
- Field Information
- member 변수에 대한 정보 (이름, 타입, 접근 지정자 등)
- Method Information
- 메서드에 대한 정보(이름, 리턴타입, 파라미터, 접근 지정자 등)
- Type Information이렇게 설명이 되어 있는데 이때 static 변수가 method area 에 저장되고, GC의 관리를 받지 않고 프로그램 종료 시 까지 유지된다.
- Field Information
GC 의 대상은 Heap 영역이다.
Static Keyword 의 특징
- 클래스 레벨 공유
- static 변수는 클래스의 모든 인스턴스에 의해 공유됨. 이 변수들은 클래스가 메모리에 로드될 때 생성되고, 프로그램이 종료될 때까지 유지됨.
- 메모리 효율
- 같은 클래스의 모든 객체들이 하나의
static
변수를 공유하기 때문에 메모리 사용이 줄어듬.
- 같은 클래스의 모든 객체들이 하나의
- 인스턴스 없이 접근 가능
- static 메서드나 변수는 객체의 인스턴스를 생성하지 않고도 호출할 수 있음. 클래스 이름을 통해 직접 접근 가능.
- 이미 method area 에 있으므로 객체가 생성되기 전에 할당되어 있기 때문
public class MyClass{
public static String staticValue = "HI";
public static int staticMethod(int a, int b) {
return a + b;
}
}
public class TestClass {
public static void main(String args[]) {
String a = MyClass.staticValue;
int resultA = MyClass.staticMethod(1,2);
MyClass m1 = new MyClass();
int resultB = m1.staticMethod(1,2);
}
}
좋은데 왜 다 static 안함?
객체 지향 설계 위반
- 캡슐화 저하
static
변수는 클래스의 모든 인스턴스에 의해 공유됨. 이는 데이터 캡슐화를 저하시켜, 객체 간의 상호 작용을 예측하기 어렵게 만들 수 있음.
객체 지향의 핵심은 각 객체가 독립적인 상태와 행동을 갖는건데static
많이 쓰면 이 원칙이 박살남. - 의존성 문제
static
메서드는 인스턴스 변수나 메서드에 접근할 수 없음.
이로 인해static
메서드가 많아지면, 클래스의 다른 비static
부분과의 결합도가 낮아져, 객체 지향적 설계가 어려워짐.
테스트와 유지보수의 어려움이 있음
- 테스트의 어려움
static
변수나 메서드는 테스트가 어렵다.static
변수는 애플리케이션의 생명 주기 동안 초기화 되거나 변경된 값이 유지되기 때문에, 테스트 간 상태를 초기화 하기 어려워짐. ▶️ 격리된 테스트 환경을 만드는데 어려움을 가짐. - 유지보수 복잡성
static
메서드나 변수가 많은 시스템은 시간이 지남에 따라 관리하기가 더 복잡해짐.static
요소들은 시스템의 다른 부분과 강하게 결합될 수 있고, 이로 인해 코드의 변경이 필요할 때 예상치 못한 부작용을 발생시킬 수 있음.
메모리 관리
- 메모리 사용증가
static
변수는 프로그램이 종료될 때 까지 메모리에 남아있음. 따라서, 많은 양의 데이터를static
으로 관리하면서 메모리 사용량이 증가하고, 필요하지 않은 데이터도 계속 메모리를 차지하게 된다. ▶️ 장시간 실행되는 애플리케이션에서 문제가 될 수 있음.
동시성 문제
- 스레드 안전 문제
멀티스레드 환경에서static
변수에 여러 스레드가 동시에 접근하게 되면 동시성 문제가 발생할 수 있음.▶️ 데이터의 일관성과 정확성을 보장하기 어렵게 만들며, 추가적인 동기화 처리가 필요하게 됨.
그럼 언제씀?
1. 공유된 상수
- 여러 인스턴스에서 공통적으로 사용되는 상수 값은
static final
로 선언하여 사용함.public class MathConstants { public static final double PI = 3.14159; }
2. 유틸리티 메서드
- 객체의 상태에 의존하지 않는 메서드, 즉 입력 값만으로 결과를 반환하는 순수 함수는
static
메서드로 선언이 됨.public class StringUtils { public static boolean isEmpty(String s) { return s == null || s.isEmpty(); } }
3. 싱글턴 패턴
최근에 DB Connection Pool 을 start up 되는 시점부터 잡아서 DB 점검일 때 DB 연결이 안되면 어플리케이션 전체가 실행 안되는 상황이 있었는데 기존 프레임워크에서 제공해주는 DataSource 를 지우고, Custom DataSource 를 만들어서 해결했는데 이렇게 싱글턴 패턴으로 만들어서 해결했음.
public class Singleton{
private static Singleton instance;
privatet Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
4. 클래스 초기화 블록
- 클래스 변수를 초기화할 때 복잡한 로직이 필요한 경우
static
초기화 블록을 사용할 수 있음. 이 블록은 클래스가 메모리에 로드될 때 한 번만 실행됨.public class Configuration { public static int bufferSize; static { bufferSize = loadBufferSize(); } private static int loadBufferSize() { // 복잡한 로직을 통해 버퍼 사이즈를 계산 return 512; } }
5. 특정 리소스의 전역 접근
- 애플리케이션 전반에서 공유되어야 하는 리소스나 서비스 객체 등을 관리할 때 사용됨.
public class DatabaseConnection {
public static Connection connection = initializeDatabaseConnection();
}
static 의 사용은 객체 지향적인 설계를 저해할 수 있기 때문에, 공통 리소스의 접근이나 상태가 변하지 않는 메서드에 국한하여 사용하는 것이 바람직하다.
'99클럽 TIL' 카테고리의 다른 글
99클럽 코테 스터디 8일차 TIL Map (1) | 2024.04.25 |
---|---|
99클럽 코테 스터디 7일차 TIL List (0) | 2024.04.24 |
99클럽 코테 스터디 5일차 TIL Override vs Overload (0) | 2024.04.22 |
99클럽 코테 스터디 4일차 TIL JVM (2) | 2024.04.21 |
99클럽 코테 스터디 3일차 TIL Annotation (0) | 2024.04.20 |
Comment