자바 코드를 작성할 때는 다음과 같은 주의할 점들이 있습니다.
1. NullPointerException
NPE는 개발 시 발생할 수 있는 예외 상황 중 하나이며, 발생 가능성을 고려하지 않고 null 체크를 하지 않은 경우 발생할 수 있습니다.
Java 8 이후에는 Optional 클래스를 사용하여 이러한 상황을 방지할 수 있습니다.
예를 들어, String의 equals() 메서드에서도 null 체크를 하지 않으면 NPE가 발생할 수 있으므로 항상 null 체크를 해주는 것이 좋습니다.
// Bad Case : name으로 null값이 넘어오면 NPE 발생
public boolean isKim(String name) {
return name.equals("Kim");
}
// Good Case : name이 null값이어도 NPE 발생하지 않음
public boolean isKim(String name) {
return "Kim".equals(name);
}
// Good Case2 : org.apache.commons.lang 에서 제공하는 StringUtils 클래스 사용해서 비교
// 내부적으로 null 체크해서 안전
public boolean isKim(String name) {
return StringUtils.equals(name, "Kim");
}
빈 컬렉션에 null 값을 할당하는 것은 바람직하지 않은 습관입니다.
대신에 Collections 클래스의 EMPTY_LIST 상수와 같은 빈 컬렉션 값을 할당하는 것이 좋습니다.
이를 통해 null 값을 사용하는 경우 발생할 수 있는 예외 상황을 방지할 수 있습니다.
// Bad Case : null 세팅
List<String> strs = null;
// Good Case : EMPTY_LIST 세팅
List<String> strs = Collections.EMPTY_LIST
2. String 생성할 때 new 키워드 사용 X
// Slow
String s = new String("hello");
// fast
String s = "hello";
new 키워드를 사용하면 항상 새로운 객체를 만들어 힙에 추가하게 됩니다.
하지만 new 키워드를 사용하지 않으면 String pool에서 해당 값이 있는지 먼저 확인하고 없는 경우에만 추가하므로 더 효율적입니다.
따라서 가능한 경우, new 키워드를 사용하지 않고 String pool을 활용하는 것이 좋습니다.
3. 반복문 내에서 새로운 객체를 생성 X
for (int i = 0; i < 5; i++) {
Foo f = new Foo();
f.getMethod();
}
루프의 반복 횟수가 많을수록 많은 객체가 생성되기 때문에 이를 지양해야 합니다.
객체 생성은 시스템 자원을 많이 소모하므로 반복문 내에서 객체를 생성하거나 초기화하는 것은 성능 저하를 초래할 수 있습니다.
따라서 가능한 경우, 루프의 외부에서 미리 필요한 객체를 생성하고 초기화한 뒤, 반복문 내에서 해당 객체를 재활용하는 것이 좋습니다.
4. Collections를 반복하는 동안 수정 X
List<String> names = new ArrayList<>();
names.add("Kim");
names.add("Lee");
names.add("Park");
for (String name : names) {
if ("Kim".equals(name)) {
names.remove(name);
}
}
목록에서 Kim을 삭제하는 코드인데, 반복하면서 동시에 요소를 삭제하므로 ConcurrentModificationException이 발생할 수 있습니다.
이 예외는 여러 스레드에서 동시에 컬렉션을 수정하려고 할 때 발생할 수 있습니다.
따라서 리스트를 반복하면서 요소를 삭제하는 경우, Iterator 인터페이스를 사용하여 안전하게 요소를 삭제해야 합니다.
5. Switch-Case문에서 break 키워드 사용
int index = 0;
switch (index) {
case 0 :
System.out.println("Zero");
case 1 :
System.out.println("One");
break;
case 2 :
System.out.println("Two");
break;
// ...
default;
System.out.println("Default");
위 코드에서는 switch문을 사용하여 숫자에 따라 문자열을 출력하는 코드입니다.
그러나 case 0에서 break문이 빠져있기 때문에 "Zero" 이후 "One"까지 출력되게 됩니다.
따라서 switch문에서 각 case 블록의 마지막에는 break문을 적절하게 추가하여 다음 case 블록으로 넘어가지 않도록 주의해야 합니다.
6. 객체 비교 "=="와 "equals( )"의 차이
== 연산자는 두 객체의 참조값이 같은지를 비교하는 반면, equals() 메서드는 두 객체의 값을 비교합니다.
따라서 객체 비교 시, == 연산자와 equals() 메서드는 서로 다른 결과를 반환할 수 있으므로, 비교할 때 주의해야 합니다.
7. 무장적 StringBuffer 사용 X
StringBuilder와 StringBuffer는 문자열 조작을 위한 클래스입니다.
StringBuffer는 동기화된 메서드로 구현되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있지만, 오버헤드가 발생할 수 있습니다.
반면, StringBuilder는 동기화되지 않은 메서드로 구현되어 있어 단일 스레드 환경에서의 성능이 더 뛰어납니다.
따라서 동기화가 우선순위가 아니라면 StringBuilder를 사용하는 것이 더 효율적일 수 있습니다.
8. Java 파일 작성 시 표준
변수는 접근 제어자를 public, protected, private 순서로 정의하는 것이 일반적입니다.
이를 통해 클래스 외부에서 변수에 접근할 수 있는 범위를 제한하여 코드의 안정성과 유지보수성을 높일 수 있습니다.
생성자는 필드 수가 적은 생성자를 먼저 정의하는 것이 좋습니다. 이는 코드의 가독성을 높이고 필요한 정보만을 전달할 수 있도록 해줍니다.
메서드는 기능별로 그룹화하여 작성하는 것이 좋습니다.
이를 통해 유사한 기능을 수행하는 메서드들을 모아서 코드의 일관성과 가독성을 높일 수 있습니다.
또한, public 메서드와 private 메서드를 구분하여 작성해야 합니다.
코드 설명을 위해 주석을 사용할 수 있지만, 최대한 주석을 줄이고 가독성 있는 코드로 작성하는 것이 좋습니다.
따라서 코드 자체를 가독성 높은 방식으로 작성하고, 필요한 경우 주석을 추가하여 코드를 설명하는 것이 좋습니다.
이러한 주의할 점들을 잘 지켜야, 안정적이고 안전한 자바 코드를 작성할 수 있습니다.
'Java[자바] > Basic[기본]' 카테고리의 다른 글
자바 코드에서 주의할 점(1) (0) | 2023.03.27 |
---|---|
자바란 무엇인가? (0) | 2023.03.27 |