본문 바로가기

자바

[자바기초요약6] this(), super(), 다형적변수, instanceof연산자, 참조형간의 형변환


 


# this(), super()  : 생성자의 첫번째 줄에만 선언될 수 있다.
                               (생성자에서만쓰임)(또한 생성자에서만 호출가능...메서드에서는안됨)
 
   this() => 현재클래스()     <<< 생성자        
 
     ps. 생성자의 용도는 객체가 만들어짐과 동시에 속성이 정해짐( 속성이란 성이나 이름, 나이등과같은 멤버변수)
                                                Person p1=new person("객체가 생성됨과동시에 값을 줌");      
                                                메서드를이용할때는 생성과 값을 따로줌...

 
  * this,super와 this(), super()와 비교 *

class A{
          int a=100;              //은닉변수
}

class B extends A{
           int a=200;

           void m(){
                     System.out.println(super.a);           //100
                     System.out.println(this.a);            //200  
                     //this는 인스턴스 자신을 가리키는 참조변수로 인스턴스의 주소가 저장되어있다.
                     //즉, this는 자기자신의클래스 주소를 가지고있으므로 A.a하면 A클래스자체이지
                     //A클래스주소가아니다. 즉 new A().a 가 맞다 ( A.a X )                     
           }                                                                                    
}                                                                                                       


//생성자안에서 다른 생성자를 호출하는방법 3가지 :  this(),  super(),  new B()
class A{
     A(){   }
}

class B extends A{
     B(int a){
           //B();     생성자를 부를때는 this(), super(), new B(); 이런식으로만부를수있음
           //         (단순히 다른 생성자를 B(); 이렇게 부를수없음)
           new B();
           jin();
     }

     B(){  
          System.out.println(1); 
     }
    
     void jin(){ 
          System.out.println("jj");
     }

     public static void main(String args[]){
          B o=new B(1);
     }
}
[an]
1
jj
 
 
 
[ex]
class A{
 A(){
  System.out.println(1);
 }
 A(int a){                  //오버로딩
  this();                   //this()는 현재클래스A의 A()을 말함
  System.out.println(2);
 }
}
class B{
 public static void main(String args[]){
  A o=new A(0);
 }
}
 [an]
1
2
 

# 상속관계시 생성자 호출관계
class A{
 A(){
  System.out.println("aaa");
 }
}

class B extends A{                      // C클래스에서 B()를 부르지만 B클래스에서는 비어있다.
                                        // 비어있는곳은 사실 아래와같이 생략되어있다.
//      B(){
//         super();
//      }
// 따라서 super()에의해 부모클래스의 A()을 가리킨다.
}  
                                                                              
class C{                                                                      
 public static void main(String args[]){                                      
  B o=new B();                                                              
 }
}

[ex]
class A{
 A(String a){
  System.out.println("aaa");
 }
 A(){
  System.out.println("bbb");
 }
}

class B extends A{            //super()에의해 부모클래스의 A()을 가리킨다(  A(String a) 와 다름 )

}

class C{
 public static void main(String args[]){
  B o=new B();
 }
}

[an]
bbb

-------------------------------------------------

class A{
 A(String a){
  System.out.println("aaa");
 }
}

class B extends A{     
 B(){ 
  super("bbb");          // 위와달리 super안에 super("bbb") 를 지정해주어서
                         // 부모클래스A의 A(String a)을 가리킨다.
 }
}

class C{
 public static void main(String args[]){
  B o=new B();
 }
}

 
[ex]
class A{
 A(){
  System.out.println(100);
 }
}
class B extends A{
 B(){
  // 즉, 여기 super()이 숨어서 실행된다!!
  System.out.println(200);                   //super()는 첫번째줄에서 생성되기때문에
                                             // 200 100 이 아니라 100 200이 출력됨
 }
}
class C{
 public static void main(String args[]){
  B o=new B();
 }
}


[ex] 컴파일에러를 해결하시오.
class A{
 A(int a){
  System.out.println(100);
 }
}
class B extends A{
 B(){
  System.out.println(200);               // B()의 super()에의해 부모에서 찾지만 없다 => 오류
 }
}
class C{
 public static void main(String args[]){
  B o=new B();
 }
}

[an1]
class A{
 A(int a){
  System.out.println(100);
 }
 A(){}                                  //하나 새로만들거나
}
class B extends A{
 B(){
  System.out.println(200);
 } 
}
class C{
 public static void main(String args[]){
  B o=new B();
 }
}
[an2]
class A{
 A(int a){
  System.out.println(100);
 }
}
class B extends A{
 B(){
  super(0);                                       //super를 내가 새로만들어주거나 하면됨 
  System.out.println(200);
 } 
}
class C{
 public static void main(String args[]){
  B o=new B();
 }
}

[ex] main메서드는 수정하지 않고 
 100 200 300 400이 출력되게 하려면?
class A {
       A() {
              System.out.println(100);
       }

       A(int a) {
              System.out.println(200);
       }
}

class B extends A {
       B(String a) {
              System.out.println(300);
       }

       B(int a) {
              System.out.println(400);
       }
}

class C {
       public static void main(String args[]) {
              B o = new B(0);
       }
}

[an]
class A{
 A(){
  System.out.println(100);
 }
 A(int a){
  this();
  System.out.println(200);
 }
}
class B extends A{
 B(String a){
  super(1);
  System.out.println(300);
 }
 B(int a){
  this("aaa");                               //한 생성자의 첫줄에 this()를선언하면 super()는 생략되어있지않음..(하나만)
  System.out.println(400);
 } 
}
class C{
 public static void main(String args[]){
  B o=new B(0);
 }
}



ps. 
소스코드 80%는 다형적변수임... 그러면 연관된게 instanceof연산자와 참조형간의
형변환이 매우 중요함! 
( 다형적변수 ,instanceof연산자, 형변환!!!! )
 


# 다형적변수 : 오버라이딩된 메서드만 호출하자!
 부모클래스명  다형적변수=new 자식클래스명();          // 다형적변수에는 부모클래스와 자식클래스에서
                                                                               // 부모것을 오버라이딩한것만 담을수있음
[ex] 다형적변수가 아닌 기본 형식 1
class A{
      int a=100;
      void m1(){
            System.out.println(200);
      }
}

class B extends A{
      int a=300;
      @Override void m1(){
            System.out.println(400);
      }
      void m2(){
            System.out.println(500);
      }
}

class C{
      public static void main(String args[]){
            A o=new A();
            System.out.println(o.a); // 100
            o.m1(); // 200            //부모A만불렀음
            o.m2(); // 컴파일에러       //부모A만불렀지 자손이 관여할수없음
 }
}


[ex] 다형적변수가 아닌 기본 형식 2
class A{
      int a=100;
      void m1(){
            System.out.println(200);
      }
}

class B extends A{
      int a=300;
      @Override void m1(){
            System.out.println(400);
      }
      void m2(){
            System.out.println(500);
      }
}

class C{
 public static void main(String args[]){
       B o=new B();                       //위와달리 o에 자손을담았기때문에 상속된 부모까지 포함해줌
       System.out.println(o.a);  // 300   //멤버변수 a를 300으로 재할당하였기때문..
       o.m1();                   // 400   //오버라이딩에의해
       o.m2();                   // 500
 }
}

 
[ex] 다형적 변수
class A{
      int a=100;
      void m1(){
            System.out.println(200);
      }
}

class B extends A{
      int a=300;
      @Override void m1(){
            System.out.println(400);
      }
      void m2(){
            System.out.println(500);
      }
}
class C{
 public static void main(String args[]){
       A o=new B();                   // 다형적변수o에는 부모와 + 자식클래스에서 오버라이딩된
                                      // 메서드만 호출할 수 있다.(나머지 자식클래스내용은 부를수없음)
                                      // o = 다형적 변수 
       System.out.println(o.a);  // 100
       o.m1();                   // 400          //자식클래스의 오버라이딩된메서드
       o.m2();                   // 컴파일에러    //자식클래스의 오버라이딩된것 이외의것은 접근할수없음
 }
}

 
[ex] 다형적 변수
class A{
      int a=100;
      void m1(){
            System.out.println(200);
      }
}

class B extends A{
      int a=300;
      @Override void m1(){
            System.out.println(400);
      }
      void m2(){
            System.out.println(500);
      }
}
class C{
 public static void main(String args[]){
       B o1=new B();
       A o2=o1;                     // 결국 A o2=new B(); 이기때문에  o2.m2()는 오버라이딩된것이
                                    // 아니기때문에 부를수없음
                                    // o2를 다형적변수라고함!!
       o1.m2(); // 500
       o2.m2(); // 컴파일에러
 }
}





# 형변환
1 수치형간의 형변환
2 참조형간의 형변환

[ex]
class A{
 void m1(){
       System.out.println(100);
 }
}

class B extends A{
 void m1(){
       System.out.println(200);
 }
 void m2(){
       System.out.println(300);
 }
}
class C{
 public static void main(String args[]){
  A o=new A();
  o.m1();        //100
  o.m2();        // 컴파일에러
  B o2=(B)o;     // 실행에러 ClassCastException         
                 // o를 B로 형변환하였기에 컴파일에러는안남..하지만 new A()에의해
                 // 동그라미안에 A()밖에없어서
  o2.m2();
 }
}

 
[ex]
class A{
 void m1(){
       System.out.println(100);
 }
}

class B extends A{
 void m1(){
       System.out.println(200);
 }
 void m2(){
       System.out.println(300);
 }
}

class C{
 public static void main(String args[]){
      A o=new B();
      o.m1();            // 오버라이딩은 가능
      o.m2();            // 컴파일에러
      B o2=(B)o;         // 위 예제랑 비교
      o2.m2();           // 형변환을 통해 m2()메서드를 부를수있음!! (원래 new B()에
                         // 의해 동그라미안에 담아놔서)
 }
}
[an]  200  300
 
[ex] 아래 소스코드를 융통성있는 소스코드로 바꾸시오.
class Animal{

}

class Dog extends Animal{
     void sound(){
           System.out.println("멍멍");
     }
}

class Cat extends Animal{
     void sound(){
            System.out.println("야옹");
      }
}

class SoundTest{
     void test(Dog a){
           a.sound();
     }
     void test(Cat a){
           a.sound();
     }
}

class A{
 public static void main(String args[]){
       Dog dog=new Dog();
       Cat cat=new Cat();
       SoundTest st=new SoundTest();
       st.test(dog);
       st.test(cat);
 }
}

???
// 1. SoundTest클래스에 중복된부분을 하나로 통일해준다 => Dog a 와 Cat a는 부모클래스Animal로 표현 
// 2. 부모Animal클래스로 자식을 부를려면 오버라이딩해야함 그래서
    부모클래스에 빈껍데기 void sound(){}를 만들어줌 
// 3. 그리고는 부모와 자식클래스의 관계에서 void sound()메서드를 오버라이딩해야함 
// 즉, 부모클래스를 호출하는메서드로 바꾸고 찾아가보면 자식이 오버라이딩된 메서드를 실행하게 변경
???
 
[an]
class Animal{
       void sound(){}
}
class Dog extends Animal{
     void sound(){
       System.out.println("멍멍");
     } 
}
class Cat extends Animal{
     void sound(){
       System.out.println("야옹");
     } 
}
class SoundTest{
     void test(Animal a){
           a.sound();                                    // a는 다형적변수!!
     }
}
class A{
 public static void main(String args[]){
       Dog dog=new Dog();
       Cat cat=new Cat();
       SoundTest st=new SoundTest();
       st.test(dog);
       st.test(cat);
 }
}
 

#객체지향언어 : 좀더 인간적인 관점의 언어...
1.상속
2.다형성.
3.완전캡슐화





# this(),super() 관련 복습문제
[ex 1 ] 컴파일에러를 해결하시오.
class A{
 A(B o){
  System.out.println(o.a);
 }
}
class B{
 String a="aaa";
}
class C extends A{

}

[an1]
class A{
 A(B o){
  System.out.println(o.a);
 }
 A(){}
}
class B{
 String a="aaa";
}
class C extends A{ 
 
}

[an2]
class A{
 A(B o){
  System.out.println(o.a);
 }
}
class B{
 String a="aaa";
}
class C extends A{
 C(){
  super(new B());
 }
}

[an3]???????????
class A{
 A(B o){
  System.out.println(o.a);
 }
}
class B{
 String a="aaa";
}
class C extends A{
 C(B o){
  super(o);
 }
}


[ex 2 ] 컴파일에러를 해결하시오.
/*
package java.lang;
public class Object{
 public String toString(){
 }
}
package java.awt;
public class Dialog{
 public Dialog(Frame f){
 }
}

package java.awt;
public class Frame{
 public Frame(){
 }
}
*/
import java.awt.*;
class A extends Dialog{

}

[an1]
import java.awt.*;
class A extends Dialog{
 A(){
  super(new Frame());
 }
}
[an2]
import java.awt.Dialog;
import java.awt.Frame;
class A extends Dialog{
 A(Frame f){
  super(f);
 }
}
 


# 다형적변수 복습 연습문제

[ex] 다형적변수 o로 오버라이딩되지 않은 메서드m을 호출하려면?
class A{
 void m(){
    System.out.println("aaa");
 }
}
class B{
 public static void main(String args[]){
    Object o=new A();
    o.m(); // 컴파일에러
 }
}

[an 1]
class A{
 void m(){
  System.out.println("aaa");
 }
class B{
 public static void main(String args[]){
  Object o=new A();
  A o2=(A)o;                 //형변환으로 다형적변수를 그냥 A객체변수로 변환                                 
  o2.m(); 
 }
}

[an 2]
class A{
 void m(){
  System.out.println("aaa");
 }
class B{
 public static void main(String args[]){
  Object o=new A();                                        
  ((A)o).m(); 
 }
}
 

[ex] 형변환은 상속관계일때만 가능하다
class A{}
class B extends A{}
class C{
 public static void main(String args[]){
  A o=new B();
  C o2=(C)o; // 컴파일에러
 }
}


[ex] ClassCastException 실행에러
class A{}
class B extends A{}
class C extends A{
 public static void main(String args[]){
  A o=new B();
  C o2=(C)o; // ClassCastException 실행에러
 }
}


# instanceof연산자 : 자료형검사하기( 기본형은안되나??? 참조형만되나?? )
  >> 객체  instanceof   클래스명 
[ex]
class A{
}
class B extends A{
}
class C extends A{
}
class D{
 public static void main(String args[]){
  A o=new B();
  System.out.println(o instanceof B); // true
  System.out.println(o instanceof C); // false
  System.out.println(o instanceof A); // true
  //System.out.println(o instanceof D);
 }
}

 
[ex]
class A{
}

class B extends A{
 void m(){
  System.out.println(100);
 }
}

class C extends A{
 void m(){
  System.out.println(200);
 }
}

class D{
 void test(A o){
  B o2=(B)o;                //B클래스형으로 형변환
  o2.m();
 }
}

class E{
 public static void main(String args[]){
  B o1=new B();
  C o2=new C();

  D d=new D();
  d.test(o1);          //100
  d.test(o2);          //ClassCastException오류
 }
}

 
[ex] 100과 200이 출력될 수 있도록 소스코드를 완성하시오.
class A{
}

class B extends A{
 void m(){
  System.out.println(100);
 }
}

class C extends A{
 void m(){
  System.out.println(200);
 }
}

class D{
 void test(A o){
  if( //here  ){
   B o2=(B)o;
   o2.m();
  }else{
   C o3=(C)o;
   o3.m();
  }
 }
}

class E{
 public static void main(String args[]){
  B o1=new B();
  C o2=new C();

  D d=new D();
  d.test(o1);
  d.test(o2);
 }
}

[an] o instanceof B