chapter 6 객체지향 프로그래밍1

byeol·2022년 7월 12일
0

Java의 정석

목록 보기
8/9
전체적인 FLOW
1. 객체지향언어
1.1 객체지향언어의 역사
1.2 객체지향언어
2. 클래스와 객체
2.1 클래스와 객체의 정의와 용도
2.2 객체와 인스턴스
2.3 객체의 구성요소 - 속성과 기능
2.4 인스천스의 생성과 사용
2.5 객체 배열
2.6 클래스의 또 다른 정의
3. 변수와 매섣,
3.1 선언위치에 따른 변수의 종류
3.2 클래스변수와 인스턴스 변수
3.3 메서드
3.4 메서드의 선언과 구현
3.5 메서드의 호출
3.6 return문
3.7 JVM의 메모리구조
3.8 기본형 매개변수와 참조형 매개변수
3.9 참조형  반환타입
3.10 재귀호출
3.11 클래스 메서드와 인스턴스 메서드
3.12 클래스멤버와 인스턴스 멤버간의 참조와 호출
4. 오버로딩
4.1 오버로딩이란?
4.2 오버로딩의 조건
4.3 오버로딩의 예
4.4 오버로딩의 장점
4.5 가변인자와 오버로딩
5. 생성자
5.1 생성자란?
5.2 기본생성자
5.3 매개변수가 있는 생성자
5.4 생성자에서 다른 생성자 호출하기-this(),this
5.5 생성자를 이용한 인스턴스의 복사
6. 변수의 초기화
6.1 변수의 초기화
6.2 명시적 초기화
6.3 초기화 블럭
6.4 멤버변수의 초기화 시기와 순서

일단 chapter6와 7은 객체지향언어의 특성을 이해하는데 매우 중요한 파트이다. 따라서 여러번 복습해야한다.

전체적인 내용을 그림으로 간략하게 정리해서 머릿속에 넣기로 했다.


  • 3.7 JVM의 메모리 구조
    JVM: 필요한 메모리 할당, 용도에 따라 메모리를 여러 영역으로 나누어 관리
    ① Method Area : 프로그램 실행 중 어떤 클래스가 사용-> 해당 class 파일을 읽어서 분석-> class information 저장(⊃클래스변수)
    Call stack : 메서드 작업에 필요한 메모리 공간 제공
    Stack을 생각해보세요.
    first in Last out

    class Main{
    public static void main(String[] args)}{
      System.out.println("야");
      firstMethod();//static 메서도는 객체 생성 없이 호출
      System.out.println("호");
    }
    static void firstMethod(){
     System.out.println("나");
      secondMethod();//static 메서도는 객체 생성 없이 호출
     System.out.println("비");
    }
    static void secondMethod(){
     System.out.println("박");
     System.out.println("수");
    }
    }

    결과는






    ③ Heap : 인스턴스가 생성되는 공간, 모든 인스턴스들을 저장

  • 3.8 기본형 매개변수와 참조형 매개변수
    -기본형 매개변수의 예시

    class Data {int x};
    
     class Main{
      public static void main(String[] args){
        Data d= new Data();
        d.x=10;
        
        change(d.x);
        System.out.println("change 후 x ="+d.x);
       }
      static change(int x){
       x=1000;
       System.out.println("change의 x"+x);
      
      }
      }

    d.x는 여전히 10이다. 그 이유는 기본형 메서드의 경우에는 참조형 변수의 주소를 받아서 그 값이 향하는 곳의 값을 변화시키는 것이 아니라
    단순히 값을 받아서 그 값을 변화시키는 것이기 때문이다.
    -참조형 매개변수의 예시

    class Data {int x};
    
     class Main{
      public static void main(String[] args){
        Data d= new Data();
        d.x=10;
        
        change(d);//change(d.x)
        System.out.println("change 후 x ="+d.x);
       }
      static change(Data d){//static change(int x)
       d.x=1000;
       System.out.println("change의 x"+d.x);
      
      }
      }

    d.x는 1000으로 변화한다. 여기서 중요한 것은 참조형 변수가 향하는 곳이 인스턴스의 주소값 즉 단지 참조형 변수를 선언한 것이 아니라 그 곳에 Data의 class 형을 가지고 있는 객체를 생성하고 그 주소를 참조형 변수에 저장하는 과정이 선행되었다는 것이다. 그래서 그 주소값이 저장된 참조형 변수를 change()라는 메서드가 받았다. 따라서 매개변수가 참조형 변수의 경우 그 곳에는 무조건 주소값이 저장된 형태이다. 그 주소값이 향하는 곳의 값을 변화시키는 것이 참조형 매개변수를 가지고 있는 메서드의 역할이다.

  • 3.9 참조형 반환타입
    반환값이 참조형 변수인데 참조형변수에는 주소값이 저장된다.
    즉 그냥 반환값이 주소형을 가진 정수라는 것이다.
    어떻게 활용될까?
    메소드의 결과값을 받은 참조형 변수 A는 반환값과 같은 주소를 가지게 되므로 같은 인스턴스를 향하게 된다!

    class Data{int x;}
     class Main{
      public static void main(String[] args){
          Data d = new Data();
          d.x=10;
          
          Data d2= copy(d);//사실 Data d2=d; 같은 결과이다.
      }
      static Data copy(Data d){
         Data tmp=new Data();
         tmp.x=d.x;
         return tmp;
      }
      }
    
  • 3.10 재귀함수

  • 3.11 클래스 매서드(static메서드)와 인스턴스 메서드

클래스 메서드인스턴스 메서드
static 메서드명static 메서드명
'클래스이름. 메서드명'반드시 객체를 생성해야만 호출이 가능.
클래스변수처럼 객체를 생성하지 않고 호출이 가능.

"어느 경우에 static을 사용해 클래스메서드를 정의하는가?"
-> 인스턴스와 관계없는 즉 인스턴스 변수나 인스턴스 메서드를 사용하지
않는 메서드를 클래스 메서드로 정의한다.

구체적으로 살펴보자

클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙여 클래스변수를 만든다.

클래스변수는 인스턴스를 생성하지 않아도 사용할 수 있다.

클래스 메서드는 인스턴스 변수를 사용할 수 없다.
-인스턴스 변수는 반드시 인스턴스가 존재해야 사용할 수 있다.
그러나 클래스메서드는 인스턴스 생성 없이 호출이 가능하다
따라서 클래스 메서드가 호출되었을 때는 인스턴스가 없을 수도 있기 때문에 인스턴스 변수를 사용할 수 없다.
반면에, 인스턴스 메서드는 static이 붙은 클래스 변수 사용이 가능하다. 이는 설명하지 않아도 알 것이다.

메서드 내에 인스턴스 변수를 사용하지 않는다면 메서드에 static을 붙이는 것을 고려한다.
즉 static 변수를 사용하거나
메서드의 매개변수를 사용하거나

class MyMath2{
	long a,b;

	long add() {return a+b;}
	long subtract() {return a-b;}
	long multiply() {return a*b;}
	double divide() {return a/b;}
	//인스턴스 변수가 아닌 매개변수를 통해서만 함수를 생성
  //따라서 static 메서드가 된다~!
	static long add(long a, long b) {return a+b;}
	static long subtract(long a, long b) {return a-b;}
	static long multiply(long a, long b) {return a*b;}
	static long divide(long a, long b) {return a/b;}
}
public class MyMathTest2 {
	public static void main(String[] args)
	{
		System.out.println(MyMath2.add(1L,2L));
		
		MyMath2 mm= new MyMath2();
		mm.a=1L;
		mm.b=100L;
		System.out.println(mm.add());
		
	}

}
  • 3.12 클래스 멤버와 인스턴스 멤버간의 참조와 호출

    같은 클래스 내에 있는 멤버들 간에는 별도의 인스턴스를 생성하지 않고 호출할 수 있습니다.
    단, 이 경우는 ¹ 인스턴스 메서드의 호출, ² 인스턴스 메서드 내 클래스변수나 인스턴수 변수를 호출, ³ 클래스 메서드에서 클래서 변수나 클래스 메서드를 호출할 때입니다.
    <매우 드물지만> ¹ 클래스 메서드에서 인스턴스 메서드나 인스턴스 변수를 사용할 경우 ² 클래스 변수에 인스턴스 변수를 대입할 경우 (static int cv= iv;//Error)는 객체를 생성하여 인스턴스를 만들어주고 난 후 사용이 가능합니다. 왜냐하면 클래스 메서드를 호출할 때는 인스턴스를 생성하지 않을 수도 있기 때문입니다.

    class Member{
    	int iv=10;
    	static int cv=20;
    	
    	int iv2=cv;
    	//static int cv2=iv;
    	static int cv2= new Member().iv;
    	
    	static void staticMethod1() {
    		System.out.println(cv);
    		//System.out.println(iv);
    		System.out.println(new Member().iv);
    		//혹은 같은 말
    		Member mm= new Member();
    		System.out.println(mm.iv);
    		
    	}
    	void instanceMethod1() {
    		System.out.println(cv);
    		System.out.println(iv);
    	}
    	static void staticMethod2() {
    		staticMethod1();
    		new Member().instanceMethod1();
    	}
    }
    class MemberCall{
    	public static void main(String[] args) {
    		
    		Member.staticMethod2();
    		
    		
    	}
    }
    //20
    //10
    //10
    //20
    //10

4. 오버로딩(overloading)

  • 4.1
    오버라이딩 VS. 오버로딩
    -오버라이딩 조상클래스에 있는 메서드를 자손클레스에서 변경하는 것
    -오버로딩 같은 이름의 메서드이지만 매개변수가 타입이 다른 함수가 같은 클래스 내에 존재하는 것

  • 4.2 오버로딩의 조건
    ① 매서드의 이름이 같아야 한다
    ② 매개변수의 개수 또는 타입이 달라야 한다.
    ③ 반화타입이 달라야 한다.
    반환타입은 영향을 주지 못한다!!

  • 4.3 오버로딩의 예시

    // 대표적으로 println메서드가 있다.
    void println()
    void println(boolean x)
    void println(char x)
    void println(char[] x)
    void println(double x)
    void println(float x)
    void println(int x)
    void println(long x)
    void println(object x)
    void println(String x)
    //이 두 예시를 보라
    int add(int a,int b){return a+b;}
    int add(int x, int y){return x+y;}
    //두 메서드는 <같은> 매서드이다.
    //이 두 예시를 보라
    int add(int a,int b){return a+b;}
    long add(int a, int b){return (long)(a+b);}
    //두 메서드는 <같은> 매서드이다.
    //이 두 예시를 보라
    long add(int a,long b){return a+b;}
    long add(long a, int b){return a+b;}
    //두 메서드는 <다른> 매서드이다.
    //그러나 만약 add(3,3)은 어떤 메서드를 호출해야할까?
    //이런 경우에는 같은 일을 하지만 매개변수를 달리하는 여러 경우의 수를
    //고려하여 여러 함수를 만들어 두어야 한다.
    //사용자가 어떤 매개변수를 넣든 같은 역할을 할 수 있도록!
    long add(int[] a){
    long result=0;
    for(int i=0;i<a.length;i++){
      result+=a[i];
    }
    return result;
    }
  • 4.4 오버로딩의 장점

    // 대표적으로 println메서드가 있다.
    void println()
    void println(boolean x)
    void println(char x)
    void println(char[] x)
    void println(double x)
    void println(float x)
    void println(int x)
    void println(long x)
    void println(object x)
    void println(String x)

    같은 역할을 하는 println의 함수들
    만약에 오버로딩이 허용되지 않는다면
    모두 다른 메서드 이름을 가져야한다.
    이는 결국 사용자와 개발자 모두에게 부담으로 다가온다.

  • 4.5 가변인자와(varargs)와 오버로딩
    가변인자는 매서드의 개수가 고정적 -> 동적으로 지정 가능

    타입...변수명

    public PrintStream printf(String format,Object...args){...}

    단 몇 가지 예시를 통해서 알아보자
    ① 가변인자를 매개변수 중에서 제일 마지막에 선언해야 한다.

    public PrintStream printf(Object...args,String format){...}
    //컴파일 에러가 뜬다!

    ② 가변인자는 내부적으로 배열을 이용하는 것이다. 그렇다면!
    굳이 왜 가변인자를 이용하는 것일까?

    String concatenate(String...str){...}
    VS.
    String concatenate_1(String[] str){...}
    자, 이렇게 배열로 한 경우에는 무조건 인자를 지정해야 한다.

    System.println(concatenate());
     System.println(concatenate("a"));
     System.println(concatenate("a","b"));
     System.println(concatenate(new String[]{"a","b"}));//배열도OK
    System.println(concatenate_1());//에러. 인자가 없음
     System.println(concatenate_1(new String[0]));//반드시 인자를 지정
     System.println(concatenate_1(null));//반드시 인자를 지정
  • ③ 배열을 매개변수로 넣을 때 주의해야할 것
    함수
    System.out.println(concatenate("100","200","300"));
    System.out.println(concatenate(new String[]{"100","200","300"}));
    System.out.println(concatenate({"100","200","300"}));

    ④ 가변인자를 사용한 메서드는 오버로딩을 하지 않는 것이 좋다.

5. 생성자(Constructor)

  • 5.1 생성자란?
    인스턴스 초기화 메서드이다.
    인스턴스 변수의 초기화 작업에 주로 사용된다.
    인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.
    생성자는 메서드라고 했다.
    하지만 우리가 알고 있는 함수와는 조금 다른 특별한 함수이다.

    1. 생성자의 이름은 클래스의 이름과 같아야 한다.
    2. 생성자는 리턴값이 없다-> 그렇지만 void를 사용하지 않는다.
    3. 하나의 클래스에는 여러개의 생성자가 존재할 수 있다.
      (생성자의 오버로딩)
    • Card c
      참조변수 c는 Card 클래스를 인스턴스의 주소를 저장하는 변수이다.
      이 변수 c를 선언한다.
    • c=new Card();
      ① 연산자 new에 의해서 메모리(heap)에 Card클래스의 인스턴스를 생성한다.
      ② 생성자 Card()가 호출되어 초기화 진행
      ③ 연산자 new의 결과로, 생성된 Card 인스턴스의 주소가 변환되어 참조변수 c에 저장된다.
  • 5.2 기본생성자(default constructor)
    나는 이전에 여러 개의 class를 만들어서 사용했지만
    생성자를 만들지는 않았다.
    하지만 class에는 반드시 하나 이상의 생성자가 존재하여야 한다.
    이것이 문제가 되지 않았던 이유는 컴파일러가 기본생성자를 만들어 주기 때문이다.
    즉, 컴파일러는 소스파일의 클래스에 생성자가 하나도 정의되지 않았을 때

    클래스이름(){}
     Card(){}

    이 형태의 기본생성자를 추가하여 컴파일을 한다.
    이 기본생성자를 보자
    ¹매개 변수도 없다!
    ²실행 내용도 없다!
    아주 간단한 모양이다!
    이는 내가 이전에 정의한 클래스들이 특별히 초기화를 하는 과정이 요구되지 않았던 작업이었기 때문이다.

  • 5.3 매개변수가 있는 생성자
    생성자도 메서드의 일종이기 때문에 매개변수가 있을 수 있다.

    class Car{
     String color;
     String geartype;
     int door;
     
     Car(){}//생성자
     Car(String c, String g, int d){//생성자
       color=c;
       geartype=g;
       door=d;
     } 
    }
  • 5.4 생성자에서 다른 생성자 호출하기-this(),this
    사실 이 부분은 헷갈린다.
    나는 보통 super()와 헷갈린다.
    여기서 중요한 것은 이 this라는 것이 어떤 범위에서 사용되는 것인가이다.
    -this()는 같은 클래스 내에서 여러 생성자가 존재할 때,
    한 생성자 내부에서 다른 생성자를 호출할 때 사용한다.

    Car(String color){
    //Car(color,"auto",4); 에러 Car대신 this를 사용해라!
    this(color,"auto",4);//생성자 호출은 무조건 첫번째 줄!
    door=5;
    }

    -super()은 자손클래스에서 조상클래스의 생정자를 호출할 때

    -this는 <생성자의 매개변수명== 클래스의 인스턴스 변수>일 때,
    이것이 클래스의 인스턴스 변수이다 라는 것을 표현한기 위해 사용한다.

    class CarTest2{
     String color;
     String geatType;
     int door;
     
     Car(String color, String gearType, int door){
        this.color= color;
        this.gearType=gearType;
        this.door=door;
      }
     }

    this.Z=Z;
    this.인스턴스변수=생성자의 매개변수값;
    여기서 중요한 것
    class(static이 붙은)변수는 this를 사용할 수 없다.

  • 5.5 생성자를 이용한 인스턴스의 복사
    현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.

    class Car{
    	String color;
    	String gearType;
    	int door;
    	
    	Car(){
    		this("White","auto",4);
    	}
    	Car(Car c){//매개변수를 그대로 복사하는 인스턴스를 생성
    		color=c.color;
    		gearType=c.gearType;
    		door=c.door;
    		//this(c.color,c.gearType,c.door);//간단히
    	}
    	Car(String color,String gearType, int door){
    		this.color=color;
    		this.gearType=gearType;
    		this.door=door;
    	}	
    }
    public class CarTest3 {
    	public static void main(String[] args) {
    	    Car c1= new Car();
    	    Car c2= new Car(c1);
    	    System.out.println("c1의 color="+c1.color+",gearType="+c1.gearType+",door="+c1.door);
    	    System.out.println("c2의 color="+c2.color+",gearType="+c2.gearType+",door="+c2.door);
         c1.door=100;
         System.out.println("cl의 door을 100으로 설정한 후");
         System.out.println("c1의 color="+c1.color+",gearType="+c1.gearType+",door="+c1.door);
    	    System.out.println("c2의 color="+c2.color+",gearType="+c2.gearType+",door="+c2.door);
    	} 
    }

    서로 같은 상태를 갖지만 독립적인 메모리 공간을 가지기 때문에
    c1의 door의 값을 바꿔도 c2에 영향을 주지 않는다.

더 나아가 만약에 참조변수를 인스턴스 변수로 가지게 된다면 어떻게 될까?
그 때는 서로 영향을 주지 않을까?

class P_new{
	int x,y;
	
	P_new(int x, int y){
		this.x=x;
		this.y=y;
	}
}
class Car{
	String color;
	String gearType;
	int door;
	P_new p ;
	
	Car(){
		this("White","auto",4,new P_new(3,3));
	}
	Car(Car c){//매개변수를 그대로 복사하는 인스턴스를 생성
		color=c.color;
		gearType=c.gearType;
		door=c.door;
		p=c.p;
		//this(c.color,c.gearType,c.door);//간단히
	}
	Car(String color,String gearType, int door,P_new p){
		this.color=color;
		this.gearType=gearType;
		this.door=door;
		this.p =p;
	}	
}
public class CarTest3 {
	public static void main(String[] args) {
	    Car c1= new Car();
	    Car c2= new Car(c1);
	    System.out.println("c1의 color="+c1.color+",gearType="+c1.gearType+",door="+c1.door+",point="+c1.p.x+","+c1.p.y);
	    System.out.println("c2의 color="+c2.color+",gearType="+c2.gearType+",door="+c2.door+",point="+c2.p.x+","+c2.p.y);
       c1.p.x=4;
       c1.p.y=5;
       System.out.println("cl의 P_new를 (4,5)로 설정한 후");
       System.out.println("c1의 color="+c1.color+",gearType="+c1.gearType+",door="+c1.door+",point="+c1.p.x+","+c1.p.y);
	    System.out.println("c2의 color="+c2.color+",gearType="+c2.gearType+",door="+c2.door+",point="+c2.p.x+","+c2.p.y);
	}
}

서로 영향을 줌을 확인 할 수 있었다.
그 이유는 참조변수 자체의 주소를 그대로 가져가기 때문이다.
사실 이는 얕은 복사이다.
복습하며 뒤 clone을 통해서 딥복사와 얕은 복사를 배워서 응용할 수 있었다.

인스턴스를 생성할 때는 다음의 2가지 사항을 결정해야한다.
1. 클래스-어떤 클래스의 인스턴스를 생성할 것인가?
2. 생성자-선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?

6. 변수의 초기화

  • 6.1 변수의 초기화
    "변수의 초기화는 변수를 선언하고 처음으로 값을 저장하는 것"

    • 멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어지므로 초기화를 하지 않고 사용할 수 있다.

    • 지역변수는 사용하기 전에 반드시 초기화를 해야한다.

      class InitTest{
      int x;//인스턴스 변수 int의 기본값이 0으로 초기화되어져 있음.
      int y=x;
      
      void method(){
         int i;//지역변수는 아직 값이 지정안됨
         int j=i;//에러. 지역변수 i가 초기화되지 않은 상태에서 사용됨
      }
      }

      멤버변수와 배열의 초기화는 선택적이지만,
      지역변수의 초기화를 필수적이다.

      각 타입의 기본값

      자료형기본값
      booleanfalse
      char'\u0000'
      byte,short,int0
      long0
      float0.0f
      doubld0.0d또는 0.0
      참조형 변수null

      ▶멤버변수의 초기화 방법 3가지
      1. 명시적 초기화 : 선언과 동시에 초기화
      2. 생성자
      3. 초기화 블럭
      -인스턴스 초기화 블럭 : 인스턴스 변수를 초기화하는데 사용.
      -클래스 초기화 블럭 : 클래스변수를 초기화하는데 사용.

  • 6.2 명시적 초기화
    선언과 동시에 초기화, 가장 기본적이면서 간단한 방법

    class Car{
      int door=4;
      Engine e =new Engine();
    }
  • 6.3 초기화 블럭
    명시적 초기화만으로 부족한 경우 초기화 블럭을 사용한다.

    static{}:클래스변수를 초기화하기 위한 블럭
    {}:인스턴스 변수를 초기화하기 위한 블럭
    ->인스턴스 변수의 초기화는 주로 생성자를 사용하고, 인스턴스 초기화 블럭은 모든 생성자에서 공통으로 수행돼야 하는 코드를 넣는데 사용한다.

    Card(){
     count ++;
     serialNo =count;
     color="white";
     gearType="Auto";
    }
    
    Card(String color, String gearType){
     count++;
     serialNo=count;
     this.color=color;
     this.gearType=gearType;
    }

    여기서 보면
    count++;
    serialNo=count;
    가 공통적으로 들어가기 때문에 같은 코드가 중복된다.
    이를 우리는 인스턴스 초기화 블럭으로 넣어주어 코드를 보다 간결하게 만들 수 있다.

    {
     count ++;
     serialNo =count;
    }//인스턴스 초기화 블럭
    
    Card(){
     color="white";
     gearType="Auto";
    }
    
    Card(String color, String gearType){
     this.color=color;
     this.gearType=gearType;
    }

    알아둬야할 것이 있다.
    ① 클래스 초기화 블럭은 클래스가 메모리에 처음 로딩될 때 한번만 수행
    ② 인스턴스 초기화 블력은 생성자와 같이 인스턴스를 생성할 때마다 수행
    ③ 생성자보다 인스턴스 초기화 블럭이 먼저 수행
    이 3가지는 꼭 기억해둬야 한다.

    class BlockTest {
    static { //클래스 초기화 블럭
    	 System.out.println("static {}");
    }  
    { //인스턴스 초기화 블럭
    	 System.out.println("{}");
    }
     
    public BlockTest() {//생성자
    	 System.out.println("생성자");
    	 
    }
    public static void main(String[] args) {
    	 System.out.println("BlockTest bt =new BlockTest()");
    	 BlockTest bt= new BlockTest();
    	 
    	 System.out.println("BlockTest bt2 =new BlockTest()");
    	 BlockTest bt2= new BlockTest();
    }


    위 예제가 실행되면서 BlockTest 메모리가 로딩될 때
    가장 먼저 클래스 초기화 블럭이 수행
    이후 인스턴스를 생성할 때 인스턴스 초기화 블럭이 실행되고
    그 다음으로 생성자가 실행된다.

  • 6.4 멤버변수의 초기화 시기와 순서

    class InitTest{
      static int cv=1;
      int iv=1;
      
      static {cv=2;}//클래스 초기화 블럭
      {iv=2;}
      InitTest(){
              iv=3;   
      }
    }
    클래스 초기화 -▶인스턴스초기화
    1. 기본값 cv=0
    2. 명시적 초기화 cv=1
    3. 클래스 초기화 블럭 cv=2
    4. 기본값 cv=2, iv=0
    5. 명시적 초기화 cv=2, iv=1
    6. 인스턴스 초기화 블럭 cv=2, iv=2
    7. 생성자 cv=2,iv=3

    클래스 초기화는 처음에 메모리에 로딩될 때 한번만
    인스턴스 초기화는 인스턴스가 생성될 때마다 이루어진다.

    순서는 클래스 초기화가 먼저 일어나고 인스턴스 초기화가 이루어진다.
    각 초기화는 기본값-> 명시적 초기화-> 초기화 블럭-> 인스턴스 초기화의 경우 생성자까지 순으로 이루어진다.

profile
꾸준하게 Ready, Set, Go!

0개의 댓글