Final: 고정 - 수정 불가능
1. final 필드: 값이 변하지 않는다.
- 필드(클래스 내 변수)에 final예약어가 사용되면, 값이 변하지 않는다는 의미
- 언제 사용? 단위나 고정값을 사용할 때
2. final메서드: 상속(Override)되지 않는다.
- 메서드(클래스 내 함수)에 final 예약어가 사용된다면, Override(상속)가 되지 않는다는 의미
- 언제 사용? 해당 메서드가 꼭 한가지의 구현만으로만 다양한 곳에서 사용되는 경우
- 상속 받았다고, 상속받은 메서드를 너무 쉽게 Override하면, 해당 사용처서 side effect발생 가능
아래 코드는 `Member` 클래스에 정의된 final 메소드이다. add() 메서드에서는 나이에 10만 더하는 기능만 사용하고 싶다면 아래와 같이 final로 메소드 오버라이딩 하는 걸 방지할 수 있다.
public final void add(){
this.age += 10;
}
`Member` 객체를 상속받은 객체가 `add()` 함수를 오버라이딩해서 사이드이펙트를 막을 수 있다.

3. final클래스: 상속(Extends) 되지 않는다.
- 클래스에 final 예약어가 사용된다면, 상속되지 않는다는 의미 (extends를 사용할 수 없다.)
- 언제 사용? 디장니 패턴 원칙 "상속보다는 합성" - 상속은 잃는 것이 많다.
상속: Inheritance
class Animal {
public void hello() { // hello 로직이 바뀌었을 경우에 다른 Puppy 등의 객체에 영향을 준다 : 시부모님의 영향력
}
public void world() { // Cat 에서 밖으로 노출 : 부모의 빚
}
}
// Inheritance
class Cat extends Animal {
public void cat() {
this.hello();
}
}
합성: Comopsition
class CAnimal implements IAnimal {
public void hello() {
}
}
class BAnimal implements IAnimal {
public void hello() {
}
}
// Composition
class CCat {
// private CAnimal cAnimal = new CAnimal();
private IAnimal cAnimal = new BAnimal();
public void cat() {
cAnimal.hello();
}
}
극단적으로는, "사실상 모든 Class를 정의할 때 Final을 붙여도 된다." 라고 말하는 책도 있다.
Static: 정적
인스턴스화 필요 없이 바로 사용 가능
⭐️Static 메소드 안에서는 static 필드만 사용 가능
1. 정적 필드
인스턴스 없이 사용 가능한 필드: 정적 필드
2. 정적 메서드
인스턴스 없이 사용가능한 메서드: 정적 메서드
- 인스턴스 생성 없이 호출이 가능하여, 유틸리티 관련 메서드를 만드는데 유용하게 사용된다.
3. 정적 클래스
인스턴스 없이 사용 가능한 (Nested) 클래스: 정적 (Nested) 클래스
- 정적 (Nested) 클래스가 아니라면: 상위 클래스 인스턴스화를 해야하므로 아래 코드 같이 new new 두번 인스턴스화를 해야한다.
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
- 정적 (Inner or Nested) 클래스라면
OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
헷갈림 방지를 위한 정적 메서드, 정적 클래스 예시
유틸리티 메서드를 위해 Static 사용 시, 상속 및 Override방지를 위해 웬만해선 final도 같이 쓰는 편
`System.out.println`


유틸리티 메서드에서는 static이 사용되었고, 유틸리티 클래스에는 Final이 사용되었다.
유틸리티 클래스로 모두 Override를 방어(클래스가 final이라서 상속불가)할 수 있으므로 유틸리티 메서드에 final을 사용하지 않음
굳이 정적 메서드를 갖고 있는 클래스를 정적으로 정의할 필욘없다. 정적 메서드 내 필드만 정적 변수로 정의하면 된다.
유틸리티 메소드를 왜 static으로 정의하나?
유틸리티 메소드는 필드가 필요없음. 파라미터에만 의존
즉 유틸리티 메소드 == 정적메소드라고 생각하면 된다.
`System.out.println()` 같은 경우도 파라미터만 넘겨주는 유틸리티 함수이다.
정적 클래스와 정적 메서드의 관계
1. 정적 메서드는 정적 클래스 안에 위치할 필요가 없다.


2. 정적 Inner or Nested 클래스는 왜 쓰는가
- Inner or Nested 클래스에서 Outer 클래스의 정적 메서드나 정적 필드를 접근할 때, 정적 Inner or Nested 클래스 만이 Outer Class의 정적 필드인 hala에 접근할 수 있다.
오해하지말자, 정적 Inner or Nested 클래스는 인스턴스화하지 않고 쓸 수 있는게 아니다
정적 Inner or Nested 클래스도 인스턴스화가 가능하다.
상위 outer클래스의 인스턴스화 없이도, Inner or Nested클래스를 인스턴스화할 수 있단 것이다.
아래 코드로 이해해보자
public class OuterClass {
public static int hala = 10;
static class InnerClass {
public void publicFunction() {
System.out.println(hala);
}
}
private void hello() {
OuterClass.InnerClass instantiatedStaticClass = new OuterClass.InnerClass();
// X - OuterClass.InnerClass.publicFunction();
instantiatedStaticClass.publicFunction();
}
}
InnerClass를 상위 클래스 인스턴스화 없이 객체 생성 가능
상수 사용시 static final을 사용하는 이유
`public static final`와 같은 형태의 쓰임새를 많이 봤을 것이다.
전역에서 사용하며, 메모리 한 영역에 정적으로 할당하여 자원을 공유하고, 불변성을 보장하는 데이터를 의미한다.
즉, 자주 사용하는 자원을 효율적으로 불변성을 보장받고 사용하기 위해 이런 식으로 사용한다는 것을 알 수 있다.
따라서 `static final` 에서 static은 메모리에 계속 상주하기에 필요할 때만 사용하도록 static을 빼는 것이 더 합리적인 것이 아닌가? 라는 의구심이 든다.
상수라는게 불변이므로 매번 인스턴스를 말들 때마다 생성할 이유가 없음. 모든 인스턴스들이 final변수를 바라보면 모두 같은 값일 것이므로 굳이 인스턴스당 같은 값을 가지는 final 변수를 둘 필요가 없다는 것.
`static`이 붙었으므로 JVM에서 Static/Method 영역에 할당되어 메모리에 상주해 있으며, 스레드의 공유 영역으로 활용된다.
ref
'ASAC 웹 풀스택 > Spring Boot' 카테고리의 다른 글
Java 기본 문법 및 JVM 구성(12) - 다형성 (0) | 2024.09.29 |
---|---|
Java 기본 문법 및 JVM 구성(11) - Generic, Interface, Abstract Class (0) | 2024.09.29 |
Java 기본 문법 및 JVM 구성(9) - DTO, VO (0) | 2024.09.28 |
Java 기본 문법 및 JVM 구성(8) - 정적 팩토리 메서드 (1) | 2024.09.28 |
Java 기본 문법 및 JVM 구성(7) - Builder: 객체 생성의, 모든 경우의 수를 지원 (0) | 2024.09.28 |
Final: 고정 - 수정 불가능
1. final 필드: 값이 변하지 않는다.
- 필드(클래스 내 변수)에 final예약어가 사용되면, 값이 변하지 않는다는 의미
- 언제 사용? 단위나 고정값을 사용할 때
2. final메서드: 상속(Override)되지 않는다.
- 메서드(클래스 내 함수)에 final 예약어가 사용된다면, Override(상속)가 되지 않는다는 의미
- 언제 사용? 해당 메서드가 꼭 한가지의 구현만으로만 다양한 곳에서 사용되는 경우
- 상속 받았다고, 상속받은 메서드를 너무 쉽게 Override하면, 해당 사용처서 side effect발생 가능
아래 코드는 Member
클래스에 정의된 final 메소드이다. add() 메서드에서는 나이에 10만 더하는 기능만 사용하고 싶다면 아래와 같이 final로 메소드 오버라이딩 하는 걸 방지할 수 있다.
public final void add(){ this.age += 10; }
Member
객체를 상속받은 객체가 add()
함수를 오버라이딩해서 사이드이펙트를 막을 수 있다.

3. final클래스: 상속(Extends) 되지 않는다.
- 클래스에 final 예약어가 사용된다면, 상속되지 않는다는 의미 (extends를 사용할 수 없다.)
- 언제 사용? 디장니 패턴 원칙 "상속보다는 합성" - 상속은 잃는 것이 많다.
상속: Inheritance
class Animal { public void hello() { // hello 로직이 바뀌었을 경우에 다른 Puppy 등의 객체에 영향을 준다 : 시부모님의 영향력 } public void world() { // Cat 에서 밖으로 노출 : 부모의 빚 } } // Inheritance class Cat extends Animal { public void cat() { this.hello(); } }
합성: Comopsition
class CAnimal implements IAnimal { public void hello() { } } class BAnimal implements IAnimal { public void hello() { } } // Composition class CCat { // private CAnimal cAnimal = new CAnimal(); private IAnimal cAnimal = new BAnimal(); public void cat() { cAnimal.hello(); } }
극단적으로는, "사실상 모든 Class를 정의할 때 Final을 붙여도 된다." 라고 말하는 책도 있다.
Static: 정적
인스턴스화 필요 없이 바로 사용 가능
⭐️Static 메소드 안에서는 static 필드만 사용 가능
1. 정적 필드
인스턴스 없이 사용 가능한 필드: 정적 필드
2. 정적 메서드
인스턴스 없이 사용가능한 메서드: 정적 메서드
- 인스턴스 생성 없이 호출이 가능하여, 유틸리티 관련 메서드를 만드는데 유용하게 사용된다.
3. 정적 클래스
인스턴스 없이 사용 가능한 (Nested) 클래스: 정적 (Nested) 클래스
- 정적 (Nested) 클래스가 아니라면: 상위 클래스 인스턴스화를 해야하므로 아래 코드 같이 new new 두번 인스턴스화를 해야한다.
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
- 정적 (Inner or Nested) 클래스라면
OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
헷갈림 방지를 위한 정적 메서드, 정적 클래스 예시
유틸리티 메서드를 위해 Static 사용 시, 상속 및 Override방지를 위해 웬만해선 final도 같이 쓰는 편
System.out.println


유틸리티 메서드에서는 static이 사용되었고, 유틸리티 클래스에는 Final이 사용되었다.
유틸리티 클래스로 모두 Override를 방어(클래스가 final이라서 상속불가)할 수 있으므로 유틸리티 메서드에 final을 사용하지 않음
굳이 정적 메서드를 갖고 있는 클래스를 정적으로 정의할 필욘없다. 정적 메서드 내 필드만 정적 변수로 정의하면 된다.
유틸리티 메소드를 왜 static으로 정의하나?
유틸리티 메소드는 필드가 필요없음. 파라미터에만 의존
즉 유틸리티 메소드 == 정적메소드라고 생각하면 된다.
System.out.println()
같은 경우도 파라미터만 넘겨주는 유틸리티 함수이다.
정적 클래스와 정적 메서드의 관계
1. 정적 메서드는 정적 클래스 안에 위치할 필요가 없다.


2. 정적 Inner or Nested 클래스는 왜 쓰는가
- Inner or Nested 클래스에서 Outer 클래스의 정적 메서드나 정적 필드를 접근할 때, 정적 Inner or Nested 클래스 만이 Outer Class의 정적 필드인 hala에 접근할 수 있다.
오해하지말자, 정적 Inner or Nested 클래스는 인스턴스화하지 않고 쓸 수 있는게 아니다
정적 Inner or Nested 클래스도 인스턴스화가 가능하다.
상위 outer클래스의 인스턴스화 없이도, Inner or Nested클래스를 인스턴스화할 수 있단 것이다.
아래 코드로 이해해보자
public class OuterClass { public static int hala = 10; static class InnerClass { public void publicFunction() { System.out.println(hala); } } private void hello() { OuterClass.InnerClass instantiatedStaticClass = new OuterClass.InnerClass(); // X - OuterClass.InnerClass.publicFunction(); instantiatedStaticClass.publicFunction(); } }
InnerClass를 상위 클래스 인스턴스화 없이 객체 생성 가능
상수 사용시 static final을 사용하는 이유
public static final
와 같은 형태의 쓰임새를 많이 봤을 것이다.
전역에서 사용하며, 메모리 한 영역에 정적으로 할당하여 자원을 공유하고, 불변성을 보장하는 데이터를 의미한다.
즉, 자주 사용하는 자원을 효율적으로 불변성을 보장받고 사용하기 위해 이런 식으로 사용한다는 것을 알 수 있다.
따라서 static final
에서 static은 메모리에 계속 상주하기에 필요할 때만 사용하도록 static을 빼는 것이 더 합리적인 것이 아닌가? 라는 의구심이 든다.
상수라는게 불변이므로 매번 인스턴스를 말들 때마다 생성할 이유가 없음. 모든 인스턴스들이 final변수를 바라보면 모두 같은 값일 것이므로 굳이 인스턴스당 같은 값을 가지는 final 변수를 둘 필요가 없다는 것.
static
이 붙었으므로 JVM에서 Static/Method 영역에 할당되어 메모리에 상주해 있으며, 스레드의 공유 영역으로 활용된다.
ref
'ASAC 웹 풀스택 > Spring Boot' 카테고리의 다른 글
Java 기본 문법 및 JVM 구성(12) - 다형성 (0) | 2024.09.29 |
---|---|
Java 기본 문법 및 JVM 구성(11) - Generic, Interface, Abstract Class (0) | 2024.09.29 |
Java 기본 문법 및 JVM 구성(9) - DTO, VO (0) | 2024.09.28 |
Java 기본 문법 및 JVM 구성(8) - 정적 팩토리 메서드 (1) | 2024.09.28 |
Java 기본 문법 및 JVM 구성(7) - Builder: 객체 생성의, 모든 경우의 수를 지원 (0) | 2024.09.28 |