이 글은 책 이펙티브 자바 3판 Item57을 참고했습니다. 잘못된 내용이 있다면 편하게 말씀해주세요 🙏🏻
주제
일반 프로그래밍 원칙
결론
지역 변수가 많거나 범위가 넓으면 오류 발생이 크다.
지역 변수의 유효 범위를 최소로 줄이면 가독성과 유지보수성이 높아지고 오류 가능성은 낮아진다.
지역 변수의 범위와 오류를 줄이는 방법 5가지를 알아보자
✅ 1. 가장 처음 쓰일 때 선언하기
C언어 개발자들은 지역 변수를 코드 블록 첫머리에 선언하는 경우가 많았다. 하지만 코드가 길어지면 정작 사용할 때 이해가 어렵다.
자바에서는 어디서든 선언 가능하니 사용하기 직전에 선언하자
public class Car {
public static void main(String[] args) {
String name = "BMW"
// ...
// 중간 코드 50줄
// ...
// name이 뭐였지?
String type = "auto"; // 단편적인 예
if (type.equals("auto") {
}
}
}
✅ 2. 모든 지역변수는 선언과 동시에 초기화하기
선언과 동시에 초기화하지 않고 사용하면 default 초기값이 들어가 로직에 문제가 생길 수 있거나, 중간에 재할당하면 맥락 파악이 어렵다.
public class Car {
public static void main(String[] args) {
String name; // 초기화 선언 X
// ...
if (name.equals("SONATA") {
// 선언과 동시에 초기화 하지 않으면 초기화를 까먹어 문제가 될 수 있다.
}
}
}
단, 예외가 있다면 try-catch 문에서 변수 초기화 과정에서 Exception 가능성이 있다면 try 블록 안에서 초기화하는 경우를 제외
public class Car {
public static void main(String[] args) {
int power;
try {
power = Engin.getPower(); // Engin.getPower() 메서드 자체가 Exception 가능성이 있는 경우
} catch (IOException e) {
throw new RunTimeException();
}
}
}
✅ 3. while 대신 for 사용하기
for의 장점
- while문 작성시 오류를 방지할 수 있다.
// while문 - 오류 발생 가능성 Up
public class Name {
public static void main(String[] args) {
List<String> lastName = Arrays.asList("김", "이", "박");
Iterator<String> i = like.iterator();
while(i.hasNext()) {
System.out.print(i.next());
}
List<String> fisrtName = Arrays.asList("구","지은", "명수");
Iterator<String> i2 = hate.iterator();
while(i.hasNext()) { // i2.hasNext()가 아닌 i.hasNext()로 실수! (컴파일, 런타임 에러 체크 X)
System.out.println(i2.next());
}
}
}
// for의 장점 : 로컬 변수, 컴파일 오류로 체크 가능
public class Name {
public static void main(String[] args) {
List<String> lastName = Arrays.asList("김", "이", "박");
for (Iterator<String> i = like.iterator(); i.hasNext();) {
System.out.print(i.next());
} // for문 종료 후 i는 for문에 대한 지역변수로 사라짐
// 아래 for에서는 i.hasNext() 접근이 불가하여 컴파일에서 체크 O
List<String> fisrtName = Arrays.asList("구","지은", "명수");
for (Iterator<String> i2 = hate.iterator(); i.hasNext();) {
System.out.print(i2.next());
}
}
}
- 코드가 짧다.
// for
for (int i = 0, n = average(nums); i < n; i++) {
}
// while
int i = 0;
int n = average(nums);
while (i < n) {
}
위 코드에서 for가 while 보다 짧아 가독성이 좋은 것을 볼 수 있다.
*tip) average(nums)에 대한 계산 결과를 미리 n = average(nums)으로 선언해주었다. for (int i = 0, n = average(nums); i < n; i++) 만약 이를 for (int i = 0, ; i < average(nums); i++)으로 해주었다면 매번 반복할 때마다 average() 연산을 하기 때문에 성능이 안 좋다. 따라서 for문에 대한 조건문 결과는 for 문 첫 번째 에서 계산하는 것이 좋다.
✅ 4. 컬렉션이나 배열 반복 시
컬렉션이나 배열을 순회만 하는 경우에는 for-each 문이 좋다.
for (Element e : c) {
// 컬렉션 c를 순회하여 e로 무언가 하는 경우
}
이터레이터를 필요할 때 반복 (e.g. remove 메서드를 사용할 때)
for (Iterator<Element> itr = c.iterator(); itr.hasNext();) {
Element e = itr.next();
// 만약 이터레이터를 사용해 특정 e를 지운다면
if (e.tostring() == "김") {
itr.remove();
}
}
✅ 5. 메서드를 작게 유지하고 한 가지 기능에 집중
단순히 메서드를 기능별로 잘게 쪼개면 지역 변수가 최소화될 것이다.
'☕️ JAVA > 🦋 Effective Java' 카테고리의 다른 글
자바의 'enum'과 'lambda'를 클래스로 이해해보기 🔎 (2) | 2022.01.21 |
---|---|
정확한 답이 필요하다면 float와 double은 피하자 🏃♂️ (0) | 2022.01.18 |
표준 라이브러리를 익히고 사용하자 ㉿ (0) | 2022.01.18 |
모든 구현 클래스에서 Object의 toString 재정의를 고려하자 🗣 (1) | 2022.01.15 |
객체 생성할 때 '생성자' 대신 '정적 팩터리 메서드'를 써볼까? 🏭 (2) | 2022.01.15 |
댓글