들어가며
내부 클래스는 자바에서 클래스 내부에 정의된 클래스를 의미합니다. 이를 통해 클래스 내부에서 다른 클래스를 사용하거나 새로운 클래스를 정의할 수 있으며, 코드의 가독성과 모듈성을 향상시킬 수 있습니다.
내부 클래스는 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스, 익명 내부 클래스로 구분할 수 있으며, 각각의 특징과 사용 방법이 다릅니다. 내부 클래스는 외부 클래스의 인스턴스 변수와 메소드에 접근할 수 있으며, 상속과 다형성을 지원합니다.
또한, 내부 클래스는 스트림 API와 함께 사용하여 코드의 가독성과 유지 보수성을 향상시킬 수 있습니다.
내부 클래스는 자바에서 매우 유용하게 사용되는 기능 중 하나이며, 이를 활용하여 더 나은 코드를 작성할 수 있습니다. 이번 글에서는 내부 클래스의 종류와 사용 방법, 장단점, 예시 및 활용 방법 등을 자세히 살펴보겠습니다.
내부 클래스란 무엇인가?
자바에서 내부 클래스(Inner class)는 다른 클래스 내부에서 정의되어 있는 클래스를 의미합니다. 즉, 클래스 내부에 다른 클래스를 정의하는 것입니다. 내부 클래스는 외부 클래스와 밀접하게 관련되어 있는 클래스로서, 외부 클래스의 멤버 변수와 메서드에 쉽게 접근할 수 있습니다.
내부 클래스는 외부 클래스의 멤버 변수와 메서드에 접근할 수 있기 때문에, 데이터 캡슐화와 보안성을 높일 수 있으며, 코드의 가독성을 높일 수 있습니다. 내부 클래스는 외부 클래스와 밀접한 관계를 가지고 있기 때문에, 내부 클래스를 사용함으로써 코드의 구조와 설계를 개선할 수 있습니다.
또한 내부 클래스는 다른 클래스에서는 접근할 수 없는 private으로 선언된 멤버 변수와 메서드에도 접근이 가능하며, 내부 클래스에서 외부 클래스의 private 멤버 변수와 메서드에도 접근할 수 있습니다. 이는 내부 클래스를 활용한 데이터 캡슐화의 장점으로 이어지게 됩니다.
내부 클래스의 종류
내부 클래스는 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스, 익명 내부 클래스로 구분되며, 각각의 특징과 사용 방법이 다릅니다. 하나씩 살펴 보겠습니다.
인스턴스 내부 클래스
인스턴스 내부 클래스(Instance Inner Class)는 다른 클래스 내부에서 선언되고, 특정 인스턴스와 관련된 클래스를 의미합니다. 즉, 특정 객체에 종속적인 클래스를 의미합니다.
인스턴스 내부 클래스는 외부 클래스의 인스턴스가 생성될 때, 함께 생성되며, 외부 클래스의 멤버 변수와 메서드에 접근할 수 있습니다. 인스턴스 내부 클래스는 외부 클래스의 모든 멤버 변수와 메서드에 접근할 수 있기 때문에, 인스턴스 내부 클래스에서는 외부 클래스의 인스턴스 멤버 변수를 사용할 수 있습니다.
인스턴스 내부 클래스는 다른 클래스에서 사용될 일이 없으며, 외부 클래스의 인스턴스가 생성될 때만 생성되므로, 메모리 사용 측면에서는 이점이 있습니다. 또한, 외부 클래스의 인스턴스 멤버 변수와 함께 사용될 때 유용하며, 특정 인스턴스와 관련된 클래스를 정의하는 데 사용될 수 있습니다.
다음은 인스턴스 내부 클래스의 예시입니다.
public class OuterClass {
private int outerVar;
public class InnerClass {
public void printOuterVar() {
System.out.println("Outer Variable: " + outerVar);
}
}
public void createInnerClass() {
InnerClass inner = new InnerClass();
inner.printOuterVar();
}
}
위 코드에서 InnerClass는 OuterClass 내부에 선언되어 있습니다. InnerClass는 OuterClass의 인스턴스 멤버 변수 outerVar에 접근할 수 있으며, createInnerClass 메서드를 통해 InnerClass의 인스턴스를 생성하고, printOuterVar 메서드를 호출하여 outerVar 값을 출력합니다.
정적 내부 클래스
정적 내부 클래스(Static Inner Class)는 다른 클래스 내부에서 선언되고, 특정 인스턴스와 관계없이 클래스 자체에 종속적인 클래스를 의미합니다. 즉, 특정 객체에 종속되지 않는 클래스입니다.
정적 내부 클래스는 외부 클래스의 멤버 변수와 메서드에 접근할 수 있지만, 외부 클래스의 인스턴스 멤버 변수에는 접근할 수 없습니다. 정적 내부 클래스는 외부 클래스의 인스턴스가 생성되지 않아도 생성될 수 있기 때문에, 메모리 사용 측면에서 이점이 있습니다.
정적 내부 클래스는 다른 클래스에서도 사용될 수 있으며, 특정 인스턴스와 관계없이 클래스 자체에서 사용해야 하는 클래스를 정의하는 데 사용될 수 있습니다. 또한, 외부 클래스의 멤버 변수와 메서드를 사용할 필요가 있는 경우, 정적 내부 클래스를 사용할 수 있습니다.
다음은 정적 내부 클래스의 예시입니다.
public class OuterClass {
private static int outerVar;
public static class InnerClass {
public void printOuterVar() {
System.out.println("Outer Variable: " + outerVar);
}
}
public static void createInnerClass() {
InnerClass inner = new InnerClass();
inner.printOuterVar();
}
}
위 코드에서 InnerClass는 OuterClass 내부에 선언되어 있습니다. InnerClass는 OuterClass의 정적 멤버 변수 outerVar에 접근할 수 있으며, createInnerClass 메서드를 통해 InnerClass의 인스턴스를 생성하고, printOuterVar 메서드를 호출하여 outerVar 값을 출력합니다. OuterClass의 인스턴스를 생성하지 않아도 InnerClass의 인스턴스를 생성할 수 있으므로, createInnerClass 메서드는 정적 메서드로 선언되어 있습니다.
지역 내부 클래스
지역 내부 클래스(Local Inner Class)는 메서드 내부에서 선언되어 있는 클래스를 의미합니다. 즉, 메서드 내부에 정의되어 있으며, 해당 메서드에서만 사용할 수 있습니다.
지역 내부 클래스는 외부 클래스나 외부 메서드와 독립적이며, 외부 클래스나 메서드의 멤버 변수에 접근할 수 없습니다. 대신, 지역 내부 클래스는 메서드 내부의 로컬 변수나 매개 변수에 접근할 수 있습니다.
지역 내부 클래스는 메서드 내부에서만 사용될 클래스를 정의하는 데 사용될 수 있습니다. 특히, 메서드 내부에서 작업을 수행하는 중간 단계에서 임시적으로 사용되는 클래스를 정의할 때 유용합니다.
public class OuterClass {
public void printMessage(final String message) {
class LocalInnerClass {
public void print() {
System.out.println(message);
}
}
LocalInnerClass inner = new LocalInnerClass();
inner.print();
}
}
위 코드에서 LocalInnerClass는 printMessage 메서드 내부에서 선언되어 있습니다. LocalInnerClass는 printMessage 메서드 내부에서만 사용되며, message 매개 변수에 접근할 수 있습니다. printMessage 메서드를 호출할 때, LocalInnerClass의 인스턴스를 생성하고, print 메서드를 호출하여 message 값을 출력합니다.
익명 내부 클래스
익명 내부 클래스(Anonymous Inner Class)는 이름이 없는 내부 클래스를 의미합니다. 즉, 클래스 선언과 인스턴스 생성을 동시에 처리하는 방법입니다.
익명 내부 클래스는 인터페이스나 추상 클래스의 구현체를 만들 때 주로 사용됩니다. 익명 내부 클래스를 사용하면 클래스를 따로 선언하지 않아도 되기 때문에 코드의 길이를 줄일 수 있습니다.
public class OuterClass {
public void sayHello() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
위 코드에서 Runnable 인터페이스를 구현하는 익명 내부 클래스를 사용하여 sayHello 메서드 내에서 새로운 스레드를 실행합니다. 익명 내부 클래스는 Runnable 인터페이스의 구현체를 만들어 run 메서드를 재정의합니다. 이렇게 만들어진 익명 내부 클래스는 Runnable 인터페이스를 구현한 클래스의 인스턴스로 사용됩니다.
익명 내부 클래스는 한 번만 사용되는 클래스이기 때문에, 일회성 작업을 수행하는 경우에 편리하게 사용할 수 있습니다.
내부 클래스의 장점과 단점
장점
- 캡슐화 : 내부 클래스는 외부 클래스 내부에 선언되므로, 외부에서는 내부 클래스에 직접 접근할 수 없습니다. 이로써 내부 클래스의 멤버 변수나 메서드를 외부에서 직접 변경하는 것을 막아 캡슐화를 실현할 수 있습니다.
- 코드의 가독성 향상 : 내부 클래스를 사용하면, 외부 클래스 내부의 관련된 클래스를 그룹화하여 가독성을 향상시킬 수 있습니다. 또한, 메서드 내부에서 사용하는 지역 클래스는 해당 메서드에서만 사용되므로 관련성이 높아집니다.
- 캐시 효과 : 내부 클래스를 사용하면 클래스 로딩 시간을 단축할 수 있습니다. 내부 클래스는 외부 클래스와 함께 로딩되므로, 한 번 로딩된 내부 클래스는 이후에도 캐시에 저장되어 다시 로딩되지 않아도 됩니다.
단점
- 코드 복잡성: 내부 클래스를 사용하면 코드의 복잡성이 증가할 수 있습니다. 내부 클래스를 사용하면서도 외부 클래스와 내부 클래스 간에 데이터를 주고받아야 하는 경우가 발생할 수 있습니다.
- 의존성 증가: 내부 클래스를 사용하면 외부 클래스와 내부 클래스 간에 서로 의존성이 증가할 수 있습니다. 내부 클래스에서 외부 클래스의 멤버 변수나 메서드에 접근하면, 해당 멤버 변수나 메서드가 변경될 때 내부 클래스의 동작에 영향을 줄 수 있습니다.
- 메모리 사용량 증가: 내부 클래스를 사용하면, 추가적인 메모리 공간이 필요합니다. 외부 클래스와 내부 클래스가 함께 로딩되므로, 내부 클래스를 사용하면 불필요한 메모리 공간이 사용될 수 있습니다.
내부 클래스의 사용 예시
내부 클래스는 다양한 용도로 사용될 수 있습니다. 여기서는 몇 가지 대표적인 사용 예시를 소개합니다.
이벤트 처리
내부 클래스는 이벤트 처리를 위해 주로 사용됩니다. 예를 들어, 버튼 클릭 이벤트 처리를 위해 다음과 같이 내부 클래스를 사용할 수 있습니다.
public class Button {
private OnClickListener listener;
public interface OnClickListener {
void onClick();
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
public void click() {
if (listener != null) {
listener.onClick();
}
}
}
public class Main {
public static void main(String[] args) {
Button button = new Button();
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick() {
System.out.println("Button clicked");
}
});
button.click();
}
}
위 코드에서는 버튼 클래스(Button)에 OnClickListener 인터페이스를 정의하고, 이를 구현한 내부 클래스(Button.OnClickListener)를 사용하여 클릭 이벤트 처리를 합니다.
데이터 구조
내부 클래스는 데이터 구조를 표현하기 위해 사용될 수 있습니다. 예를 들어, 트리 자료구조를 구현할 때 다음과 같이 내부 클래스를 사용할 수 있습니다.
public class TreeNode {
private int value;
private TreeNode left;
private TreeNode right;
public TreeNode(int value) {
this.value = value;
}
public void insert(int value) {
if (value < this.value) {
if (left == null) {
left = new TreeNode(value);
} else {
left.insert(value);
}
} else {
if (right == null) {
right = new TreeNode(value);
} else {
right.insert(value);
}
}
}
// ...
}
위 코드에서는 TreeNode 클래스 내부에 left, right 필드와 insert 메서드를 구현하고 있습니다. insert 메서드에서는 새로운 노드를 생성할 때 내부 클래스를 사용하여 구현하고 있습니다.
쓰레드
내부 클래스는 쓰레드를 구현할 때 주로 사용됩니다. 예를 들어, 다음과 같이 내부 클래스를 사용하여 새로운 쓰레드를 생성할 수 있습니다.
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 작업 수행
}
});
thread.start();
}
}
위 코드에서는 Thread 클래스의 생성자에 인자로 Runnable 인터페이스를 구현한 내부 클래스를 전달하여 새로운 쓰레드를 생성합니다.
내부 클래스의 생성과 사용 방법
내부 클래스는 외부 클래스의 멤버로 선언되며, 외부 클래스 내부에서 생성되어 사용됩니다.
내부 클래스의 생성과 사용 방법은 다음과 같습니다.
인스턴스 내부 클래스 생성하기
인스턴스 내부 클래스를 생성하려면 외부 클래스의 인스턴스를 먼저 생성해야 합니다. 그리고 인스턴스 내부 클래스는 외부 클래스의 인스턴스를 참조할 수 있으므로, 생성자를 통해 외부 클래스의 인스턴스를 전달받아 필드에 저장합니다.
public class Outer {
private int x;
public class Inner {
public void printX() {
System.out.println(x);
}
}
public void createInner() {
Inner inner = new Inner();
inner.printX();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.createInner();
}
}
위 코드에서는 Outer 클래스 내부에 Inner 클래스를 선언하고 있습니다. Inner 클래스는 Outer 클래스의 필드인 x를 참조하고 있습니다. createInner 메서드에서는 Inner 클래스의 인스턴스를 생성하고 printX 메서드를 호출하여 x 값을 출력합니다.
정적 내부 클래스 생성하기
정적 내부 클래스를 생성하려면 외부 클래스와 동일한 방식으로 인스턴스를 생성하지 않아도 됩니다.
public class Outer {
private static int x;
public static class Inner {
public void printX() {
System.out.println(x);
}
}
public static void createInner() {
Inner inner = new Inner();
inner.printX();
}
}
public class Main {
public static void main(String[] args) {
Outer.createInner();
}
}
위 코드에서는 Outer 클래스 내부에 static 키워드를 사용하여 Inner 클래스를 선언하고 있습니다. Inner 클래스는 Outer 클래스의 정적 필드인 x를 참조하고 있습니다. createInner 메서드에서는 Inner 클래스의 인스턴스를 생성하고 printX 메서드를 호출하여 x 값을 출력합니다.
지역 내부 클래스 생성하기
지역 내부 클래스는 외부 클래스의 메서드 내부에서 선언됩니다. 지역 내부 클래스는 외부 클래스의 인스턴스에 접근할 수 없으며, 메서드의 로컬 변수와 매개변수를 참조할 수 있습니다.
public class Outer {
public void createInner(int x) {
class Inner {
public void printX() {
System.out.println(x);
}
}
Inner inner = new Inner();
inner.printX();
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
outer.createInner(10);
}
}
위 코드에서는 Outer 클래스의 createInner 메서드 내부에서 Inner 클래스를 선언합니다.
내부 클래스와 외부 클래스 간의 접근 권한
내부 클래스와 외부 클래스 간의 접근 권한은 다음과 같습니다.
1. 인스턴스 내부 클래스에서의 접근 권한
인스턴스 내부 클래스는 외부 클래스의 인스턴스와 밀접한 관계가 있으므로, 외부 클래스의 모든 멤버에 접근할 수 있습니다. 따라서 인스턴스 내부 클래스에서는 외부 클래스의 인스턴스 필드와 메서드에 자유롭게 접근할 수 있습니다.
2. 정적 내부 클래스에서의 접근 권한
정적 내부 클래스는 외부 클래스의 인스턴스와 관계없이 사용될 수 있으므로, 외부 클래스의 정적 멤버에만 접근할 수 있습니다. 따라서 정적 내부 클래스에서는 외부 클래스의 정적 필드와 메서드에만 접근할 수 있습니다.
3. 지역 내부 클래스에서의 접근 권한
지역 내부 클래스는 외부 클래스의 인스턴스와는 무관하며, 외부 클래스의 메서드 내부에서만 사용됩니다. 따라서 지역 내부 클래스에서는 외부 클래스의 메서드의 매개변수와 로컬 변수에만 접근할 수 있습니다.
4. 익명 내부 클래스에서의 접근 권한
익명 내부 클래스는 외부 클래스의 인스턴스와는 무관하며, 외부 클래스의 메서드 내부에서만 사용됩니다. 따라서 익명 내부 클래스에서는 외부 클래스의 메서드의 매개변수와 로컬 변수에만 접근할 수 있습니다.
위 내용을 정리하면, 내부 클래스의 접근 권한은 외부 클래스와 같은 레벨의 접근 권한을 가집니다. 따라서 내부 클래스에서는 외부 클래스의 모든 멤버에 접근할 수 있습니다. 그러나 외부 클래스에서는 내부 클래스의 private 멤버에는 접근할 수 없습니다.
내부 클래스의 상속과 다형성
내부 클래스도 일반적인 클래스와 마찬가지로 상속과 다형성을 지원합니다.
먼저, 내부 클래스를 상속받는 경우, 내부 클래스가 private으로 선언되지 않았다면, 상속받은 클래스에서 내부 클래스의 멤버에 접근할 수 있습니다. 이는 내부 클래스가 일반적인 클래스와 마찬가지로 상속되기 때문입니다.
다음으로, 내부 클래스도 일반적인 클래스와 마찬가지로 다형성을 지원합니다. 내부 클래스를 사용하는 코드에서 내부 클래스 타입의 변수를 선언하고, 이 변수에 다른 내부 클래스의 인스턴스를 할당하는 것이 가능합니다. 이 때, 내부 클래스 타입의 변수를 사용하여 해당 내부 클래스의 멤버에 접근할 수 있습니다.
예를 들어, 다음과 같이 Person 클래스와 이를 상속받은 Student 클래스가 있을 때, Student 클래스 내부에서 InnerClass 내부 클래스를 정의하고, 이를 사용하는 코드를 작성할 수 있습니다.
public class Person {
public void greet() {
System.out.println("Hello, I am a person.");
}
public class InnerClass {
public void greet() {
System.out.println("Hello, I am an inner class.");
}
}
}
public class Student extends Person {
public void greet() {
System.out.println("Hello, I am a student.");
}
public static void main(String[] args) {
Person.InnerClass inner = new Student().new InnerClass();
inner.greet(); // "Hello, I am an inner class."
}
}
위 코드에서, Student 클래스에서는 Person 클래스 내부에 정의된 InnerClass 내부 클래스를 사용합니다. 이를 위해, Student 클래스 내부에서 InnerClass 클래스를 다시 정의하지 않고, Person 클래스의 InnerClass 클래스를 사용합니다. 이를 통해, 내부 클래스도 일반적인 클래스와 같이 다형성을 지원하는 것을 확인할 수 있습니다.
내부 클래스와 람다 표현식의 차이점
내부 클래스와 람다 표현식은 비슷한 기능을 수행하지만, 몇 가지 차이점이 있습니다.
문법적 차이점
내부 클래스는 클래스를 정의하고 인스턴스화하는 전통적인 객체 지향 방식을 따릅니다. 반면 람다 표현식은 더 간결한 문법을 제공합니다. 람다 표현식은 인터페이스를 구현하는 익명 클래스의 객체를 생성하는 것과 같은 동작을 수행하지만, 람다 표현식은 클래스를 선언하지 않기 때문에 코드가 더 간결해집니다.
상태 유지
내부 클래스는 외부 클래스의 인스턴스 변수에 액세스할 수 있으며, 이를 통해 상태를 유지할 수 있습니다. 반면 람다 표현식은 일반적으로 final 변수에만 액세스할 수 있습니다. 따라서 람다 표현식은 내부 상태를 유지하기 위해 보통 외부 클래스에서 final 필드를 정의하고 사용합니다.
가독성
람다 표현식은 간결한 문법을 사용하므로 코드의 가독성을 향상시킵니다. 예를 들어, 람다 표현식을 사용하면 코드가 더 직관적이고 읽기 쉽습니다. 반면 내부 클래스는 명시적으로 클래스를 정의해야 하므로 코드가 더 복잡해질 수 있습니다.
성능
내부 클래스는 클래스를 정의하고 객체를 인스턴스화해야 하므로 람다 표현식보다 더 많은 오버헤드가 발생합니다. 따라서 람다 표현식은 내부 클래스보다 성능이 좋을 수 있습니다. 그러나 대부분의 상황에서는 미세한 차이로 인해 람다 표현식을 내부 클래스보다 더 선호하는 것이 좋습니다.
결론적으로, 내부 클래스와 람다 표현식은 모두 유용한 도구이며, 어떤 것을 사용할지는 코드의 특정 요구 사항에 따라 다릅니다.
내부 클래스와 스트림 API의 활용
내부 클래스와 스트림 API를 함께 사용하면 매우 유용한 기능을 구현할 수 있습니다. 내부 클래스는 스트림 API에서 사용할 수 있는 다양한 함수형 인터페이스의 구현을 간편하게 할 수 있습니다. 또한 내부 클래스를 사용하면 코드의 가독성과 유지보수성을 높일 수 있습니다.
예를 들어, ArrayList에 있는 모든 문자열을 대문자로 변환한 후 새로운 리스트로 만드는 코드를 작성해보겠습니다.
List<String> originalList = Arrays.asList("apple", "banana", "cherry");
List<String> uppercaseList = new ArrayList<>();
for (String s : originalList) {
uppercaseList.add(s.toUpperCase());
}
위 코드를 스트림 API를 사용하여 변환하면 다음과 같이 작성할 수 있습니다.
List<String> originalList = Arrays.asList("apple", "banana", "cherry");
List<String> uppercaseList = originalList.stream()
.map(s -> s.toUpperCase())
.collect(Collectors.toList());
이 코드는 람다 표현식을 사용하여 간결하게 작성되었습니다. 그러나 이를 더 개선하여 내부 클래스를 사용할 수도 있습니다. 예를 들어, 다음과 같이 Function 인터페이스를 구현하는 내부 클래스를 사용하여 코드를 작성할 수 있습니다.
List<String> originalList = Arrays.asList("apple", "banana", "cherry");
List<String> uppercaseList = originalList.stream()
.map(new ToUpperCaseFunction())
.collect(Collectors.toList());
private static class ToUpperCaseFunction implements Function<String, String> {
@Override
public String apply(String s) {
return s.toUpperCase();
}
}
위 코드에서는 Function 인터페이스를 구현하는 내부 클래스인 ToUpperCaseFunction을 정의하고, 이를 map() 메소드에 전달하여 각 문자열을 대문자로 변환합니다.
내부 클래스를 사용하는 이점 중 하나는 코드의 가독성과 유지보수성이 높아진다는 것입니다. 이 코드에서는 ToUpperCaseFunction 클래스가 각 문자열을 대문자로 변환하는 역할을 하므로, 코드의 의도가 더 명확하게 전달됩니다. 또한 ToUpperCaseFunction 클래스를 다른 곳에서도 사용할 수 있으므로, 코드의 재사용성도 높아집니다.
나가며
내부 클래스를 사용할 때는 장단점을 고려하여 적절하게 활용해야 합니다. 내부 클래스는 코드의 중첩과 복잡도를 증가시킬 수 있으며, 외부 클래스와의 결합도를 높일 수 있습니다. 그러나 내부 클래스를 사용하면 코드를 더 모듈화하고, 외부 클래스와의 의존성을 감소시키며, 코드의 가독성과 유지 보수성을 높일 수 있습니다.
따라서 내부 클래스는 자바에서 매우 유용하게 사용되는 기능 중 하나이며, 이를 활용하여 더 나은 코드를 작성할 수 있습니다.
'Language > Java' 카테고리의 다른 글
[JAVA] 객체 지향 프로그래밍 용어 정리 (0) | 2023.04.23 |
---|---|
[JAVA] 상황별 반복문 사용 기준(while문, do-while문, for문) (1) | 2023.04.22 |
[Java] 문자열 공백 제거 trim() Method 정의 및 사용법 (1) | 2023.03.27 |
[Java] 증감연산자, 부호연산자 (0) | 2023.02.03 |
[JAVA] 연산자의 우선순위와 결합규칙 (0) | 2023.02.01 |
댓글