보글보글 개발일지
article thumbnail
Published 2023. 5. 25. 12:39
[Java] Final 키워드 코딩기록/CS
반응형

Final의 정의

자료형에 값을 단 한번만 설정할수 있게 강제하는 키워드 즉, 값을 한번 설정하면 그 값을 다시 설정할 수 없다

public class Sample {
    public static void main(String[] args) {
        final int n = 123;  // final 로 설정하면 값을 바꿀수 없다.
        n = 456;  // 컴파일 에러 발생
    }
}

한 번만 할당 가능하다는 선언. 재할당하려고 하면, 컴파일 오류가 발생하여 바로 확인이 가능.

final은 프로그램 수행 도중 그 값이 변경되면 안되는 상황에 사용한다.

Final 변수

  • 변수에 final을 붙이면 이 변수는 수정할 수 없다는 의미.
  • 수정될 수 없기 때문에 초기화 필수.
  • final 키워드가 붙은 변수는 초기화 후 변경 불가. 다음과 같이 변경하려고 하면 컴파일 에러가 발생!
final String hello = "Hello world";

hello = "See you around"// compile error!

수정 불가의 범위

  • 그 변수의 값에 한정.
  • 다른 객체 참조 시 객체 내부의 값은 변경 가능.
  • 기본형 변수: 값 변경 불가
  • 참조형 변수: 객체 내부의 값 변경 가능, 가리키는 객체 변경 불가능. →set을 통해 값 변경 가능. 재 할당 불가능!
public class Service {
  public void variableFinal() {
    final int value = 2;
    final Person person = new Person("사바라다", 29);

    System.out.println("value = " + value);
    System.out.println("person_1 = " + person);

    // value = 5; // 컴파일 에러 - 기본형 변수 값 변경 불가
    person.setAge(10);
    person.setName("사바라");

    System.out.println("person_2 = " + person);
    // person = new Person("염광호", 29); // 컴파일 에러
  }
}

class Person {
  private String name;
  private int age;
  //.. get, set, toString 메서드 존재하나 길이상 생략
}

  • stack 메모리에서 기본형 변수는 **값(2)**를 가지고, 참조형 변수는 객체의 주소를 가짐.
  • 객체 내부의 값은 final 영향 밖에 있어 변경 가능!
  • 리스트의 경우, final로 선언시 재할당 불가
    • 리스트 또한 참조형 변수이므로, 리스트에 값을 더하거나(add) 빼는(remove) 것, 내부 값 변경은 가능
    • 재할당만 불가능
    • 만약 그 값을 더하거나 빼는 것도 불가능하게 하고 싶은 경우에는 List.of로 수정이 불가능한 리스트(Unmodifiable List)를 사용
import java.util.ArrayList;
import java.util.Arrays;

public class Sample {
    public static void main(String[] args) {
        final ArrayList<String> a = new ArrayList<>(Arrays.asList("a", "b"));
        // 컴파일 에러 발생
				a = new ArrayList<>(Arrays.asList("c", "d"));
    }
}
import java.util.List;

public class Sample {
    public static void main(String[] args) {
        final List<String> a = List.of("a", "b");
        a.add("c");  // UnsupportedOperationException 발생
    }
}

초기화

  • 변수를 final로 선언 시 초기화 전에 사용하면 컴파일 에러 발생.
  • 메서드 내부 변수의 초기화 방법
    • 선언시 초기화
    • 사용하기 전 초기화
    public void variableFinal() {
    //선언시 초기화
      final int value_1 = 2;
      final int value_2;
    
      System.out.println("value = " + value_1);
    //사용하기 전 초기화
      value_2 = 3;
      System.out.println("person_2 = " + value_2);
    }
    
  • 객체 멤버 변수의 초기화 방법
    • 선언시 초기화
    • 생성자를 이용한 초기화
    • 초기화 block을 이용한 초기화
    public void variableFinal() {
      Person person = new Person("사바라다");
      System.out.println("person = " + person);
    }
    
    class Person {
    
      private final String name;
    //초기화 블록을 이용한 초기화
      private final int age;
      {
        age = 10;
      }
    //선언시 초기화
      private final String email = "abab@naver.com";
    //생성자를 이용한 초기화
      public Person(String name) { 
        this.name = name;
      }
    
      @Override
      public String toString() {
        return "Person{" +
            "name='" + name + '\\'' +
            ", age=" + age +
            ", email='" + email + '\\'' +
            '}';
      }
    }
    
  • static 변수의 초기화 방법
    • 선언시 초기화
    • static 초기화 block을 이용한 초기화
    class Person {
    //선언시 초기화
      private static final String DEFAULT_NAME = "보경";
    //static 초기화 block을 이용한 초기화
      private static final int DEFAULT_AGE;
      static {
        DEFAULT_AGE = 10;
      }
    

Final 인자(arguments)

  • 메소드 내에서 변경이 불가능
  • 따라서 다음과 같이 final int로 선언한 number는 읽을 수 있지만, number = 2처럼 값을 변경하려고 하면 컴파일 에러가 발생한다.
public void func(final int number) {
    System.out.println(number);

// number = 2;  compile error!
}

Final 클래스(class)

  • final 키워드를 클래스에 붙이면 상속 불가능
  • 다른 클래스에서 상속하여 재정의 불가.
  • ex) Wrapper클래스(Integer): 클래스 설계시 재정의 불가능하게 사용.
final class finalclass{
    final String hello;
    finalclass() {
        hello = "hello world";
    }
}
//컴파일 에러 발생
class finalfinaclass extends finalclass() { 
}

Final 메소드(method)

  • Override 불가
class finalclass{
    final String hello = "hello world";
    final String getHello() {
			return hello;
    }
}
class finalfinalclass extends finalclass{
		@Override
    String getHello() { //컴파일 에러
        return "See you";
    }
}

Final의 효과/사용 이유

효과

서비스 안정성이 높아진다.

  • 버그 발생 가능성이 줄어든다.
  • 버그를 찾는 시검이 빨라진다.(컴파일 오류)
  • 코드 품질이 높아져 변화에 좀 더 빠르게 대응할 수 있다.

불변 객체

  • 한 번 생성되면 상태를 수정할 수 없는 객체 → 생성이 된 불변 객체는 신뢰할 수 있다.
  • 스레드 동기화 문제 방지
    • 돈 넣을 때마다 새로운 객체 생성 → 여러 스레드 동시에 사용해도 신뢰 가능.

불변 객체 사용이유

  • 한번 생성되면 상태를 수정할 수 없는 객체 -> 생성이 된 불변 객체는 신뢰할 수 있다.
    • 아래와 같이 작성시 실수 할 확률이 적어진다.
    public int addFromTo(final int a, final int b){
    	return addFromOneTo(b) - addFromOneTo(a-1);
    }
    public int addFromOneTo(final int n){
    	return (n * (n + 1)) / 2;
    }
    
  • public int addFromTo(final int a, final int b){ int sum = 0; for (int i = a; i < b ; i++) { //b까지 더해야하는데, 실수 발생 sun += i; } return sum; }
  • 스레드 동기화 문제를, 오류 방지를 사전에 할 수 있다.
  • 값 타입(VO)은 불변 객체(immutable object)로 설계해야한다!

Final 클래스(class)

  • final 키워드를 클래스에 붙이면 상속 불가능
  • 다른 클래스에서 상속하여 재정의 불가.
  • ex) Wrapper클래스(Integer): 클래스 설계시 재정의 불가능하게 사용.
final class finalclass{
    final String hello;
    finalclass() {
        hello = "hello world";
    }
}
//컴파일 에러 발생
class finalfinaclass extends finalclass() { 
}

Final 메소드(method)

  • Override 불가
class finalclass{
    final String hello = "hello world";
    final String getHello() {
			return hello;
    }
}
class finalfinalclass extends finalclass{
		@Override
    String getHello() { //컴파일 에러
        return "See you";
    }
}

Final의 효과/사용 이유

효과

서비스 안정성이 높아진다.

  • 버그 발생 가능성이 줄어든다.
  • 버그를 찾는 시검이 빨라진다.(컴파일 오류)
  • 코드 품질이 높아져 변화에 좀 더 빠르게 대응할 수 있다.

불변 객체

  • 한 번 생성되면 상태를 수정할 수 없는 객체 → 생성이 된 불변 객체는 신뢰할 수 있다.
  • 스레드 동기화 문제 방지
    • 돈 넣을 때마다 새로운 객체 생성 → 여러 스레드 동시에 사용해도 신뢰 가능.

불변 객체 사용이유

  • 한번 생성되면 상태를 수정할 수 없는 객체 -> 생성이 된 불변 객체는 신뢰할 수 있다.
    • 아래와 같이 작성시 실수 할 확률이 적어진다.
    public int addFromTo(final int a, final int b){
    	return addFromOneTo(b) - addFromOneTo(a-1);
    }
    public int addFromOneTo(final int n){
    	return (n * (n + 1)) / 2;
    }
    
  • public int addFromTo(final int a, final int b){ int sum = 0; for (int i = a; i < b ; i++) { //b까지 더해야하는데, 실수 발생 sun += i; } return sum; }
  • 스레드 동기화 문제를, 오류 방지를 사전에 할 수 있다.
  • 값 타입(VO)은 불변 객체(immutable object)로 설계해야한다!

Final 클래스(class)

  • final 키워드를 클래스에 붙이면 상속 불가능
  • 다른 클래스에서 상속하여 재정의 불가.
  • ex) Wrapper클래스(Integer): 클래스 설계시 재정의 불가능하게 사용.
final class finalclass{
    final String hello;
    finalclass() {
        hello = "hello world";
    }
}
//컴파일 에러 발생
class finalfinaclass extends finalclass() { 
}

Final 메소드(method)

  • Override 불가
class finalclass{
    final String hello = "hello world";
    final String getHello() {
			return hello;
    }
}
class finalfinalclass extends finalclass{
		@Override
    String getHello() { //컴파일 에러
        return "See you";
    }
}

Final의 효과/사용 이유

효과

서비스 안정성이 높아진다.

  • 버그 발생 가능성이 줄어든다.
  • 버그를 찾는 시검이 빨라진다.(컴파일 오류)
  • 코드 품질이 높아져 변화에 좀 더 빠르게 대응할 수 있다.

불변 객체

  • 한 번 생성되면 상태를 수정할 수 없는 객체 → 생성이 된 불변 객체는 신뢰할 수 있다.
  • 스레드 동기화 문제 방지

불변 객체 사용이유

  • 한번 생성되면 상태를 수정할 수 없는 객체 -> 생성이 된 불변 객체는 신뢰할 수 있다. 
    • for 문을 통해 합을 구하는 것 보다 아래와 같이 작성시 실수 할 확률이 적어진다.
    public int addFromTo(final int a, final int b){
    	return addFromOneTo(b) - addFromOneTo(a-1);
    }
    public int addFromOneTo(final int n){
    	return (n * (n + 1)) / 2;
    }
  • 스레드 동기화 문제를, 오류 방지를 사전에 할 수 있다.
  • 값 타입(VO)은 불변 객체(immutable object)로 설계해야한다!

 

 

반응형
profile

보글보글 개발일지

@보글

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!