안녕하세요!
이번에는 nested class 중에 하나인 local class에 대해서 알아보겠습니다.
Local class의 경우는 block 내부에 정의됩니다. Block이라고 하면 instance block*, static block*, constructor, method, for loop이나 if 문 block등이 있습니다. (*instance block과 static block은 다음에 한 번 자세히 알아보겠습니다.)
지역변수(local variable)처럼 정의되어 있는 block의 내부에서만 사용이 가능하여, 보통 선언 후에 바로 객체를 생성해서 사용하게 됩니다. 사용할 수 있는 범위가 정의되어 있는 block에만 한정되기 때문에 사용 빈도가 높지 않다고 합니다.
사용 방법
아래 코드를 보시면 local class를 사용할 수 있는 위치별로 정의된 local class를 볼 수 있습니다.
class Outer {
// a Class inside Constructor (Constructor 내부)
Outer(){
class ConstructorLocal {
}
}
// a class inside instance block (Instance block 내부)
{
class Local{
}
}
// a class inside static block (static block 내부)
static {
class StaticLocal{
}
}
// a class inside method (method 내부)
public void add(int a, int b) {
class MethodLocal {
}
// a class inside if block
if(a > b) {
class Local{
}
}
}
}
출처: https://javabydeveloper.com/java-local-class/
한 번 method 내에서 사용하는 방법에 대해 간단한 예제로 알아볼까요?
static class Outer {
int a = 5;
void test() {
int b = 6;
// method 내부에 local class 정의
class LocalInnerClass {
void getPrint() {
System.out.println(a);
System.out.println(b);
}
}
//정의한 local class를 method 내에서 initialize 해서 사용
LocalInnerClass localInClass = new LocalInnerClass();
localInClass.getPrint();
}
}
Outer class 내부의 test() method 안에 LocalInnerClass를 정의하였고, 해당 method 내에서 변수를 선언하고 생성해서 사용했습니다.
간단한 예제로 대략적인 사용방법을 알게되었으니, 조금 더 긴 코드로 한 번 더 연습을 해보겠습니다.
Oracle 공식 문서에 method 내부에 local class가 사용된 좋은 예시가 있어서 한 번 가져와봤습니다.
아래 예제를 보시면 LocalClassExample 이라는 클래스 안에 validatePhoneNumber() method가 있습니다. 그리고 그 method 내부에 PhoneNumber 라는 local class가 정의되어 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
public class LocalClassExample {
static String regularExpression = "[^0-9]";
public static void validatePhoneNumber(
String phoneNumber1, String phoneNumber2) {
final int numberLength = 10;
// Valid in JDK 8 and later:
// int numberLength = 10;
class PhoneNumber {
String formattedPhoneNumber = null;
PhoneNumber(String phoneNumber){
// numberLength = 7;
String currentNumber = phoneNumber.replaceAll(
regularExpression, "");
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}
public String getNumber() {
return formattedPhoneNumber;
}
// Valid in JDK 8 and later:
// public void printOriginalNumbers() {
// System.out.println("Original numbers are " + phoneNumber1 +
// " and " + phoneNumber2);
// }
}
PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
PhoneNumber myNumber2 = new PhoneNumber(phoneNumber2);
// Valid in JDK 8 and later:
// myNumber1.printOriginalNumbers();
if (myNumber1.getNumber() == null)
System.out.println("First number is invalid");
else
System.out.println("First number is " + myNumber1.getNumber());
if (myNumber2.getNumber() == null)
System.out.println("Second number is invalid");
else
System.out.println("Second number is " + myNumber2.getNumber());
}
public static void main(String... args) {
validatePhoneNumber("123-456-7890", "456-7890");
}
}
|
cs |
코드가 많아 조금 혼란스러우니 inner class 부분만 떼어내서 보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class PhoneNumber {
String formattedPhoneNumber = null;
PhoneNumber(String phoneNumber){
// numberLength = 7;
String currentNumber = phoneNumber.replaceAll(
regularExpression, "");
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}
public String getNumber() {
return formattedPhoneNumber;
}
// Valid in JDK 8 and later:
// public void printOriginalNumbers() {
// System.out.println("Original numbers are " + phoneNumber1 +
// " and " + phoneNumber2);
// }
}
|
cs |
PhoneNumber class만 따로 떼어 왔습니다. 보시면 일반 클래스와 다른 점이 없습니다. Field로 String formatterPhoneNumber를 가지고 있구요, String phoneNumber를 파라미터로 받는 constructor가 있네요. 그리고 formattedPhoneNumber를 리턴하는 getter가 정의되어 있습니다.
따로 떼어보니 별로 복잡하지 않죠? Constructor에 validation을 위한 코드가 들어가 있어 조금 길어졌지만 크게 나누어 보면 별다른 점이 없는 일반 클래스입니다. 다만, validatePhoneNumber() 라는 method 안에 들어있다는 것이 보통의 클래스와는 다른 점입니다.
Local class는 enclosing class(local class를 감싸고 있는 클래스를 의미합니다!)에 있는 멤버에 접근할 수가 있습니다. 위의 예제에서는 line#8에서 enclosing class의 멤버인 regularExpression에 접근했음을 확인 할 수 있습니다.
Local member에도 접근할 수 있는데요, local member라고 하면 local class가 정의된 block 내부를 의미하는 것 같습니다. 다만, 멤버의 값을 변경하는 등의 수정은 할 수가 없습니다. Line#6에서 보시다시피 validatePhoneNumber() 안의 numberLength 변수는 final이기 때문에 값을 수정할 수는 없습니다.
이렇게 사용되는 local class는 Enclosed class 내부에서만 사용이 될 수 있고, (위 예제의 line#39, 40에서 처럼요!) 외부에서는 사용될 수가 없다는 특징이 있습니다.
정확히 어떠한 경우에 사용 되면 더욱 효과적인지 조금 더 공부를 해보고 중요한 내용은 지속적으로 업데이트 하도록 하겠습니다.
보시고 궁금하신 사항이나 나누고 싶은 사항 등 모두 댓글로 알려주세요!
감사합니다. ☺️
*참고자료
https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
'Java' 카테고리의 다른 글
Static 키워드 알아보기 (0) | 2022.05.12 |
---|---|
Inner Class - Anonymous class(익명 클래스) (0) | 2022.05.10 |
Inner class 알아보기 (0) | 2022.05.09 |
Interface(인터페이스) 알아보기(1) (0) | 2022.05.07 |
Autoboxing & Unboxing (2) | 2022.05.05 |