일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 코딩테스트
- String
- 공부방식
- mapstruct
- 정리글 작성법
- Git #회고록
- 네트워크 기초
- 회고록
- 인터넷 #ISP
- 피드백
- Java환경
- 시작 #꾸준히 #과하지않게
- 회고
- git #intellij
- 코드스테이츠 #
- 회고록_코드스테이츠
- 사용자계정 #WSL2
- WSL #Linux #ubuntu
- 에러해결
- 글 foramt
- 회고 #주간회고
- WSL2 #권한
- 코드스테이츠 #회고록
- OOP
- 호스트주소 #Host주소
- 몰입학습 #몰입
- 롤중독
- 백엔드로드맵
- jvm
- JAVA기본
- Today
- Total
느리더라도 꾸준히
[Java기본]static 메서드는 왜 필요할까? 본문
목표
메서드는 클래스내부에서 인스턴스 메서드와 static 메서드로 선언할수 있다. 이때 이 static 메서드가 왜 필요한지를 이해하고 어떤 장단점이 있는지 이해하자.
본문
static Method
정적메서드는 static 멤버들만 이용해서, 모든 인스턴스에 공유되는 메서드(명령모음)이다. 즉 해당 객체의 인스턴스 변수를 사용하지 않고, 메서드를 호출한다는 의미이다.
예를 들어 우리는 String.format(), Math.max(), Arrays.sort() 등의 메서드들은 해당 객체를 new로 생성하지 않아도, 해당 클래스의 메서드를 사용할 수 있다. 이는 바로 static 메서드가 클래스 영역에 저장되어 있기 때문이다.
static Method 어떻게 사용할까?
method 앞에 static만 붙으면 된다.
package staticMethodTest.subpackage;
// Java 환경
public class stringkyu {
public String str;
private final byte[] value = new byte[10];
//String 내부에서 사용되는 필드들...
public static String addString(String f_str, String l_str) {
return f_str + l_str;
}
// 다른 String 메서드들.........
}
Stringkyu.java 는 내가 만들어본 String 클래스이다. 내부는 정말 간단하게 다음과 같이 되어있다.
접근제한자를 public으로 설정했기때문에, 상위 디렉토리든 하위 디렉토리든 사용이 가능하다.
public class Main3 {
public static void main(String[] args) {
String firstName = "김";
String lastName = "규하";
String f_Name = stringkyu.addString(firstName,lastName);
System.out.println(f_Name); // 김규하
//Stringkyu 인스턴스 생성 없이
//Stringkyu의 메서드(명령 모음)을 가져와서 로직을 돌릴수 있다!
}
}
같은 패키지에 있는 Main3.java에서 인스턴스의 생성없이 stringkyu.addString()를 사용이 가능한 모습이다.
public class Main {
public static void main(String[] args) {
String firstName = "김";
String lastName = "규하";
String f_Name = stringkyu.addString(firstName,lastName);
System.out.println(f_Name);
}
}
상위 패키지에 있는 Main.java에서도 인스턴스의 생성없이 stringkyu.addString()를 사용이 가능한 모습이다.
String 클래스속 static method
조금 더 쉽게 이해해보기 위해 자주 쓰이는 String의 static 메서드를 확인해보자.
Java api doc을 들어가보면 static method들을 확인해볼수 있다.
format은 String.format() 으로 사용사능한 반면, equals()는 아래 코드처럼 꼭 String 객체이 있어야만 사용할수 있을 것이다.
String str = "abc";
str.equals("abc);
왜 사용할까? - 장단점
장점
static method, 속도가 빨라지고 공유(반복적인 사용)에 효율적이다.
public class LottoNumberFactory {
private static final int MIN_LOTTO_NUMBER = 1;
private static final int MAX_LOTTO_NUMBER = 45;
private static final int LOTTO_LENGTH = 6;
private static List<LottoNumber> lottoNumbers = new ArrayList<>();
//45개의 로또 숫자 초기화
static {
for (int i = MIN_LOTTO_NUMBER; i <= MAX_LOTTO_NUMBER; i++) {
lottoNumbers.add(new LottoNumber(i));
}
}
// 로또 번호 추출
public static List<LottoNumber> createLottoNumbers() {
List<LottoNumber> lotto = new ArrayList<>();
Collections.shuffle(lottoNumbers);
for (int i = 0; i < LOTTO_LENGTH; i++) {
lotto.add(lottoNumbers.get(i));
}
return lotto;
}
}
createLottoNumbers() 메소드는 6개의 당첨번호를 추첨할 때, 그리고 자동으로 로또를 구입할 때 호출된다. static으로 선언되어 있으므로 해당 메소드를 사용할 때 마다 반복적으로 LottoNumberFactory객체를 생성해 줄 필요 없다.
조금 구체적으로 설명해보자. 런타임 시점에 new로 생성자를 Heap 영역으로 생성해야하는 인스턴스 속 메서드와 달리, static 메서드는 컴파일 시점에 클래스 영역에 저장된다. 그러므로 이후 생성되는 모든 인스턴스들이 클래스영역에 저장되어있는 static method를 공유하고 필요시 사용하여 편리함을 얻을 수 있다.
그렇다면 객체의 멤버변수에 접근할 필요가 없는 메소드는 static을 붙여서 사용하는게 무조건 효율적인 것일까?
단점
그러나 OOP개념을 기준으로 보았을때, static method는 객체들의 상호작용과는 어울리지 않는다
1. 객체 지향에서 멀어진다. Polymorphism 위반
Message passing
앞에서 말했다시피 정적 메소드는 객체의 생성주기와 관계가 없다. 이런 점에서 정적메소드는 객체 지향의 메시지 전달(message passing)[1]을 위반한다. 객체 지향에서는, 객체들은 서로 관계를 맺고 메시지를 통해 정보를 교환하고 결과를 반환한다. 정적 메소드를 실행하는 것은 객체에게 행위를 지시하는 것이 아니다. 다른 객체와 관계를 맺고 있지도 않다. 즉, 메시지 전달이 아니라 함수 호출에 불과하다고 할 수 있다. 이러한 방식은 객체지향이 아닌 절차 지향에 어울리는 방식이다.
- 메시지 전달(message passing)
[1]: 한 객체에서 다른 객체로 데이터를 전달하거나, 다른 객체의 메소드를 실행시키는 것.
Overriding과 Dynamic Binding
public abstract class WoowaTechCrew {
public void hello() {
System.out.println("안녕하세요.");
}
}
public class Orange extends WoowaTechCrew {
@Override
public void hello() {
System.out.println("하이요!");
}
}
public class Kafka extends WoowaTechCrew {
@Override
public void hello() {
System.out.println("안녕하쎄요~");
}
}
// main
public static void main(String[] args) {
WoowaTechCrew orange = new Orange();
WoowaTechCrew kafka = new Kafka();
orange.hello();
kafka.hello();
}
//-------출력결과
//하이요!
//안녕하쎄요~
위 코드는 다형성을 활용한 간단한 예시이다. 위 코드에서 다형성은 같은 타입(=클래스)으로 묶을수 있는 여러객체(인스턴스들)에게 동일한 명령을 내렸을때, 각 객체에 맞는 다른일을 수행하도록 하는 특성을 말한다.
static 메소드는 객체 지향의 특징인 다형성을 위반한다. Overriding(메소드 재정의)과 Dynamic Binding(동적 바인딩)[2]이 불가능하기 때문이다. 또한 인터페이스를 구현하는 데 사용할 수도 없다. 이는, static 메소드는 런타임 이전 컴파일 시에 정적 바인딩이 이루어지기 때문이다.
- 동적 바인딩
후기 바인딩, 동적 바인딩 또는 동적 연결은 런타임 시점에, 객체에 대해 호출되는 메소드 또는 인수와 함께 호출되는 함수를 이름별로 찾는 컴퓨터 프로그래밍 메커니즘.
쉽게 말해 런타임 시점에, 호출될 함수를 결정하여 메모리와 연결시켜주는 작업을 말한다.
2. 메모리 효율이 떨어질 수 있다.
정적 메소드는 객체를 생성하지 않고 사용한다. 반복적으로 객체를 생성하지 않아도 되니 메모리 효율에 좋을 것 같다는 생각이 들 수도 있다.
그러나, 런타임 중 동적으로 생성된 것들은 GC(Garbage Collector)[3]의 대상이 되는 반면, static 키워드가 붙은 메소드 등은 GC의 대상이 아니다. GC는 동적으로 할당된 메모리만을 대상으로 한다. 정적으로 할당된 static 영역은 GC의 대상이 아니다. static으로 할당된 영역이 크다면 GC의 효율이 떨어지기 마련이며, 프로그램이 끝날 때까지 그 영역은 메모리에서 내릴 수 없다. 즉, static 영역이 지나치게 많은 메모리를 차지하고 있다면 메모리가 부족한 현상이 발생할 수 있다.
정리
static은 장점도 있을뿐더러, 정적 팩터리 메서드를 활용하면 정적 메소드를 더욱 효율적으로 사용할 수도 있다. 결론적으로 위에서 말한 장단점이 있기에 어떤 상황에서는 무조건 쓰고, 쓰지않고 단정지을 수가 없다. 나 스스로 판단해보고, 속한 집단의 관례에 맞추어 사용하도록 하자.
출처
https://tecoble.techcourse.co.kr/post/2020-07-16-static-method/
'Java' 카테고리의 다른 글
[JVM]정적 바인딩과 동적 바인딩 (0) | 2022.11.15 |
---|---|
[OOP]캡슐화에 대해서 세부적으로 알아보자. (0) | 2022.11.08 |
[JVM]변수 선언과 할당시 관점으로 JVM 동작 이해하기 (0) | 2022.11.04 |
[Java기본]while문속의 switch문과 break; (0) | 2022.11.03 |
[배열]배열 복사 메서드 비교하기 (0) | 2022.11.03 |