저번 static 강의를 졸면서 봤더니 이번 강의가 무슨 말인지 이해가 안간다.
이 그림을 이해하는 것을 포스팅의 최종목표로 하고 다시 이전 static 강의부터 다시 들어야겠다.
다시 한 번
static - class method
no static - instance method
일단 이걸 마음속에 다시 한 번 새기고 시작하자
그리고 바꾸기 전 코드를 먼저 써보겠다.
class Print{
public static void a(String delimiter) {
System.out.println(delimiter);
System.out.println("a");
System.out.println("a");
}
public static void b(String delimiter) {
System.out.println(delimiter);
System.out.println("b");
System.out.println("b");
}
}
public class staticMethod {
public static void main(String[] args) {
Print.a("-");
Print.b("*");
}
}
Print 라는 class로 a(), b() method들을 묶어줬다.
근데 이제 저 구분자를 바꿔줘야 할 수도 있고, a와 b를 프린트 하는게 한 두번이 아닌 여러번이 될 수 있으니까
좀더 효율적으로 코드를 쓸 수 있어야 한다.
그래서 바꿔준 코드
class Print{
public String delimiter;
public void a() {
System.out.println(this.delimiter);
System.out.println("a");
System.out.println("a");
}
public void b() {
System.out.println(this.delimiter);
System.out.println("b");
System.out.println("b");
}
}
public class staticMethod {
public static void main(String[] args) {
// Print.a("-");
// Print.b("-");
Print t1 = new Print();
t1.delimiter = "-";
t1.a();
t1.b();
// Print.a("*");
// Print.b("*");
Print t2 = new Print();
t2.delimiter = "*";
t2.a();
t2.b();
}
}
어차피 Print 하는 class의 기능은 똑같으니, 구분자만 바꿔주면 원하는대로 class의 변수를 바꿔가면서 사용할 수 있다.
그래서 Print t1 = new Print();
라는 코드를 써서 t1이라는 인스턴스를 만들어 준것이다.
근데 우리가 호출하려는 method는 그럼 class의 method가 아니라 instance의 method이다.
그렇기 때문에 원래 public 뒤에 붙어있던 static을 제거해줘야 한다. 그래야 instance의 method로 사용할 수 있다.
그래서 다시 class로 method를 불러내려고 하면 에러가 난다.
static을 지웠으니 이제 걔는 instance 소속의 method가 되어버렸으니까
자 이제 본론들어 와서 여러 가지 실험을 해보자
class Poo {
public static String classVar = "I class var";
public String instanceVar = "I instance var";
public static void classMethod() {
System.out.println(classVar); // OK
// System.out.println(instanceVar); // Error
}
public void instanceMethod() {
System.out.println(classVar); // OK
System.out.println(instanceVar); // OK
}
}
public class StaticApp {
public static void main(String[] args) {
System.out.println(Poo.classVar); //OK
// System.out.println(Poo.instanceVar); //Error
}
}
Poo (ㅋㅋ)라는 class 안에
static이 붙어 있는 class용 변수와
static이 붙어 있지 않은 instance용 변수를 만들었다.
이것들이 main method에서, class method에서 실행이 되는지 확인을 해보는거다.
확인해보면 결국 class 단위 안에서는 class 변수만 가지고 올 수 있다.
static이 붙지 않은 instance 변수는 불러올 수 없다.
근데 instance method 안에서는 class 변수, instance 변수 둘다 접근 가능하다.
public class StaticApp {
public static void main(String[] args) {
System.out.println(Poo.classVar); //OK
// System.out.println(Poo.instanceVar); //Error
Poo.classMethod();
// Poo.instanceMethod(); // Error
}
}
위에 적힌 코드가 같다고 치고 보자.
Poo.classMethod는 실행된다. 왜냐 class 를 통해 class method에 접근하는거니까
근데 class를 통해 instancemethod에 접근하는것은 불가능하다. 그렇게 약속되어 있단다.
그럼 이제 또 instance를 만들어서 확인해볼 차례이다.
class Poo {
public static String classVar = "I class var";
public String instanceVar = "I instance var";
public static void classMethod() {
System.out.println(classVar); // OK
// System.out.println(instanceVar); // Error
}
public void instanceMethod() {
System.out.println(classVar); // OK
System.out.println(instanceVar); // OK
}
}
public class StaticApp {
public static void main(String[] args) {
System.out.println(Poo.classVar); //OK
// System.out.println(Poo.instanceVar); //Error
Poo.classMethod();
// Poo.instanceMethod(); // Error
Poo f1 = new Poo();
System.out.println(f1.classVar);
System.out.println(f1.instanceVar);
}
}
이렇게 f1이라는 instance를 만들어 줬다. 그러면 아래와 같은 그림의 상황이 만들어 지는데...
1. instance는 class에 있는 변수, method를 복제해 온다.
2. static이 붙은 class의 변수, method들은 링크처럼 연결되어 있다. 그렇기 때문에 instance에서 그 값이 바뀌거나, class에서 그 값이 바뀌면 같이 바뀌게 되는거다.
3. static이 붙어있지 않은 instance의 변수, method들은 연결되어 있지 않다. 그냥 카피만 해온것이다. 따라서 instance에서 그 값을 바꾼다고 class에서 바뀌지 않으며, class에서 바꾼다고 instance안에서 바뀌지 않는다. (서로 독립된 존재이다.)
4. f2라는 instance를 하나 더 만들면 같은 상황이 반복되는것.
5. class의 변수를 바꾸면 모든 instance의 변수들이 바뀐다.
6. instance에서 class의 변수를 바꾸면, 그것을 사용하는 모든 instance들의 변수 역시 링크되어 바뀐다.
드디어 저 그림을 이해하게 됐다!! 예이
자 그럼 진짜 마지막으로 실험...
class Poo {
public static String classVar = "I class var";
public String instanceVar = "I instance var";
public static void classMethod() {
System.out.println(classVar); // OK
// System.out.println(instanceVar); // Error
}
public void instanceMethod() {
System.out.println(classVar); // OK
System.out.println(instanceVar); // OK
}
}
public class StaticApp {
public static void main(String[] args) {
System.out.println(Poo.classVar); //OK
// System.out.println(Poo.instanceVar); //Error
Poo.classMethod();
// Poo.instanceMethod(); // Error
Poo f1 = new Poo();
Poo f2 = new Poo();
System.out.println(f1.classVar); // I class var
System.out.println(f1.instanceVar); // I instance var
f1.classVar = "Changed by f1";
System.out.println(Poo.classVar); // Changed by f1
System.out.println(f2.classVar); // Changed by f1
f1.instanceVar = "Changed by f1";
System.out.println(f1.instanceVar); //Changed by f1
System.out.println(f2.instanceVar); // I instance var
}
}
진짜 같은 실험을 위해 f2 instance를 만들어주고 해봤다.
f1에서 class 변수를 바꿔 주면,
Poo class, f2 instance 에서 둘다 바뀌었다. 왜냐? class 변수들은 서로 링크되어 있으니까
f1에서 instance 변수를 바꿔주면,
f1에서는 바뀌지만, f2에서는 바뀌지 않는다. instance 변수들은 서로 독립적이기 때문이다.
그리고 당연히 class를 통해 instance의 변수에는 접근가능하지 않기 때문에 sysout으로 불러낼수 없다.
좀 오래 걸리긴 했는데
이정도면 꽤 훌륭하게 이해한거 같다
아싸뵤
'Java > Java 객체지향프로그래밍' 카테고리의 다른 글
객체지향 프로그래밍 활용~ (0) | 2020.11.27 |
---|---|
정신 꽉붙잡아 this 생성자 (0) | 2020.11.27 |
Instance (0) | 2020.11.26 |
클래스 more deeply (0) | 2020.11.25 |
클래스 존재 이유와 기본 형식 (0) | 2020.11.25 |