JAVA/JAVA2

[java2] #18 - final 키워드

yoonddo 2022. 7. 27. 18:20

# final

final 키워드는 변수(variable), 메서드(method), 클래스(class)에 사용될 수 있다.

이 final 키워드는 어떤 곳에 사용되냐에 따라 다른 의미를 가진다. 하지만 final 키워드를 붙이면 무언가를

제한다는 공통적 의미를 가진다.

 

final 변수(variable)

변수에 final을 붙이면 이 변수는 수정할 수 없다는 의미를 가진다. 수정될 수 없기 때문에 초기화 할 때

필수로 값을 넣어야 한다. 만약 객체 안의 변수라면 생성자, static 블럭을 통한 초기화까지는 허용한다.

 

수정할 수 없다는 범위는 그 변수의 값에 한정한다. 즉 다른 객체를 참조 할 때 참조하는 객체의 내부 값은

변경할 수 있다는 의미다.  

 

// fanal 변수 선언 예시

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 = 2; // 컴파일 에러
    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 메서드 존재하나 길이상 생략
}

결과

value = 2
person_1 = Person{name='사바라다', age=29}
person_2 = Person{name='사바라', age=10}

변수를 final로 선언하고 초기화 전에 사용하면 컴파일 에러가 발생한다. 


일반적인 초기화 방법

 (1) 메서드 내부 변수

public void variableFinal() {

  final int value = 2; //선언시 초기화
  final int value_2; //사용하기 전 초기화

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

  value_2 = 3;
  System.out.println("person_2 = " + value_2);
}

 (2) 객체 멤버 변수

public void variableFinal() {
  Person person = new Person("사바라다");
  System.out.println("person = " + person);
}

class Person {

  private final String name;

  private final int age; //초기화 block을 이용한 초기화
  {
    age = 10;
  }

  private final String email = "koangho93@naver.com"; //선언시 초기화

  public Person(String name) { //생성자를 이용한 초기화
    this.name = name;
  }

  @Override
  public String toString() {
    return "Person{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", email='" + email + '\'' +
        '}';
  }
}

(3) static 변수

class Person {

  private static final String DEFAULT_NAME = "염광호"; //선언시 초기화

  private static final int DEFAULT_AGE;
  static {					//static 초기화 block을 이용한 초기화
    DEFAULT_AGE = 10;
  }

  ... person 객체 내부 후략

# final 메서드(method)

메서드에 final을 붙이면 override를 제한하게 된다. 원래 클래스를 상속하게 되면 부모클래스의

protected, public의 접근제어자를 가진 메서드를 상속받아 재구현을 할 수 있다. 즉 동일한

메서드지만 다르게 동작하게 만들 수 있다는 말이다. 하지만 상속받은 클래스에서 해당 메서드를

수정해서 사용하지 못하게 할 수 있는 방법이 메서드에 final을 붙이는 방법이다.

public class Pet {
    public final void makeSound() {
        System.out.println("ahaha");
    }
}

public class Dog extends Pet {
    //final로된 메서드는 override할수 없음
     public void makeSound() { 

     }
}

 

메서드 인자에 final 키워드를 붙이면 메서드 안에서 변수값을 변경할 수 없다.

public class Pet {
    int weight;
    public void setWeight(final int weight) {
	//weight = 1; //final 인자는 메서드안에서 변경할 수 없음
    }
}

# final 클래스(class)

클래스에 final을 선언하면 상속 자체가 안된다. 그냥 클래스 그대로 사용해야 한다.

Util 형식의 클래스나 여러 상수 값을 모아둔 Constants 클래스을 final로 선언한다.

public final class Pet {
}

//Pet 클래스가 final 클래스로 선언되어 상속할 수 없음
public class Dog extends Pet {
}

(1) 상수 클래스

public final class Constants {
    public static final int SIZE = 10;
}

//public class SubConstants extends Constants {
//}

(2) Util 형식의 클래스

JDK에서 String도 final 클래스로 선언되어 있다. 자바의 코어 라이브러리이기 때문에 side-effect가 있으면 안 되기 때문이다.  다른 개발자가 상속을 해서 새로운 SubString을 만들어 라이브러리로 다른 곳에서 사용하게 되면 유지보수, 정상 실행 보장이 어려워질 수 있다.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
}

# final 필드와 상수

상수(static final)

일반적으로 불변의 값을 상수라 부르며 불변의 값을 저장하는 필드를 자바에서는 상수(constant)라고 부른다.

final 필드는 한번 초기화되면 수정할 수 없는 필드지만 final 필드를 상수라고 부르지 않는다.

왜냐하면 불변의 값은 객체마다 저장할 필요가 없는 공용성을 띠고있고 여러가지 값으로 초기화 될 수 없기 때문이다.

final 필드는 객체마다 저장되고 생성자의 매개값을 통해서 여러가지 값을 가질 수 있기 때문에 상수가 될 수 없다.

상수는 static이면서 final 이어야 한다.

static final필드는 객체마다 저장되지 않고, 클래스에만 포함된다. 한 번 초기값이 저장되면 변경할 수 없다.

(상수 이름은 대문자로 작성하는게 관례이며, 언더바(_)를 사용하여 단어들을 연결한다.)

static final double PI = 3.14159;

static final double EARTH_RADIUS = 6400;

 

 

 

 

 

 

참고 https://velog.io/@lychee/Java-final

'JAVA > JAVA2' 카테고리의 다른 글

[java2] #20 - Thread (스레드)  (0) 2022.07.28
[java2] #19 - IntStream 반복문  (0) 2022.07.27
[java2] #17 - Collection Framework(Set/List/Map), Iterator  (0) 2022.07.26
[java2] #16 - HashSet  (0) 2022.07.26
[java2] #15 - HashMap  (0) 2022.07.25