안녕하세요, 여행벌입니다.

저번 포스팅에 이어 자주 사용되는 String 클래스 메소드를 정리해보겠습니다.


public int indexOf(int ch)
// 매개변수로 들어온 문자가 처음 등장하는 인덱스를 반환하는 메소드

public int indexOf(int ch, int fromIndex)
// fromIndex 부터 매개변수로 들어온 문자가 처음 등장하는 인덱스를 반환하는 메소드

public int indexOf(String str)
// str이 부분 문자열로 처음 등장하는 인덱스를 반환하는 메소드

public int indexOf(String str, int fromIndex)
// fromIndex 부터 str이 부분 문자열로 처음 등장하는 인덱스를 반환하는 메소드

public int lastIndexOf(int ch)
// 매개변수로 들어온 문자가 마지막으로 등장하는 인덱스를 반환하는 메소드

public int lastIndexOf(int ch, int fromIndex)
// fromIndex 부터 매개변수로 들어온 문자가 처음 등장하는 인덱스를 반환하는 메소드

public int lastIndexOf(String str)
// str이 부분 문자열로 처음 등장하는 인덱스를 반환하는 메소드

public int lastIndexOf(String str, int fromIndex)
// fromIndex 부터 str이 부분 문자열로 처음 등장하는 인덱스를 반환하는 메소드

public String substring(int beginIndex)
// beginIndex 부터 끝까지 부분 문자열을 반환하는 메소드

public String substring(int beginIndex, int endIndex)
// beginIndex 부터 endIndex 전까지 부분 문자열을 반환하는 메소드

public int indexOf(int ch)

 indexOf는 입력으로 들어온 문자가 처음 등장하는 인덱스를 반환하는 메소드입니다. 하지만 매개변수의 자료형을 보시면 char가 아니라 int 인 것을 확인할 수 있습니다. 이는 아스키코드로 변환해서 입력받기 때문입니다. 또, 입력으로 들어온 문자가 등장하지 않으면 -1 을 반환합니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "traev5el";
		System.out.println(str1.indexOf('x'));
		System.out.println(str1.indexOf('e'));
		System.out.println(str1.indexOf('5'));
		System.out.println(str1.indexOf(53)); // 아스키코드 53번은 '5'
	}
}
-1
3
5
5

 "traev5el" 에는 'x'가 없으므로 -1을 반환하고, 가장 처음 등장하는 'e' 는 4번 째 문자이므로 인덱스 3을 반환하고 '5' 는 인덱스 5, 또 53은 아스키코드 '5' 를 의미하므로 마찬가지로 인덱스 5를 반환하는 것을 확인할 수 있습니다.

public int indexOf(int ch, int fromIndex)

 indexOf 메소드는 메소드 오버로딩이 되어있습니다. 두 번째 인자로 탐색을 시작할 위치를 지정할 수 있습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "traev5el";
		System.out.println(str1.indexOf('x', 0));
		System.out.println(str1.indexOf('e', 4));
		System.out.println(str1.indexOf('t', 0));
		System.out.println(str1.indexOf(53)); // 아스키코드 53번은 '5'
	}
}
-1
6
0
5

 0번 인덱스부터 (처음부터) 탐색해도 'x' 는 존재하지 않으므로 -1을 반환하고, 인덱스 4번부터 'e' 를 찾으면 첫 번째 등장하는 'e'가 아닌 그 다음 'e' 를 탐색하는 것을 확인할 수 있습니다.

public int indexOf(String str)

 indexOf 메소드에는 매개변수로 String 인스턴스를 전달할 수도 있습니다. 그러면, 전달받은 매개변수가 부분 문자열로 처음 등장하는 인덱스를 반환해줍니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "abcdabcdabcd";
		System.out.println(str1.indexOf("abcd"));
		System.out.println(str1.indexOf("bcdb"));
		System.out.println(str1.indexOf("dabc"));
	}
}
0
-1
3

 문자열 "abcdabcdabcd" 에서 먼저 "abcd" 를 찾아보면 0번 인덱스부터 3번 인덱스까지 "abcd"가 존재하는 것을 확인할 수 있습니다. 따라서, 0 을 반환해줍니다.

 "bcdb" 는 존재하지 않으므로 -1을 반환해주고, "dabc" 는 3번 인덱스부터 6번 인덱스까지 "dabc"가 처음 등장하므로 3을 반환해줍니다.

public int indexOf(String str, int fromIndex)

마찬가지로 fromIndex 부터 str이 부분 문자열로 처음 등장하는 부분의 인덱스를 반환해줍니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "abcdabcdabcd";
		System.out.println(str1.indexOf("abcd", 9));
	}
}

 "abcdabcdabcd" 에서 9번 인덱스부터 탐색을 진행하면 "bcd" 에서 "abcd"를 찾는 것이므로 -1을 반환합니다.

public int lastIndexOf(int ch)
public int lastIndexOf(int ch, int fromIndex)
public int lastIndexOf(String str)
public int lastIndexOf(String str, int fromIndex)

 indexOf 메소드와 사용방법은 동일하나 lastIndexOf 는 메소드 이름 그대로 마지막 인덱스를 반환해줍니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "abcdabcdabcd";
		System.out.println(str1.lastIndexOf('c'));
		System.out.println(str1.lastIndexOf("abcd"));
	}
}
10
8

public String substring(int beginIndex)
public String substring(int beginIndex, int endIndex)

 substring 메소드를 이용하면 문자열에서 일부분만 부분 문자열로 새롭게 생성할 수 있습니다. beginIndex는 어디서부터 자르기 시작할지를 나타내는 값이고, endIndex는 endIndex 전까지만 문자열을 자르겠다는 뜻입니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "abcdabcdabcd";
		System.out.println(str1.substring(5));
		System.out.println(str1.substring(4, 8));
	}
}
bcdabcd
abcd

이상으로 자주 쓰이는 String 클래스 메소드 정리를 마무리해보겠습니다.

 

안녕하세요, 여행벌입니다.

오늘은 자바에서 굉장히 많이 사용하는 String 클래스의 특징과 메소드에 대해서 정리해보겠습니다.


String 클래스

 String 클래스는 자바에서 지원해주는 클래스입니다. 클래스이므로 인스턴스를 생성해서 사용하면 됩니다.

String name = new String("travelbeeee");

 name 이라는 이름의 String 인스턴스를 생성했고, 생성자에 "travelbeeee"를 매개변수로 입력했습니다. 일반적인 클래스 인스턴스 생성과 다를게 없습니다. 하지만, 이전의 포스팅을 보면 제가 아래와 같이 String 클래스의 인스턴스를 생성한 것을 볼 수 있습니다.

String name = "travelbeeee";

 new 키워드 없이 String 클래스의 인스턴스를 생성해서 사용해왔습니다. 즉, String 클래스는 "" (큰따옴표) 만으로도 인스턴스 생성이 가능합니다.

public static void main(String[] args){
	int len = "travelbeeee".length();
    System.out.println(len);
}

 위의 String 클래스의 인스턴스를 만들고, length 메소드를 실행시켜보았습니다. 실행해보면 "11" 이 예상대로 출력됩니다! 즉, "" (큰따옴표) 만으로도 인스턴스 생성이 가능한 것을 확인할 수 있습니다.

 

 String 클래스에는 큰 특징이 하나 있습니다. 바로,

 

"String 인스턴스는 Immutable 인스턴스입니다."

 

 Immutable은 "변경할 수 없는" 이라는 뜻입니다. String 인스턴스는 처음에 문자열을 선언하면 그 내용을 바꿀 수 없습니다!

String name = "travelbeeee";

 name 이라는 이름의 String 클래스의 인스턴스는 내부에 문자열 "travelbeeee"를 지니게 되고, 이 내용은 인스턴스가 소멸될 때까지 바꿀 수 없습니다.

String name = "travelbeeee";
String name2 = "travelbeeee";

 그럼 위와 같은 경우에 다른 일반적인 클래스의 인스턴스와 어떤 차이가 발생할까요?

 String 인스턴스는 Immutable 인스턴스이므로, 문자열 내용이 같은 경우에는 하나의 인스턴스를 서로 공유하게 됩니다. 

 즉, 위의 코드는 아래의 코드와 동일합니다.

String name = "travelbeeee";
String name2 = name;

 그럼 문자열 내용이 같은 인스턴스를 2개 생성하려면 어떻게 해야될까요? new 키워드를 이용해서 그냥 인스턴스를 2개 생성하면 됩니다.

String name = "travelbeeee";
String name2 = new String("travelbeeee");

 다음 예제를 통해 확인해보겠습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		String str2 = "travelbeeee";
		String str3 = new String("travelbeeee");
		
		if(str1 == str2) {
			System.out.println("str1 과 str2는 동일한 인스턴스를 참조 중");
		}
		else {
			System.out.println("str1과 str2는 다른 인스턴스를 참조 중 ");
		}
		
		if(str1 == str3) {
			System.out.println("str1과 str3는 동일한 인스턴스를 참조 중");
		}
		else {
			System.out.println("str1과 str3는 다른 인스턴스를 참조 중");
		}
	}
}

 결과는 다음과 같습니다.

str1 과 str2는 동일한 인스턴스를 참조 중
str1과 str3는 다른 인스턴스를 참조 중

 우리는 str1과 str3가 같은 내용의 문자열을 지니고 있지만, 다른 인스턴스를 참조하고 있는 것을 확인할 수 있습니다. 반면에 str1과 str2는 같은 인스턴스를 참조하고 있습니다.

 

 String 인스턴스는 그 안에 저장된 데이터를 수정할 수 없는, 참조만 가능한 인스턴스이기 때문에 Immutable 인스턴스여도 문제가 발생하지 않습니다.

String 클래스 switch 문

자바 7부터 String 인스턴스를 이용해서 switch 문의 구성이 가능해졌습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		switch(str1) {
		case "travel":
			System.out.println("이름은 : travel 입니다.");
			break;
		case "beeee":
			System.out.println("이름은 : beeee 입니다.");
			break;
		case "travelbeeee":
			System.out.println("이름은 : travelbeeee 입니다.");
		}
	}
}

 결과는 다음과 같습니다.

이름은 : travelbeeee 입니다.

 이처럼 자바 7에서부터 switch 문에서 String 인스턴스 사용을 지원해주기 때문에 조금 더 편하게 코드를 구현할 수 있습니다.

String 클래스 메소드

 이제 String 클래스에 있는 메소드 중 자주 사용되는 메소드를 정리해보도록 하겠습니다.

public int length() // 문자열의 길이를 반환해주는 메소드

public boolean isEmpty() // 문자열이 비어있는지 확인해주는 메소드

public boolean isEquals(Object obj) // 두 인스턴스가 지니고 있는 문자열이 같은지 확인해주는 메소드

public int compareTo(String str)
// 두 인스턴스가 지니고 있는 문자열의 사전 순서를 비교해주는 메소드

public int compareToIgnoreCase(String str)
// 두 인스턴스가 지니고 있는 문자열을 대소문자 상관 없이 사전 순서로 비교해주는 메소드

public static String valueOf(Object obj)
// 기본 자료형의 값을 문자열로 바꿔주는 메소드

public String concat(String str)
// 두 인스턴스가 지니고 있는 문자열을 하나로 이어주는 메소드

public int length()

length 메소드는 String 인스턴스의 문자열의 길이를 반환해줍니다. 반환형은 int 형이고, String 클래스에서 가장 많이 사용되는 메소드가 아닐까 싶습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		System.out.println(str1.length());
	}
}
11

public boolean isEmpty()

 isEmpty 메소드는 String 인스턴스에 저장된 문자열이 없다면 true를 반환하고, 아니면 false를 반환합니다. 즉 String 인스턴스의 length 메소드를 호출한 값이 "0" 이라면 true를 반환하고, 아니면 false를 반환합니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		System.out.println(str1.isEmpty());
	}
}
false

public boolean equals(Object obj)

 equals 메소드는 두 인스턴스가 지니는 문자열이 같으면 true 를 반환하고, 다르면 false를 반환합니다. 매개변수로 Object형을 입력 받지만, String 클래스가 Object 클래스를 상속하므로 String 인스턴스의 참조 값을 전달할 수 있습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		System.out.println(str1.equals("travelbeeee"));
		System.out.println(str1.equals("travelbeee"));
	}
}
true
false

public int compareTo(String str)

 compareTo 메소드는 equals 메소드에서 조금 더 자세히 비교를 해주는 메소드입니다. 두 문자열이 사전 순서로 누가 앞서는지를 결과로 알려줍니다. 두 문자열의 내용이 일치하면 "0" 을 반환하고, 호출된 인스턴스의 문자열이 인자로 전달된 문자열보다 앞서면 음수를 반환하고 아니면 양수를 반환합니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		System.out.println(str1.compareTo("travelbeeee"));
		System.out.println(str1.compareTo("abcdefg"));
		System.out.println(str1.compareTo("xzcxvzxcvkas"));
	}
}
0
19
-4

public int compareToIgnoreCase(String str)

 compareToIgnoreCase 는 문자열 비교에 있어서 대소문자 구분을 하지 않고 사전 순서로 누가 앞서는지를 알려주는 메소드입니다. compareTo 메소드와 결과는 같으나 이 결과값이 대소문자를 구분하지 않은 결과값입니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travelbeeee";
		System.out.println(str1.compareTo("TRAVELBEEEE"));
		System.out.println(str1.compareToIgnoreCase("TRAVELBEEEE"));
	}
}
32
0

public static String valueOf(Object obj)

 valueOf 메소드는 기본 자료형의 값을 문자열로 바꿔줍니다. 클래스 메소드이므로 인스턴스 생성 없이 사용할 수 있습니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = String.valueOf(123); // 정수 123을 문자열로 변환
		System.out.println(str1.equals("123"));
	}
}

 int형 123을 문자열로 변환해준 후 문자열 "123" 과 비교해봤습니다.

true

public String concat(String str)

 concat 메소드는 두 인스턴스의 문자열을 이어줍니다. 이어준다는 뜻은 말 그대로 "travel" 과 "beeee"를 concat하면 "travelbeeee"로 만들어줍니다.

 concat 메소드는 "+" 연산을 통해서도 사용할 수 있습니다. "travel" + "beeee" 를 진행하면 자동으로 "travel" .concat("beeee") 를 호출합니다.

package Hello;

public class test{
	public static void main(String args[]) {
		String str1 = "travel";
		System.out.println(str1 + "beeee");
		System.out.println(str1.concat("beeee"));
	}
}
travelbeeee
travelbeeee

 그럼 다음과 같은 경우는 자바에서 어떻게 처리해줄까요?

"123" + 7;

 String 인스턴스와 int 형을 + 연산을 진행해보았습니다. + 연산은 자동으로 concat 으로 바뀌므로 위의 코드는 아래와 같습니다.

"123".concat(7);

 하지만 concat 매소드는 매개변수로 String 인스턴스를 입력받기 때문에, 에러가 발생합니다. 즉 우리가 원하는 결과를 얻고 싶으면 다음과 같이 진행해야됩니다.

"123" + String.valueOf(7);

메소드가 워낙 많아서 다음 포스팅에서 이어서 정리해보도록 하겠습니다.

 

안녕하세요, 여행벌입니다.

오늘은 자바 메소드 오버로딩에 대해서 알아보겠습니다.


메소드 오버로딩

  한 클래스 내에 동일한 이름의 메소드를 둘 이상 정의하는 것이 가능할까요?? 자바는 "메소드 오버로딩"을 지원해주기 때문에, 매개변수만 다르다면 동일한 이름의 메소드를 여러개 정의하는 것이 가능합니다!

 메소드를 호출하면 다음 두 가지 정보를 참조하여 메소드를 찾게 됩니다.

 

●  메소드의 이름

●  메소드의 매개 변수 정보

 

 메소드의 이름은 동일하지마, 매개 변수 정보가 다르다면 다른 메소드로 인식하는 것이 "메소드 오버로딩" 입니다.

 정리하면, 메소드의 이름이 같아도 매개변수 선언이 다르면 메소드 호출문의 전달인자를 통해서 호출된 메소드를 구분할 수 있습니다. 따라서 매개변수의 선언이 다르다면 동일한 이름의 메소드 정의를 허용하는데, 이를 "메소드 오버로딩" 이라 합니다.

 

 예시를 통해서 메소드 오버로딩에 대해서 다뤄보겠습니다.

package Hello;

class Calculate{
	public int add(int a, int b) {
		return a + b;
	}
	public double add(double a, double b) {
		return a+ b;
	}
}
public class test{
	public static void main(String args[]) {
		Calculate cal = new Calculate();
		System.out.println(cal.add(2,  5));
		System.out.println(cal.add(2.5, 3.4));
	}
}

 Calculate 클래스 안에 같은 이름의 메소드 add를 2개 정의했습니다. 하지만, 매개변수가 위의 add는 int 형이고 아래 add는 double형으로 다르므로 "메소드 오버로딩"이 적용되어 문제 없이 클래스가 정의되는 것을 확인할 수 있습니다.

 그러면 다음과 같이 매개변수의 수가 다르면 어떻게 될까요?

package Hello;

class Calculate{
	public int add(int a, int b) {
		return a + b;
	}
	public int add(int a, int b, int c) {
		return a+ b + c;
	}
}
public class test{
	public static void main(String args[]) {
		Calculate cal = new Calculate();
		System.out.println(cal.add(2,  5));
		System.out.println(cal.add(2, 3, 4));
	}
}

 매개변수의 수가 달라도 매개변수의 정보가 다르므로 마찬가지로 "메소드 오버로딩"이 문제 없이 적용됩니다.

 

즉, 매개변수의 수 또는 매개변수의 형(type)이 다르면 메소드 오버로딩이 성립합니다. 

 

 그럼 매개변수가 아닌 반환형이 다른 경우에도 메소드 오버로딩이 성립할까요??

package Hello;

class Calculate{
	public int add(int a, int b) {
		return a + b;
	}
	public double add(int a, int b) {
		return double(a+ b);
	}
}
public class test{
	public static void main(String args[]) {
		Calculate cal = new Calculate();
		System.out.println(cal.add(2,  5));
		System.out.println(cal.add(2, 3));
	}
}

 마찬가지로 Calculate 클래스 내에 같은 이름의 메소드 add를 2개 정의했는데, 매개변수는 같지만 반환형을 다르게 해보았습니다.

 이때는 매개변수 정보가 같으므로 메소드를 구분할 수 없습니다. 따라서, "메소드 오버로딩"이 성립하지 않고, 먼저 정의된 int 를 반환하는 add 함수만 정의가 진행됩니다.

 

반환형이 다른 경우에는 메소드 오버로딩이 성립하지 않습니다.

 

 그러면 저번 포스팅에서 다뤘던 생성자 메소드는 오버로딩이 될까요??

 생성자도 일종의 메소드이므로 오버로딩이 적용됩니다! 따라서, 다음과 같이 여러 종류의 생성자를 만들 수 있습니다.

class Student{
	private int IDNumber;
	private String StudentName;
	
	public Student(int IDN, String Name) {
		IDNumber = IDN;
		StudentName = Name;
	}
	public Student(int IDN) {
		IDNumber = IDN;
		StudentName = "이름이없습니다.";
	}
	public Student(String Name) {
		IDNumber = 0;
		StudentName = Name;
	}
}

 인스턴스를 생성할 때, 어떤 값을 매개변수로 넘기냐에 따라 호출되는 생성자가 달라집니다.

 

 이처럼 자바에서는 메소드의 이름과 매개변수 정보를 기반으로 메소드를 호출하므로, 이름이 같더라도 매개변수 정보가 다르다면 동일한 이름의 메소드를 여러 개 정의할 수 있습니다.


 

안녕하세요, 여행벌입니다.

오늘은 static 선언을 이용한 클래스 변수, 클래스 메소드의 정의 방법 및 특징에 대해서 알아보겠습니다.


클래스 변수 (static 변수)

 지난 포스팅부터 계속 등장하던 '인스턴스 변수'는 인스턴스가 생성되었을 때, 생성된 인스턴스 안에 존재하는 변수입니다. 그러나 '클래스 변수'는 인스턴스의 생성과 상관없이 존재하는 변수입니다. 

 

 "클래스 변수는 클래스를 정의할 때 생성되는 변수입니다.

라서, 클래스 변수는 선언된 클래스의 모든 인스턴스가 공유하게 됩니다."

 

 같은 의미로 클래스 변수는 인스턴스 내에 존재하는 변수가 아니라 '어떠한 인스턴스에도 속하지 않는 상태로 클래스 정의시 메모리 공간에 딱 하나만 존재하게 되는 변수' 라고도 표현할 수 있습니다.

 클래스 변수도 저번 포스팅에서 다루었던 '접근 수준 지시자'의 규칙을 그대로 적용받기 때문에 public으로 선언되면 어디서든 접근이 가능하고 아래와 같이 default 로 선언되면 같은 패키지 내에서만 접근이 가능합니다. 그럼, 클래스 변수의 특징을 예제를 통해서 익혀보도록 하겠습니다.

package Hello;

class Example{
	static int n = 0;
	
	public void printN() {
		System.out.println("현재 n : " + n);
	}
}

public class test{
	public static void main(String args[]) {
		Example ex1 = new Example();
		ex1.n++;
		ex1.printN();
		Example.n++;
		ex1.printN();
	}
}


  클래스 변수 n과 n의 값을 출력해주는 메소드를 가지고 있는 클래스 Example을 만들고, 인스턴스를 생성해 n의 값을 1 증가시켜주고 출력을 진행했습니다. 그 후, Example.n++; 명령어를 수행하고 다시 한 번 메소드를 통해 n의 값을 출력했습니다. 결과는 다음과 같습니다.

 결과는 다음과 같습니다.

 

 "Example.n 과 같이 클래스 변수는 클래스의 이름을 통해서도 접근이 가능한 것을 알 수 있습니다."

 

package Hello;

class Example{
	static int n = 0;
	
	public void printN() {
		System.out.println("현재 n : " + n);
	}
}

public class test{
	public static void main(String args[]) {
		Example ex1 = new Example();
		ex1.n++;
		ex1.printN();
		Example.n++;
		ex1.printN();
		Example ex2 = new Example();
		ex2.printN();
	}
}


 이번에는 인스턴스를 하나 더 생성하고 클래스 변수의 특징을 알아보겠습니다. ex2 라는 인스턴스를 하나 더 만든 후, n의 값을 출력해보았습니다.

 다른 인스턴스인 ex2 에서 n 의 값을 출력해도 ex1의 n의 값과 동일한 것을 확인할 수 있습니다.

 

"클래스 변수는 모든 인스턴스가 공유하는 변수인 것을 확인할 수 있습니다."

 

 따라서 자연스럽게 우리는 클래스 변수가 인스턴스의 생성과 상관이 없는 것을 알 수 있습니다. 그럼, 클래스 변수는 언제 메모리에 할당되고 초기화가 될까요??

 다음 예제를 확인해보겠습니다.

package Hello;

class Example{
	static int n = 0;
	
	public void printN() {
		System.out.println("현재 n : " + n);
	}
}

public class test{
	public static void main(String args[]) {
		Example.n++;
		Example ex1 = new Example();
		ex1.printN();
	}
}

 이번에는 인스턴스 생성하기 전에 클래스 명을 이용해 클래스 변수에 접근했습니다. 결과는 다음과 같습니다.

 인스턴스를 생성하기도 전에 클래스 변수에 접근해 1을 증가시키는 코드가 제대로 작동한 것을 확인할 수 있습니다. 즉, 클래스 변수는 인스턴스 생성 이전에 메모리 공간에 존재하는 것을 확인할 수 있습니다.

 

 "클래스 변수는 클래스가 정의되는 순간 메모리 공간에 할당되고 초기화됩니다."

 

 그럼 클래스 변수는 언제 사용하면 좋을까요?? 모든 인스턴스가 참조해야하는 값이지만, 인스턴스가 각각 지녀야할 필요는 없을 때 클래스 변수를 이용하면 됩니다. 예를 들어, 환율과 관련된 클래스를 정의할 때, 모든 인스턴스가 각각 현재 환율을 저장하고 있을 필요는 없습니다. 따라서, 환율을 static으로 선언해 클래스 변수로 만들어 놓는다면 메모리를 아낄 수 있습니다.

클래스 메소드 (static 메소드)

 클래스 메소드는 클래스 변수와 마찬가지로 메소드에 static 선언이 들어간 것을 의미합니다. 또, 동일하게 인스턴스 생성 이전부터 접근이 가능하고 어느 인스턴스에 속하지 않습니다.

package Hello;

class Example{
	static int n = 0;
	
	public void printN() {
		System.out.println("현재 n : " + n);
	}
	public static void staticPrintN() {
		System.out.println("현재 n : " + n);
	}
}

public class test{
	public static void main(String args[]) {
		Example.n++;
		Example.staticPrintN();
	}
}


 클래스 변수와 마찬가지로 인스턴스 생성과 관계없이 클래스 명으로 접근할 수 있고, 결과는 아래와 같습니다.

 그럼 클래스 메소드는 어떤 경우에 사용하면 좋을까요?? 다음과 같은 경우에는 클래스 메소드로 정의하는 것이 더 좋습니다.

 

외부에 기능을 제공하기 위한 메소드

인스턴스 변수의 값을 참조하거나 수정하지 않는 메소드 / 인스턴스 메소드를 호출하지 않는 메소드

 

 하나씩 왜 클래스 메소드로 사용하면 좋은지 생각해보겠습니다.

 먼저, 오로지 기능을 제공하기 위한 메소드는 인스턴스 생성이 따로 필요없이 우리는 메소드(기능)만 이용하면 됩니다. 따라서, 클래스 메소드로 선언하는 것이 더 현명합니다. 우리가 자주 사용하면 Math 클래스는 기능 제공을 위한 목적으로 만들어진 클래스입니다.  따라서, 메소드와 변수들이 모두 Static으로 선언되어있습니다.

package Hello;

import java.lang.Math.*;

public class test{
	public static void main(String args[]) {
		System.out.println(Math.PI); // Math클래스의 PI static 변수
		Syttem.out.println(Math.abs(-1)); // Math클래스의 abs static 메소드
	}
}

 그 다음으로, 클래스 메소드는 인스턴스 변수의 값을 참조하거나 수정하지 않아야 되고 인스턴스 메소드를 호출하면 안된다고 했습니다. 그 이유는 간단합니다. 클래스 메소드는 인스턴스 생성과 상관 없이 참조할 수 있습니다. 하지만, 인스턴스 변수는 인스턴스 생성 시 선언되는 변수이므로 클래스 메소드에서 인스턴스 변수를 참조하거나 수정하면 에러가 날 수 밖에 없습니다. 마찬가지로 인스턴스 메소드도 인스턴스 생성 전까지 선언되지 않으므로 참조할 수 없습니다.

Static 초기화 블록

 위에서 클래스 변수는 모든 인스턴스가 공유해야하는 상황에서 유용하게 사용할 수 있다고 했습니다. 그럼, 클래스 변수는 어떻게 초기화를 해야될까요?? 생성자를 이용해서 초기화를 하면 인스턴스 생성 시 초기화가 진행되므로, 적절하지 않습니다. 따라서 자바에서는 "Static 초기화 블록" 을 지원해줍니다.

class example{
	static String date;
	static {
		LocalDate today = LocalDate.now();
		date = today.toString();
	}
}

  다음과 같이 static 초기화 블록을 사용하면 클래스 변수를 선언과 동시에 초기화 할 수 있고, 클래스 로딩 시 단 한 번 실행됩니다.


  

+ Recent posts