JEP 181: Nest-Based Access Control

JEP 181: Nest-Based Access Control

Java 프로그래밍 언어를 사용하면 다른 클래스 내에 클래스를 정의 할 수 있습니다. 이러한 클래스는 중첩 클래스 라고하며 여기에 설명되어 있습니다.

1
2
3
4
5
6
7
8

class OuterClass {
...
class NestedClass {
...
}
}

중첩 클래스는 정적 및 비 정적이라는 두 가지 범주로 나뉩니다. 선언 된 중첩 클래스static 는 정적 중첩 클래스 라고 합니다. 비 정적 중첩 클래스는 내부 클래스 라고 합니다.

1
2
3
4
5
6
7
8
9
10
11

class OuterClass {
...
static class StaticNestedClass {
...
}
InnerClass 클래스 {
...
}
}

중첩 된 클래스는 그 둘러싸는 클래스의 멤버입니다. 비 정적 중첩 클래스 (내부 클래스)는 private 클래스로 선언 된 경우에도 해당 클래스의 다른 멤버에 액세스 할 수 있습니다. 정적 중첩 클래스는 해당 클래스의 다른 멤버에 액세스 할 수 없습니다. 의 일원으로서 OuterClass, 중첩 클래스가 선언 될 수있다 private, public, protected, 또는 개인 패키지 . (외부 클래스는 선언 public또는 패키지 전용 일 수 있음을 상기하십시오 .)

중첩 클래스를 사용하는 이유

중첩 된 클래스를 사용하는 이유는 다음과 같습니다.

1
2
3
4
5
6
7
8
한 곳에서만 사용되는 클래스를 논리적으로 그룹화하는 방법입니다 . 
한 클래스가 다른 한 클래스에 유용하면 그 클래스에 클래스를 포함시키고 두 클래스를 함께 유지하는 것이 논리적입니다. 이러한 "헬퍼 클래스"를 중첩하면 패키지가보다 간결 해집니다.

그것은 캡슐화를 증가시킵니다 . A와 B라는 두 개의 최상위 클래스를 고려하십시오.
여기서 B는 선언되지 않으면 A의 멤버에게 액세스해야합니다 private. A 클래스 내의 B 클래스를 숨김으로써 A 멤버는 비공개로 선언 될 수 있고 B 멤버는 비공개로 선언 될 수 있습니다. 또한 B 자체는 외부 세계로부터 숨길 수 있습니다.

보다 읽기 쉽고 유지 보수가 쉬운 코드로 이어질 수 있습니다 . 최상위 클래스의 작은 클래스를 중첩하면 코드가 사용되는 위치에 가깝게 배치됩니다.

그럼 중첩 기반 접근 제어가 무엇이냐 하면 JEP181 클래스에 Nested로 묶인 충첩 클래스(nestmates)라도 다른 중첩 클래스에서
private 접근제어 자에 의해 해당 값을 reflect을 통해서라도 접근 되지 않았다

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

import java.lang.reflect.Field;

public class JEP181 {

public static class Nest1 {

private int varNest1;

public void f() throws Exception {

final Nest2 nest2 = new Nest2();

// this is ok
nest2.varNest2 = 2;

// this is not ok
final Field f2 = Nest2.class.getDeclaredField("varNest2");
f2.setInt(nest2, 2);

System.out.println(f2.getInt(nest2));

}

}

public static class Nest2 {
private int varNest2;
}

public static void main(String[] args) throws Exception {

new Nest1().f();

}

}

jdk 11 이하에서 위 코드를 실행 시켜 보면 java.lang.IllegalAccessException 에러가 나온다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\lib\idea_rt.jar=7454:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\test\out\production\test" JEP181
Exception in thread "main" java.lang.IllegalAccessException: Class JEP181$Nest1 can not access a member of class JEP181$Nest2 with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.setInt(Field.java:946)
at JEP181$Nest1.f(JEP181.java:18)
at JEP181.main(JEP181.java:32)

Process finished with exit code 1

```

위에 문제를 nestmates간에서는 호출할 수 있게 바꿔 준 것이다.

JDK11에서는 아래처럼 nestmates간에서는 정상적으로 호출이 된다.

“C:\Program Files\Java\jdk-11\bin\java.exe” “-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\lib\idea_rt.jar=7543:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.2\bin” -Dfile.encoding=UTF-8 -classpath D:\test\out\production\test JEP181
2

Process finished with exit code 0


# 참조 
-----
* [JEP 181](http://openjdk.java.net/jeps/181)
* [nested](https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html)