์๋ฐ์๋ final์ด๋ผ๋ ํค์๋๊ฐ ์์ต๋๋ค. ํด๋์ค, ๋ฉ์๋, ๋ณ์(๋ฉ์๋ ๋งค๊ฐ๋ณ์ ํฌํจ)์ ์ ์ฉํ ์ ์์ต๋๋ค. ํด๋์ค์ ๊ฒฝ์ฐ final ํค์๋๋ ํด๋์ค๊ฐ ํ์ ํด๋์ค๋ฅผ ๊ฐ์ง ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ฆ, ์์์ด ๊ธ์ง๋ฉ๋๋ค... ์ด๋ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ(๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ) ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, String ํด๋์ค๋ final๋ก ์ ์ธ๋ฉ๋๋ค.
public final class String {
}
class SubString extends String { // Compilation error
}
๋ํ ์ต์ข
์์ ์๋ ์ถ์ ํด๋์ค(ํค์๋ abstract๊ฐ ์๋ ํด๋์ค)์๋ ์ํธ ๋ฐฐํ์ ์ธ ๊ฐ๋
์ด๊ธฐ ๋๋ฌธ์ ์ ์ฉํ ์ ์๋ค๋ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค. ์ต์ข
๋ฉ์๋์ ๊ฒฝ์ฐ ํ์ ์๋ ํด๋น ๋ฉ์๋๋ฅผ ํ์ ํด๋์ค์์ ์ฌ์ ์ํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ด๋ ์๋ ๊ตฌํ์ ๋ณ๊ฒฝ์ ๋ฐฉ์งํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
public class SuperClass {
public final void printReport() {
System.out.println("Report");
}
}
class SubClass extends SuperClass {
public void printReport() { //Compilation error
System.out.println("MyReport");
}
}
๊ธฐ๋ณธ ์ ํ์ ๋ณ์์ ๊ฒฝ์ฐ final ํค์๋๋ ํ ๋ฒ ํ ๋น๋ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ฐธ์กฐ ๋ณ์์ ๊ฒฝ์ฐ ๊ฐ์ฒด๊ฐ ํ ๋น๋ ํ์๋ ํด๋น ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ด๊ฑด ์ค์ํ๋ค! ์ฐธ์กฐ๋ ๋ณ๊ฒฝํ ์ ์์ง๋ง ๊ฐ์ฒด์ ์ํ๋ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. Java 8์ ์ฌ์ค์ ์ต์ข
์ด๋ผ๋ ์๋ก์ด ๊ฐ๋
์ ๋์
ํ์ต๋๋ค. ๋ณ์(๋ฉ์๋ ๋งค๊ฐ๋ณ์ ํฌํจ)์๋ง ์ ์ฉ๋ฉ๋๋ค. ๊ฒฐ๋ก ์ final ํค์๋๊ฐ ์์์๋ ๋ถ๊ตฌํ๊ณ ๋ณ์์ ๊ฐ์ ์ด๊ธฐํ ํ์ ๋ณ๊ฒฝ๋์ง ์๋๋ค๋ ๊ฒ์
๋๋ค. ์ฆ, ์ปดํ์ผ ์ค๋ฅ ์์ด ์ด๋ฌํ ๋ณ์์ final ํค์๋๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค. ํจ๊ณผ์ ์ผ๋ก ์ต์ข
๋ณ์๋ ๋ก์ปฌ ํด๋์ค(๋ก์ปฌ ๋ด๋ถ ํด๋์ค), ์ต๋ช
ํด๋์ค(์ต๋ช
๋ด๋ถ ํด๋์ค) ๋ฐ ์คํธ๋ฆผ(Stream API) ๋ด์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
public void someMethod() {
// In the example below, both a and b are effectively final, since they are assigned values only once:
int a = 1;
int b;
if (a == 2) b = 3;
else b = 4;
// c is NOT effectively final since its value changes
int c = 10;
c++;
Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
}
์, ์ ์ ์ธํฐ๋ทฐ๋ฅผ ํด๋ณด์. ๊ฒฐ๊ตญ CodeGym ๊ณผ์ ์ ์ด์ํ๋ ๋ชฉํ๋ Java ๊ฐ๋ฐ์๊ฐ ๋์ด ํฅ๋ฏธ๋กญ๊ณ ๋ณด์๊ฐ ์ข์ ์ง์
์ ์ฐพ๋ ๊ฒ์
๋๋ค. ์, ์์ํ๊ฒ ์ต๋๋ค.
-
์ต์ข ์ ์ธ๋ ๋ฐฐ์ด์ ๋ํด ๋ฌด์์ ๋งํ ์ ์์ต๋๊น?
-
์ฐ๋ฆฌ๋ String ํด๋์ค๊ฐ ๋ถ๋ณ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ํด๋์ค๋ final๋ก ์ ์ธ๋ฉ๋๋ค. ๋ฌธ์์ด ๊ฐ์ final ํค์๋๋ก ํ์๋ char ๋ฐฐ์ด์ ์ ์ฅ๋ฉ๋๋ค.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ String ๊ฐ์ฒด์ ๊ฐ์ ๋ฐ๊ฟ ์ ์์ต๋๊น? ์ค์ ๋ฉด์ ์ง๋ฌธ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ์ต์ ๋ฐ๋ฅด๋ฉด ๋ง์ ํ๋ณด์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋๋ตํ์ง ์์ต๋๋ค. ํนํ ์ฐธ์กฐ ๋ณ์์ ๋ํด final ํค์๋๊ฐ ์ฌ์ฉ๋๋ ๋ฐฉ์์ ์ดํดํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๊ณ ๋ฏผํ๋ค๊ฐ ์ฝ๋์งํ์ ์์ ๋ถํ ํ๋ ํ ๊ฒ์. ํ
์คํธ ํธ์ง๊ธฐ๋ฅผ ํด๋ฆญํ๋ฉด ๋ด์ฉ์ ํ์ํ๊ฑฐ๋ ์จ๊ธธ ์ ์๋ ๋ธ๋ก์ ์ถ๊ฐํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ญ์์ค. ๋ต๋ณ:
-
๋ฐฐ์ด์ ๊ฐ์ฒด์ด๋ฏ๋ก final ํค์๋๋ ๋ฐฐ์ด์ ๋ํ ์ฐธ์กฐ๊ฐ ํ ๋น๋๋ฉด ์ฐธ์กฐ๋ฅผ ๋ณ๊ฒฝํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ์ฆ, ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
final int[] array = {1, 2, 3, 4, 5}; array[0] = 9; // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5} array = new int[5]; // Compilation error
-
๊ทธ๋ ์ฐ๋ฆฌ๋ ํ ์์์ด. ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๊ฐ์ฒด์ ํจ๊ป ์ฌ์ฉ๋ ๋ ๊น๋ค๋ก์ด ์ต์ข ํค์๋๊ฐ ๋ฌด์์ ์๋ฏธํ๋์ง ์ดํดํ๋ ๊ฒ์ ๋๋ค. Reflection API๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ๋ฐ๊ฟ ์ ์์ต๋๋ค.
import java.lang.reflect.Field;
class B {
public static void main(String[] args) throws Exception {
String value = "Old value";
System.out.println(value);
// Get the String class's value field
Field field = value.getClass().getDeclaredField("value");
// Make it mutable
field.setAccessible(true);
// Set a new value
field.set(value, "CodeGym".toCharArray());
System.out.println(value);
/* Output:
* Old value
* CodeGym
*/
}
}
์ด๋ฐ ์์ผ๋ก ๊ธฐ๋ณธ ์ ํ์ ์ต์ข
๋ณ์๋ฅผ ๋ณ๊ฒฝํ๋ ค๊ณ ์๋ํ๋ค๋ฉด ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์์์ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด ์ต์ข
int ํ๋๊ฐ ์๋ Java ํด๋์ค๋ฅผ ๋ง๋ค๊ณ Reflection API๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น ๊ฐ์ ๋ณ๊ฒฝํด ๋ณด์ญ์์ค. ๋ชจ๋์๊ฒ ํ์ด์ ๋น๋๋ค!
GO TO FULL VERSION