[JAVA_Back-End]

[JAVA] 클래스와 인스턴스 + 생성자 본문

Programming/JAVA

[JAVA] 클래스와 인스턴스 + 생성자

너굴위 2023. 8. 23. 12:26
728x90
반응형

< 지난 포스팅 정리 >
객체(Object)
=> 사물의 추상화 (공통적인 내용 분리)
=> class
     멤버필드
     메서드
               문법
               오버로딩
               가변인자
=> 참조변수 선언/생성/초기화
*1개 java -> 1개이 class를 정의
  1개 java -> 여러개의 class를 정의도 가능(x)
                     일반클래스
                     실행클래스 
                                       main메서드 포함
                                       클래스명 = 파일명
                                        public
 
멤버필드
메서드
          - 사용할 수 있는 영역(존재 시간)
            인스턴스                  기호(x)
            클래스(static)           static   공유멤버필드


클래스 : 객체를 정의해 놓은 것

              객체를 생성하는 데 사용

 

객체 : 실제로 존재하는 것. 사물 또는 개념

          객체가 가지고 있는 기능과 속성에 따라 다름

 

 

# 인스턴스 변수와 클래스 변수
=> 인스턴스 변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만,
     클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.
 
* StudentMain01.java - 멤버필드의 초기화

//class 선언
class Student {

              String name;
              String number;
              int age;
              double height;
              double weight;

}

public class StudentMain01{
    public static void main(String[] args) {
        //참조변수 선언
        Student stu1;
         
        //참조변수 생성
        stu1 = new Student();  //인스턴스

        //초기화->멤버필드 초기화
        stu1.name="홍길동";
        stu1.number="1001";
        stu1.age=20;
        stu1.height=180;
        stu1.weight=80;

        //초기화 시킨 멤버필드를 출력
        System.out.println(stu1.name);
        System.out.println(stu1.number);
        System.out.println(stu1.age);
        System.out.println(stu1.height);
        System.out.println(stu1.weight);


        //stu2인스턴스 생성
        Student stu2= new Student();
        stu2.name="손수빈";
        stu2.number="1002";
        stu2.age=23;
        stu2.height=163;
        stu2.weight=55;

        System.out.println(stu2.name);
        System.out.println(stu2.number);
        System.out.println(stu2.age);
        System.out.println(stu2.height);
        System.out.println(stu2.weight);


       
        System.out.println(stu1); //참조값 확인
        System.out.println(stu2);
    }
}

 
 
* VariableEx01.java  - 인스턴스 변수와  클래스 변수

class Variable{

    //인스턴스 멤버필드
    String str1;

    //클래스 멤버필드
    static String str2;
}



public class VariableEx01 {
    public static void main(String[] args){

        Variable v1 = new Variable();
        Variable v2 = new Variable();
        v1.str1="홍길동";
        v1.str2="손수빈";

        System.out.println(v1.str1);
        System.out.println(v1.str2);

        System.out.println(Variable.str2);
        Variable.str2="이순신";
        System.out.println(Variable.str2);

        v2.str1="강감찬";
        System.out.println(v2.str1);
        System.out.println(v2.str2);

    }
}

 
* Ex6_3.java  - 인스턴스 변수와 클래스 변수 예제

public class Ex6_3 {
    public static void main(String[] args) {
        System.out.println("Card.width = "+Card.width);
        System.out.println("Card.height = "+Card.height);

        Card c1= new Card();
        c1.kind="Heart";
        c1.number= 7;

        Card c2=new Card();
        c2.kind="Spade";
        c2.number=4;

        System.out.println("c1은"+c1.kind+", "+c1.number +"이며, 크기는("+c1.width+", "+c1.height+ ")");
        System.out.println("c2은"+c2.kind+", "+c2.number +"이며, 크기는("+c2.width+", "+c2.height+ ")");
        System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
        c1.width=50;
        c1.height=80;

        System.out.println("c1은"+c1.kind+", "+c1.number+"이며, 크기는 ("+c1.width+","+c1.height+")");
        System.out.println("c2은"+c2.kind+", "+c2.number+"이며, 크기는 ("+c2.width+","+c2.height+")");   //c1값을 바꿨지만 c2에도 적용이 된다(클래스 변수이기 때문)
    }
}

class Card{
    String kind;
    int number;
    static int width =100;
    static int height = 250;

}

 
* MethodEx04.java  - 인스턴스 메서드와 클래스 메서드

class Method{
    //인스턴스 메서드
    void doFunc1(){  
        System.out.println("doFunc1()호출");
    }

    //클래스 메서드
    static void doFunc2(){
        System.out.println("doFunc2()호출");
    }
}

public class MethodEx04 {
    public static void main(String[] args){
        Method m1 = new Method();
        Method m2 = new Method();
        m1.doFunc1();
        m1.doFunc2();

        Method.doFunc2();

        m2.doFunc1();
        Method.doFunc2();

    }
}

메서드 참조 그림

 
* MethodEx05.java  -클래스 변수와 인스턴스 변수 / 클래스 메서드와 인스턴스 메서드 활용

class Method{
    String str1="데이터1";
    static String str2="데이터2";

    void doFunc1(){
        System.out.println(str1);
        System.out.println(str2);
    }

    static void doFunc2(){    
        //System.out.println(str1);   //static함수 안에서는 인스턴스 변수를 사용하지 못함
        System.out.println(str2);

    }
}

public class MethodEx05 {
    public static void main(String[] args){
      Method m = new Method();
      m.doFunc1();
      //m.doFunc2();

      Method.doFunc2();    //클래스 안에 있는 static 함수를 참조

    }
}


 
 
* MethodEx06.java - 인스턴스 메서드 안에서 this로 인스턴스 메서드 참조

class Method{
    String str1="데이터1";
   
    void doFunc1(){
        System.out.println(str1);
        //this는 자기참조용 주소
        System.out.println(this);  
        System.out.println(this.str1);
       
        //doFunc2();
        this.doFunc2();
    }

    void doFunc2(){
        System.out.println("doFunc2() 호출");
    }
   
}

//public static void main(String[] args) 설명
//java MethodEx06
// java= MethodEx06.main()  실행


public class MethodEx06 {
    public static void main(String[] args){
      Method m = new Method();
      Method m1 = new Method();
      m.doFunc1();
      System.out.println(m);   //m은 참조값(주소)
      System.out.println(m1);
      m1.doFunc1();     //m과 m1에서 만들어진 doFunc1는 서로 다른 객체이기 때문에 this를 했을 때 주소값이 다르다.
     
      System.out.println(m);
      System.out.println(m1);
    }
}

 
 


 
생성자 (Constructor)

- 객체의 레퍼런스를 생성하기 전에 객체의 초기화를 위해 사용되는 코드의 블록 (인스턴스 초기화)
- 생성자의 이름 = 클래스의 이름
- 생성자는 return 값이 없다.
- 생성자 안에서 다른 생성자를 호출할 때는 항상 첫줄에서만 호출해야 한다.
- 연산자 new가 인스턴스를 생성하는 것이며 생성자가 인스턴스를 생성하는 것이 아니기 때문에 헷갈리면 안된다.
   => 메모리가 생성될 때 생성자도 호출이 가능하다.
 
* ConstructorEx01.java  - 생성자의 기본구조

class Constructor{
    //생성자의 메서드명은 클래스 이름과 같아야 한다
    // 리턴이 없음
    //컴파일러가 기본적으로 제공해왔기 때문에(기본생성자) 사용하지 않았던 것이다.
    Constructor(){
        System.out.println("생성자 호출");

    }
}


public class ConstructorEx01 {
    public static void main(String[] args) {
        // new Constructor();
        // => Constructor() : 생성자 호출
        Constructor c1 = new Constructor();
        //c1.Constructor();  생성자를 따로 호출할 수 없다. 윗줄과 같이 메모리가 생성될 때 생성자도 호출이 가능하다.
    }
}

 
* ConstructorEx02.java  - 생성자 오버로딩

class Constructor{

    String str1;

    //생성자 오버로딩: 생성자의 이름이 같아도 매개변수가 다르기 때문에 같은 이름을 사용할 수 있음
    Constructor(){
        System.out.println("생성자 호출");
        str1="홍길동";

    }

    Constructor(String str1){
        this.str1=str1;     //this는 인스턴스 멤버와 연관이 있기 때문에 변수이름이 같아도 참조하는 역할이 다름을 알 수 있다.
    }
}


public class ConstructorEx02 {
    public static void main(String[] args) {
       
        Constructor c1 = new Constructor();
        Constructor c2 = new Constructor("손수빈");
        System.out.println(c1.str1);   //기본 생성자 Constructor을 출력
        System.out.println(c2.str1);   //따로 만든 생성자 Constructor(String str1)을 출력
    }
}

 
* Ex6_12.java  - 기본생성자와 매개변수가 있는 생성자

class Car{

    String color;
    String gearType;
    int door;

    Car(){}    //기본 생성자

    Car(String c, String g, int d){  //매개변수가 있는 생성자
        color=c;
        gearType=g;
        door=d;
    }
}

public class Ex6_12 {
    public static void main(String[] args) {
       
      Car c1 = new Car();
      c1.color ="white";
      c1.gearType="auto";
      c1.door=4;

      Car c2=new Car("white", "auto", 4);

      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);
    }
}

 
* Ex6_13.java - 기본생성자와 매개변수가 있는 생성자(2)
-> 매개변수가 있는 생성자를 기본 생성자에서 this로 참조해 사용할 수 있다 (반복되는 내용 혹은 적용할 내용이 있을 시)
-> this.color 하면 인스턴스 변수이고, color은 생성자의 매개변수로 정의된 지역변수가 된다. ( 변수의 이름은 같지만 참조하는 내용이 달라진다)
-> this로 생성자를 참조하는지 인스턴스 변수를 참조하는지에 정확히 확인해야 한다.

class Car2{

    String color;
    String gearType;
    int door;

    Car2(){
        this("white","auto",4);
    }    //기본 생성자

    Car2(String color){  //매개변수가 있는 생성자
       this(color,"auto",4);   //this()생성자를 참조
    }

    Car2(String color,String gearType, int door){
        this.color=color;   //this:클래스의 인스턴스 변수를 참조
        this.gearType=gearType;
        this.door=door;

    }
}

public class Ex6_13 {
    public static void main(String[] args) {
        Car2 c1= new Car2();
        Car2 c2 = new Car2("blue");

        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);
    }
}

 
+ 만약 멤버필드에서 인스턴스 변수를 할당하고 초기값을 지정하지 않으면 자동으로 초기화 되어
   String은 null값 int는 0값이 나타난다.
+ 대신 멤버변수(클래스 변수와 인스턴스 변수)와 배열의 초기화는 선택이지만, 지역변수의 초기화는 필수이다.
 
 
* StudentEx01.java  - 생성자 오버로딩 (2)
- this로 다른 생성자 호출하기

class Student{
    String hakbun;
    String name;

    //생성자 오버로딩
    Student(){   //기본생성자에 값을 지정
        //this.hakbun="0000";
        //this.name="아무개";
        //Student("0000","아무개");   //생성자는 직접적으로 호출할 수 없기 때문에 this를 사용하여 해당 클래스의 생성자를 참조하는 느낌으로 부를 수 있다.
        this("0000","아무개");   //다른 생성자를 호출할 때는 항상 첫줄에서만 호출해야 한다.
    }

    Student(String name){   //이름만 인자로 받겠다 (학번은 값을 지정)
        //this.hakbun="0000";
        //this.name=name;
         this("0000","아무개");

    }

    Student(String hakbun, String name){    //학번 이름 둘다 인자로 받겠다.
        this.hakbun=hakbun;
        this.name=name;
    }

    void viewStudent(){
         System.out.printf("%s\t%s\n",this.hakbun,this.name);
    }
}


public class StudentEx01 {
    public static void main(String[] args) {

        Student s1 =new Student();
        s1.viewStudent();

        Student s2 = new Student("손수빈");
        s2.viewStudent();

        Student s3 = new Student("0928","손수빈");
        s3.viewStudent();

    }
   
}

 
상속
=> 공통 클래스
=> 같은 특징이 있다면 해당 특징을 클래스로 만든다. (부모클래스)
=> 해당 특징을 적용해야한다면 자식클래스에 부모클래스를 extends한다.
 
* 상속의 구조
자식클래스 extends 부모클래스 {
}
 
유도클래스
공통클래스
 
 

클래스를 다중상속시켰을 때 생성자의 주소값은 같다.

 
* InheritanceEx02.java  - 부모클래스/자식1클래스/자식2클래스 생성한 후 출력값 확인하기
- 메서드 뿐만 아니라 변수까지 상속이 가능하다.


class Parent{
    //private String p ="부모";    //private는 상속이 불가능하다
    String p ="부모";
    void viewParent(){
        System.out.println("viewParent() 호출");
    }
}

class Child1 extends Parent{
    String c1 ="자식 1";
    void viewChild(){
        System.out.println("viewChild() 호출");
    }
}

class Child2 extends Parent{
    String c2 = "자식 2";
    void viewChild2(){
        System.out.println("viewChild2() 호출");
    }
}



public class InheritanceEx02 {
    public static void main(String[] args) {
        Parent p1 = new Parent();
        p1.viewParent();

        Child1 c1 = new Child1();
        c1.viewChild();
        c1.viewParent();

        System.out.println(c1.c1);
        System.out.println(c1.p);   // 메서드 뿐 아니라 변수까지 상속이 가능하다.

        Child2 c2 = new Child2();
        c2.viewChild2();
        c2.viewParent();

         System.out.println(c2.c2);
        System.out.println(c2.p);
    }
    
}

 
* InheritanceEx03.java  - 부모 자식 손자 클래스 상속


class Parent{
    //private String p ="부모";    //private는 상속이 불가능하다
    String p ="부모";

    Parent(){
        System.out.println("Parent 생성자 호출"+this);
    }
    void viewParent(){
        System.out.println("viewParent() 호출");
    }
}

class Child extends Parent{
    String c1 ="자식 1";

    Child(){
        System.out.println("Child 생성자 호출"+this); //모르겠음
    }
    void viewChild(){
        System.out.println("viewChild() 호출");
    }
}

class GrandChild extends Child{
    String gc = "손자";

    GrandChild(){
        System.out.println("GrandChild 생성자 호출"+this);
    }
    void viewGrandChild(){
        System.out.println("viewGrandChild() 호출");
    }
}

public class InheritanceEx03 {
    public static void main(String[] args) {
       
        GrandChild gc = new GrandChild();

       
        gc.viewGrandChild();
        gc.viewChild();
        gc.viewParent();    //GrandChild ---상속---> Child ---상속---> Parent

        System.out.println(gc.p);
        System.out.println(gc.c1);
        System.out.println(gc.gc);

    }
}

 
* Ex7_1.java  - 상속 예제(Smart Tv클래스와 Tv클래스)

class Tv{
    boolean power;
    int channel;

    void power() { power =! power;}
    void channelUp() { ++channel;}
    void channelDown(){--channel;}
}

class SmartTv extends Tv{
    boolean caption;
    void displayCaption (String text){
        if(caption){
            System.out.println(text);
        }
    }
}

public class Ex7_1 {

    public static void main(String[] args) {
        SmartTv stv = new SmartTv();    //SmartTv는 Tv클래스를 상속받기 때문에 SmartTv클래스 하나만 인스턴스화 해서 객체로 사용해도 모든것을 사용할 수 있다.
        stv.channel=10;
        stv.channelUp(); //SmartTv에는 channelUp메소드가 없지만 Tv를 상속받았기 때문에 해당 메소드를 사용할 수 있는것이다.
        System.out.println(stv.channel);  //변수도 마찬가지
        stv.displayCaption("Hello, Worlds");
        stv.caption=true;
        stv.displayCaption("Hello, World");
    }
}

 
* InheritanceEx04.java  - 오버로딩/오버라이딩

  • 오버로딩 : 부모 클래스를 상속받으며 부모 클래스 안에 있는 메소드의 이름과 같은 메소드를 정의

                         매개변수의 형태나 개수가 다름  (매개변수의 형태에 따라 부모 메소드를 사용할지 안할지 정할 수 있음)

  • 오버라이딩:  부모 클래스를 상속받아도 자식 클래스에서 같은 형태(이름, 매개변수 동일)의 클래스를 재정의 하면 자식 메서드가 적용됨.

 


class Parent{
    //private String p ="부모";    //private는 상속이 불가능하다
    String p ="부모";

    Parent(){
        System.out.println("Parent 생성자 호출"+this);
    }
    void viewParent(){
        System.out.println("viewParent() 호출");
    }
}

class Child extends Parent{
    String c1 ="자식 1";

    Child(){
        System.out.println("Child 생성자 호출"+this);
    }
    void viewChild(){
        System.out.println("viewChild() 호출");
    }

    void viewParent(int i){   //오버로딩
        System.out.println("child viewParent() 호출");
    }
     void viewParent(){   //오버라이딩
        System.out.println("child viewParent() 호출");   //재정의 (부모로부터 상속받아도 자식 메서드가 먼저이다)
    }
}


public class InheritanceEx04 {
    public static void main(String[] args) {
       
        Child c =new Child();

        c.viewChild();
        c.viewParent(9);  //이렇게 되면 오버로딩
        c.viewParent();

    }




   
}

 
 
* InheritanceEx05.java  - super
super: 자식클래스 안에서 부모 클래스의 메서드를 호출하고 싶을 때 사용함


class Parent{
   
    void viewParent(){
        System.out.println("viewParent() 호출");
    }
}

class Child extends Parent{
    void viewChild(){
        System.out.println("viewChild() 호출");
    }

    //오버라이딩
     void viewParent(){  
        //부모 viewParent()
        super.viewParent();     //super :자식 안에서 부모의 메서드를 호출하고 싶을 때 사용
        System.out.println("child viewParent() 호출");  
    }
}

public class InheritanceEx05 {
    public static void main(String[] args) {
       
        Child c =new Child();

        c.viewChild();
        c.viewParent();
       
    }
   
}

 
* InheritanceEx06.java  - super(2)


class Parent{
  /*  Parent(){
    System.out.println("Parent 생성자 호출");
   }
   */

   Parent(String name){
    System.out.println("Parent(String name)생성자 호출");    //부모 클래스가 먼저 인스턴스화 되는데 기본 생성자가 없기 때문에 Child에서 호출할 시 에러발생
   }
}

class Child extends Parent{
  Child(){
    super("손수빈");  //부모의 생성자를 명시적으로 호출하고 싶을 때 super을 사용하여 호출가능하다.
    System.out.println("Child생성자 호출");
  }
}


public class InheritanceEx06 {
    public static void main(String[] args) {
       
        Child c =new Child();

    }
   
}

 
* Ex7_3.java  - this 와 super을 이용한 변수값 확인

class Parent2{int x =10;}

class Child2 extends Parent2{
    int x=20;
    void method(){
        System.out.println("x="+x);
        System.out.println("this.x="+this.x);
        System.out.println("super.x="+super.x);
    }
}

public class Ex7_3 {
    public static void main(String[] args) {
        Child2 c =new Child2();
        c.method();
    }
   
}

 
* Ex7_4.java  - this 와 super을 이용한 변수값 확인(2)

class Point{
    int x,y;
    Point(int x, int y){
        this.x=x;  //Point 클래스 안에 있는 인스턴스 변수(x,y)를 this로 표현
        this.y=y;
    }
}

class Point3D extends Point{
    int z;
    Point3D(int x,int y, int z){
        super(x, y);   //Point클래스를 상속받아 Point클래스 안의 Point생성자를 super로 사용
        this.z=z;      //Point3D 클래스 안에 있는 인스턴스 변수(z)를 this로 표현
    }
}

public class Ex7_4 {
    public static void main(String[] args) {
       Point3D p = new Point3D(1, 2, 3);  
       System.out.println("x="+p.x+",y="+p.y+",z="+p.z);
    }
   
}

 
* InheritanceEx07.java - final
final: 변수에 사용되면 값을 변경할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게된다.
         클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.


class Parent{    //여기에 final을 붙이면  cannot inherit from final Parent라고 뜬다 (상속불가능)
   
   String DATA;   //여기에 final을 붙이면  already have been assigned라고 뜨면서 처음 DATA만 적용이 된다.
   Parent(){
    System.out.println("Parent 생성자 호출");
    this.DATA="10";
    this.DATA="20";

    System.out.println(this.DATA);
   }

    void viewParent(){    // 여기에 final을 붙이면 cannot override viewParent() in Parent라고 뜬다 (오버라이딩 불가능)
    System.out.println("Parent viewParent() 호출");  
   }
   
}

class Child extends Parent{
  Child(){
    System.out.println("Child생성자 호출");
  }
  void viewParent(){
    System.out.println("Child viewParent() 호출");
   }
}


public class InheritanceEx07 {
    public static void main(String[] args) {
       
        Child c =new Child();
        c.viewParent();
    }
   
}

=> 어떤 변수인지 구분 할 수 있어야 한다.
(인스턴스 변수, 클래스 변수, 지역변수)
 
=> 오버라이딩과 오버로딩에 대한 개념 확실하게 잡기 

=> 상속 시 각 생성자의 주소값이 어떻게 되는지에 대해 이해 필요(주소가 왜 같게 나오는지)
 
변수 구분 정리 (시험문제 가능)
1. 클래스 변수 = Static변수
2. 인스턴스 안에 있는 변수가 인스턴스 변수
3. 인스턴스를 선언하는 변수는 main의 지역변수
4. 생성자 안에서 매개변수의 역할을 하는 변수는 지역변수
 
this 사용 정리
1. this    : 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
                모든 인스턴스메서드에 지역변수로 숨겨진 채로 존재한다.
2. this(), this(매개변수)    : 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.
 
오버로딩/오버라이딩 정리
1. 오버로딩 : 부모 클래스를 상속받으며 부모 클래스 안에 있는 메소드의 이름과 같은 메소드를 정의
                         매개변수의 형태나 개수가 다름  (매개변수의 형태에 따라 부모 메소드를 사용할지 안할지 정할 수 있음)
2. 오버라이딩:  부모 클래스를 상속받아도 자식 클래스에서 같은 형태(이름, 매개변수 동일)의 클래스를 재정의 하면 자식 메서드가 적용됨.

728x90
반응형