Chap 10. 클래스 변수와 클래스 메소드
10-1 static 선언을 붙여서 선언하는 클래스 변수
public static void main(Stringp[] args)의 의미
(1) 선언된 클래스의 모든 인스턴스가 공유하는 클래스 변수

static 변수는 c의 전역변수와 마찬가지로 heap영역(인스턴스가 저장되는 공간)이 아닌 메소드 영역에 저장되며 프로그램이 시작될 때부터 프로그램이 종료될때 까지 존재한다.
인스턴스 멤버가 아닌 클래스 멤버이기 때문에 클래스에 의한 인스턴스들이 공유하는 변수(공유변수)이다. 따라서, 객체의 생성, 소멸과 상관없이 존재한다.
(2) 클래스 변수의 접근 방법
클래스 내부 접근
- static 변수가 선언된 클래스 내에서는 이름만으로 직접 접근 가능
클래스 외부 접근
- private 으로 선언되지 않으면 클래스 외부에서도 접근 가능.
- 접근 수준 지시자가 허용하는 범위에서 접근 가능.
- 클래스 또는 인스턴스의 이름을 통해 접근
class AccessWay {
static int num = 0; //직접 클래스 변수 초기화
AccessWay() {incrCnt();} //생성자 → 함수 호출해서 +1
void incrCnt() {
num++; //함수 내에서 +1
}
}
class ClassVarAccess {
public static void main(String[] args) {
AccessWay way = new AccessWay(); //생성자함수호출로 num+=1
way.num++; //외부에서 인스턴스의 이름을 통함 접근으로 num+=1
AccessWay.num++; //외부에서 클래스 이름을 통한 접근으로 num+=1
System.out.println("num = " + AccessWay.num); //num = 3
}
}
(3) 클래스 변수의 초기화 시점과 초기화 방법
클래스 변수는 생성자 기반 초기화 하면 안된다!
class InstCnt {
static int instNum = 100; //클래스 변수의 적절한 초기화 위치!
InstCnt() {
instNum++;
//instNum = 100; 으로 초기화할 경우, 인스턴스 생성시마다 값이 리셋된다!
System.out.println("인스턴스 생성: " + instNum);
}
}
class OnlyClassNoInstance {
public static void main(String[] args) {
InstCnt.instNum -= 15; //인스턴스 생성없이 instNum에 접근 (가능)
System.out.println(InstCnt.instNum);
}
}
(4) 클래스 변수의 활용의 예

10-2 static 선언을 붙여서 정의하는 클래스 메소드
(1) 클래스 메소드의 정의와 호출

단순 기능 제공이 목적인 메소드들, 인스턴스 변수와 관련지을 이유가 없는 메소드들은 static으로 선언하는 것이 옳다.
class SimpleCalculator {
static final double PI = 3.1415;
static double add(double n1, double n2) {
return n1 + n2;
}
static double min(double n1, double n2) {
return n1 - n2;
}
static double calCircleArea(double r) {
return PI * r * r;
}
static double calCirclePeri(double r) {
return PI * (r * 2);
}
}
위와 같이, 계산방법을 나타내는 메소드들은 인스턴스가 생성될때마다 만들어낼 필요가 없으므로, static으로 선언하는 것이 옳다.
(2) 클래스 메소드에서 인스턴스 변수에 접근이 가능할까?
class AAA {
int num = 0;
static void addNum(int n) {
num += n; //논리적으로 이 문장이 유효할 수 있는가?
}
}
인스턴스 멤버를 static 메소드 안에서 변경할 수 있을까?
→NO!
클래스 메소드는 프로그램이 시작될 때 만들어지는데, 인스턴스 변수는 인스턴스를 new로 생성하는 시점에 만들어진다.
따라서 해당 문장은 인스턴스가 존재하지 않는 시점에 이루어지는 연산이므로 유효하지 않다.
10-3 System.out.println 그리고 public static void main()
(1) System.out.println()에서 out과 println의 정체는?

(2) main메소드가 public 이고 static 인 이유는?

(3) main메소드를 어디에 위치시킬 것인가?

10-4 또 다른 용도의 static 선언
(1) static 초기화 블록

(2) static import 선언

Chap 11. 메소드 오버로딩과 String 클래스
11-1 메소드 오버로딩
(1) 메소드 오버로딩
호출된 메소드를 찾을 때 참조하게 되는 두가지 정보 : 메소드의 이름, 메소드의 매개변수 정보
→ 따라서 이 둘중 하나의 형태가 다른 메소드를 정의하는 것이 가능하다.


inst.simple(7, 'k')와 같은 상황에서, k가 double로 들어갈지 int로 들어갈지 모호한 상황이 생긴다.
(2) 생성자의 오버로딩

(3) 키워드 this를 이용한 다른 생성자의 호출

호출하여 사용하고 있는 인스턴스에 대하여 'this'라고 표현한다. (참조형 변수 this)
Person(int rnum) {
regiNum = rnum;
passNum = 0;
}
위와 같이 쓰는 것 대신에
Person(int rnum) {
this(rnum, 0);
}
으로 쓰면, this(rnum, 0) 을 통해 일반 생성자를 호출 가능하다!
(Person(int rnum) 함수를 새롭게 만드는것 대신에, this(rnum, 0)을 통해 Person(int rnum, int pnum) 함수를 호출하는 식으로 바꾸면 중복된 코드를 줄일 수 있으므로 효율적이다.)
(4) 키워드 this를 이용한 인스턴스 변수의 접근

11-2 String 클래스 (강의 8분14초~
(1)String 인스턴스 생성의 두가지 방법
- String str1 = new String("Simple String");
- String str2 = "The Best String";
둘 다 String 인스턴스의 생성으로 이어지고 그 결과 인스턴스의 참조 값이 반환된다.
(2) String 인스턴스와 println 메소드

(3) 문자열 생성 방법 두 가지의 차이점

왜 이런 결과가 나타날까?
str1과 str2 (str1→ "Simple String" ←str2)
constant pool에 "Simple String"을 넣어두고, 해당 레퍼런스 정보를 str1에 주었음. 이때, str2도 동일한 정보를 필요로 하기 때문에 동일한 레퍼런스 정보를 준다. (만약 str2가 "Simple String"에서 한글자라도 바뀌었다면 constant pool에 다른 레퍼런스 정보가 생성된다.)
str3과 str4 (str3→ "Simple String", str4→ "Simple String")
heap 영역에 별도의 인스턴스를 생성하여 각각의 공간을 할당한다.
(4) String 인스턴스는 Immutable 인스턴스

immutable instance : 정보가 바뀌지 않는 인스턴스
str1 = "A";
str1 = "B";
위와 같이 str1에 "A"를 할당한 뒤에, "B"로 바꾼다면 A가 있던 자리에 A의 정보를 지우고 B를 넣는것이 아니라
새로운 공간에 B를 만들고 str1이 B를 가리키도록 바꾼다.
결국, A는 사용하지 않는 것일 뿐, 정보가 바뀌는 것이 아니다.
이후에 str2 = "A"; 로 선언을 해준다면 이전에 선언되었던 A를 그대로 사용한다.
11-3 String 클래스의 메소드
(1) 문자열 연결시키기

str3 = str1.concat(str2) : str1 뒤에 str2를 붙인 새로운 문자열을 str3에 저장하라
immutable instance이므로, str1바로 뒤의 공간에 str2를 할당하여 이어 붙이는것이 아니라,
새로운 공간에 str1+str2 문자열을 할당하고 str3이 이를 가리킬 수 있도록 한다.
(2) 문자열의 일부 추출

(3) 문자열의 내용 비교

cmp = str1.compareTo(str2)는 str1 - str2를 연산하고, 그 결과를 cmp에 저장한다.
(4) 기본 자료형의 값을 문자열로 바꾸기

(5) 문자열 대상 '+연산'과 '+=연산'

17은 String type이 아닌 int type이기 때문에, 형변환이 필요하다! (concat은 문자열&문자열일때만 사용 가능)
(6) 문자열 결합의 최적화를 하지 않을 경우


문자열 최적화를 진행할 경우 (StringBuilder 사용)

StringBuilder라는 임시공간에 append를 통해 여러 type들을 넣어주고 맨 마지막에 toString()을 통해 문자열로 바꾸어준다. => 사용하는 공간이 2개(StringBuilder, birth)뿐이므로 메모리 부담감이 작아져 효율적이다!

(7) StringBuffer
StringBuffer와 StringBuilder는 기능적으로는 완전히 동일하다.
<공통점>
- 생성자를 포함한 메소드의 수
- 메소드의 기능
- 메소드의 이름과 매개변수의 선언
<차이점>
- StringBuffer는 쓰레드에 안전하다. 따라서, 쓰레드 안전성이 불필요한 상황에서 StringBuffer를 사용하면 성능의 저하만 유발하게 된다.
- 그래서 StringBuilder가 등장하게 되었다.
과제4
toString() 메소드 :
객체의 값을 문자열 형태로 변환하여 출력해준다. 인스턴스의 값을 출력할 때 그냥 인스턴스를 넣거나 기본 toString() 메소드를 사용하면 해시값을 포함한 이상한 값이 출력된다.

만들어 둔 인스턴스의 정보를 편하게 출력하기 위해 toString()메소드를 오버라이딩하여 해당 메소드를 사용할 수 있다.
public String toString() {
return (출력하고 싶은 내용);
}
과제5
static 메소드에 static변수 (O), 인스턴스 변수 (X) - static이 생성되는 시점에 인스턴스는 생성되지 않으므로, 오류 발생
인스턴스 메소드에 static변수 (O), 인스턴스 변수 (O)
'Java' 카테고리의 다른 글
| [Java] 6주차 복습 - chap 12, 13 (2) | 2022.01.21 |
|---|---|
| [Java] 4주차 복습 - Chap 07, 08, 09 (0) | 2022.01.06 |
| [Java] 3주차 복습 - Chap 05, 06 (3) | 2022.01.04 |
| [Java] 2주차 복습 - Chap03, 04 (3) | 2022.01.03 |
| [Java] 1주차 복습 - Chap01, 02 (2) | 2021.12.29 |