[Java_Summary] 단축키, final, static final, Singleton, Scanner, package import
1. 단축키
(이클립스 단축키)
- sysout + 'Ctrl'키 + 'space'키 누르면 System.out.println();이 자동 완성된다.
- 'Ctrl'키 + '/'키 누르면 선택한 줄이 모두 주석 처리된다.
- 'Alt'키 + 'Shift'키+마우스 왼클릭하면 여러줄 선택가능하고 선택한 줄을 한번에 앞으로 당기거나 수정할 수 있다.
- 'Alt'키 + 'Shift'키 + 's'키 +'r'키->select all -> generate하면 멤버변수(속성 값)에 대한 get, set함수가 자동 생성된다.
2. final
- final int a = 5;
- 초기값을 반드시 준다.
- 프로그램 내에서 a값을 바꾸려고 할 경우 오류가 난다.
- 상수의 개념으로도 사용할 수 있다.
- 예시) PI, 예금 금리 등 바뀌면 안되는 변수를 final로 고정한다.
- 메소드 앞에도 final을 사용할 수 있다.
- final int m1(){}
- 오버라이딩을 못하도록 한다.(상속 개념에서 사용한다.)
- 클래스 앞에도 final을 사용할 수 있다. >> 더이상 상속을 받지 않겠다. *심영 클래스
2.1 static final 변수
- static main 메서드 내에서는 선언할 수 없지만 클래스 멤버변수로는 선언할 수 있다.
- 해당 변수 값을 객체를 생성하지 않아도 사용할 수 있고, 수정은 불가하고, 처음부터 초기화해서 사용하고 싶을 때 사용할 수 있다.
- private static final int A = 100;도 가능하다.
2.2 싱글턴
- private static M1(){} 생성자인데 객체 생성전에 미리 실행하고, 외부에서 호출할 수 없다.(static은 생성자에서 사용 불가!)
- private M1(){}
싱글턴(Singleton) 패턴은 소프트웨어 엔지니어링에서 객체의 인스턴스가 오직 하나만 생성되는 것을 보장하는 디자인 패턴입니다. 이 패턴은 특정 클래스에 대한 단일 인스턴스만 필요한 경우에 유용하게 사용됩니다. 예를 들어, 설정, 데이터베이스 연결, 로깅 시스템 등의 경우 전체 애플리케이션에서 단 하나의 인스턴스만 있으면 충분합니다.
싱글턴 패턴을 구현하는 방법은 여러 가지가 있지만, 기본 원리는 동일합니다:
- 생성자를 private으로 선언하여 외부에서 직접 인스턴스를 생성할 수 없게 합니다.
- 클래스 내부에 자기 자신의 유일한 인스턴스를 참조할 private static 변수를 선언합니다.
- 외부에서 이 유일한 인스턴스에 접근할 수 있도록 public static 메소드를 제공합니다. 이 메소드는 내부적으로 인스턴스를 생성하는 로직을 포함하며, 이미 인스턴스가 생성되어 있다면 생성된 인스턴스를 반환합니다.
기본 싱글턴 패턴 구현 예시:
싱글턴 패턴의 주의점:
- 멀티스레드 환경에서의 안전성: 위의 기본 예시는 멀티스레딩 환경에서 안전하지 않습니다. 동시에 여러 스레드가 getInstance()를 호출할 때, 유일한 인스턴스가 아니게 여러 인스턴스가 생성될 수 있습니다. 이를 해결하기 위해 synchronized 키워드를 사용하거나, 초기화-on-demand holder idiom(클래스 로더의 클래스 초기화 단계를 이용한 스레드 안전한 지연 초기화 방법) 등의 방법을 사용할 수 있습니다.
- 전역 인스턴스 사용의 단점: 싱글턴 인스턴스가 전역적으로 접근 가능하기 때문에, 코드의 어느 곳에서나 변경될 수 있어 사이드 이펙트가 발생할 가능성이 있습니다. 이는 디버깅을 어렵게 만들고, 코드의 유지보수성을 저하시킬 수 있습니다.
2.3 싱글턴 예제
3. Scanner의 System.in() 입력 스트림에 대한 주의사항
Java에서 Scanner 클래스를 사용할 때 주의해야 할 몇 가지 포인트가 있습니다. 특히, 같은 입력 스트림(System.in)을 사용하여 여러 Scanner 객체를 생성하는 경우에는 더욱 그렇습니다. 당신이 제시한 코드에서는 System.in을 사용하여 두 개의 Scanner 객체가 생성됩니다: 하나는 main 메소드 내에서, 다른 하나는 MemberExam 클래스의 생성자 내에서입니다. 이 경우 일반적으로는 문제가 발생하지 않습니다. 왜냐하면 두 Scanner 객체 모두 동일한 입력 스트림(System.in)에서 데이터를 읽어들이기 때문입니다. 그러나 이런 사용 방식에는 몇 가지 주의해야 할 점이 있습니다:
- Scanner의 종료: Java에서는 Scanner 객체를 더 이상 사용하지 않을 때 close() 메소드를 호출하여 리소스를 해제하는 것이 좋습니다. 이는 특히 파일이나 네트워크 입력 스트림 같은 경우에 중요합니다. 그러나 System.in과 같은 표준 입력 스트림의 경우, 프로그램이 종료될 때까지 열려 있어야 하므로 일반적으로 close()를 호출하지 않습니다. System.in을 닫으면 다시 열 수 없으며, 이후의 입력 시도에서 NoSuchElementException이 발생할 수 있습니다.
- 엔터키 비우기: Scanner 클래스의 nextLine() 메소드를 사용한 후 nextInt(), next(), nextDouble() 등의 메소드를 사용할 때 주의해야 합니다. nextLine() 메소드는 엔터키(즉, 줄 바꿈 문자)까지 읽어들인 후 입력 버퍼를 비웁니다. 그러나 nextInt()나 next() 메소드는 엔터키를 비우지 않고 입력 버퍼에 남겨둡니다. 이로 인해 다음 nextLine() 호출 시 예상치 못한 동작이 발생할 수 있습니다. 당신의 코드에서는 nextInt()와 next()만 사용하고 있으므로, 이 문제는 발생하지 않습니다.
- 다중 Scanner 객체: 동일한 입력 스트림에 대해 여러 Scanner 객체를 생성하는 것은 일반적으로 권장되지 않지만, System.in 같은 경우에는 큰 문제가 되지 않을 수 있습니다. 그러나 가능하다면 프로그램 전체에서 하나의 Scanner 객체를 재사용하는 것이 좋습니다. 이렇게 하면 리소스 사용을 최소화하고, 객체 관리를 더 단순하게 할 수 있습니다.
코드의 현재 구성에서는 Scanner 객체를 close()하지 않고, 엔터키를 명시적으로 비우지 않아도 문제가 발생하지 않습니다. 그러나 좋은 프로그래밍 습관을 위해, 가능하다면 한 개의 Scanner 객체를 재사용하고, 필요에 따라 엔터키를 처리하는 방법을 고려하는 것이 좋습니다.
4. 다른 패키지에 있을 때 불러오는 방법
- import를 사용해서 패키지이름 닷 클래스이름으로 접근한다.
- 객체 생성할 땐, 패키지이름 닷 클래스 이름으로 명시한다.
- 패키지이름 닷으로 명시하지 않으면 default로 import로 받은 클래스를 받아온다.
>>>패키지이름 닷 아스트레이는 해당 패키지 안에 동일 레벨 내에 있는 모든 클래스를 import한다.
235p부터 open challenge, 연습문제, 실습문제 풀기
5. char의 비교 equals
- char Type은 문자열 하나만 값으로 받을 수 있다.
- c1 == c2 같으면 true, 다르면 false를 반환한다.
- c1.equals(c2); 이런건 char 타입에선 안되고 String타입만 가능하다.
6. 이중 반복문이 있는 경우 continue와 break
while 문 안에 for 문이 있을 때, 특정 조건에서 while 문을 continue 하고자 하는 경우, continue 문을 직접 사용할 수 없습니다. 왜냐하면 continue 문은 현재 실행 중인 가장 가까운 루프를 다시 시작하게 하므로, for 문에 적용됩니다. while 문으로 직접 점프하고 싶다면, 다른 접근 방법을 사용해야 합니다.
접근 방법 1: 플래그 변수 사용
while 문을 continue 하기 위한 조건을 플래그(flag) 변수를 사용하여 관리할 수 있습니다. for 문 내에서 특정 조건이 충족되면 플래그 변수의 값을 변경하고, for 문이 끝난 직후에 이 플래그 변수의 상태를 검사하여 while 문을 continue 할지 결정합니다.
접근 방법 2: 레이블을 사용한 break
Java에서는 레이블(label)을 사용하여 특정 루프를 지정하고, break 또는 continue 문과 함께 이 레이블을 사용하여 다중 루프 구조에서 원하는 루프를 직접 제어할 수 있습니다. while 문에 레이블을 지정하고, for 루프 내에서 조건이 충족될 때 해당 레이블로 break 하면 while 문을 탈출할 수 있습니다.
outerLoop: while (condition) {}