2020.11.01 생활코딩 유투브 공부 ( 모든 출처 : 유투버 생활코딩 ) 133 강 ~



Object : 모든 클래스의 조상 


package ~~ 


class O {} 

는 사실 class O extens Object {} 이다. ( 자바안에서 비록 우리에게 눈으로 안보여도) 

공통적인 기능들을 Object 클래스에 구현해놓았다. 


Object 클래스 ( 2/5 ) : toString

toString () 메소드   : 문자화 하는것 


c1.toString()  

자바는 내부적으로 toString 이라는 메소드를 호출 ( 문자화 ) 


부모클래스 Object 는 모든 클래스의 상위클래스인데 Object 에 있는 toString을 overriding 을 통해서 사용을 변경할 수 있다. 




Object 클래스 ( 3/5 ) : equals  


class Student { 

    String name ; 

    Student ( String name ) { 

    this.name = name ; 

    } 

    //오버라이딩중 

    public boolean equals ( Object obj ) {  //데이터 타입이 Object 이고 밑에서 obj 로 오려고 하는 그 s2 는 Student 타입이다. -> Student 의 부모가 Object 이다. 

        Student s = (Student) obj ; 

       return this.name = s.name ; 

     } 

******중요********* 

**Object obj = s2 ( 데이터타입은 Student ) 즉 자식데이터타입을 부모데이터타입을 가지고 있는 변수에 할당하려고함 ( 다형성  -> 자식 데이터 타입은 부모 데이터 타입에 할당 될 수 있다. )  그렇게 되면 Object에는 존재하지 않고 자식인 s2 ( Student 타입 ) 만 가지고 있는 name 이라는 인스턴스 변수에 접근을 할 수 없다. ( 다형성에서 배웠잖아  )  따라서 Object 타입을 -> Student 타입으로 다시 변환시켜야 할 필요가 있다...

    Student s =obj;  전환할 수 없다 (그냥은 불가능 )  ( Object obj = s2 가능 . 부모가 더 크니까 )   --> Student s = (Student)obj 이렇게 써야한다.( 중요 :  즉 자식이 부모로 변환은 가능하지만 부모가 자식으로 되려면 강제로 명시적으로 형변환을 해야하지만 형변환이 되는... 정책을 java 가 가지고 있다. 

 

-- 완벽하게 동일하게 하려면 Object 클래스의 메소드중 하나인  hashCode() 까지 함께 구현해서 오버라이딩해되 ! . (심화) 


class ObjectDemo { 

    public static void main ( String [][ args  { 

        Student s1 = new Student ( "egoing " ) ; 

        Student s2 = new Student ( "egoing " ) ; 

        System.out.println ( s1 == s2 ) ;  false

        System.out.println ( s1.equals(s2) ) ;  false 

    }

//name 이라는 애가 같다면 s1 과 s2 가 같다고 할 수 있도록 equals를 오버라이딩해서  만들 수 있다. 


}



Object 클래스 ( 4/5 ) : finalize 

여러가지이유로 사용을 만류하고 있다.  

finalize 는 객체가 소멸될 때 호출되기로 약속된 메서드 


원시 데이터형 ( byte, short, int , long , float , double, boolean, char ) 를 사용할 때는 비교연산자 == 를 쓰고 , String 이나 객체를 비교할 때는 equals 를 사용한다. 


-toString 가급적 구현하기를 권장한다. 

-equals 를 기본적으로 사용하는 것이 권장된다. 


가비지 컬렉션 (garbage colletion )  인스턴스를 만드는 것은 내부적으로는 컴퓨터의 메모리를 사용하는 것이다. 메모리는 RAM 

프로그램은 RAM (아주빠른) 에 올라온 상태로 실행된다. 

좋은 애플리케이션은 RAM을 작게 사용하고 파워풀하게 기능해야 한다. 


자바는 아주 제한적으로 제공을 한다. ( 램을 관리하는 작업을 자바에서는 자동화시켰다. -> 가비지 컬렉션 ) 

변수를 사용하는 곳이 더이상 없다면 이 변수와 변수에 담겨 있는 인스턴스는 더 이상 메모리에 머물고 있을 필요가 없다. 자바는 이를 감지 -> 자동으로 쓰지 않은 데이터를 삭제 



Object 클래스 ( 5/5 ) : colone 


복제 하는 역할 


class  Student implements Cloneable

    String name 

    Student ( String name )  { 

        this.name = name ; 

    }  

    public Object clone() throws CloneNotSupportedException

        return super.clone() ; 

        }  

        ** clone 에 들어가 보면 protected Object clone() 

                                            throws CloneNotSupportedException

                        이렇게 되어 있다. 즉 RuntimeExceptin 이 아니라 그냥 exception 이라서                         반드시 처리를 해야한다.  throws CloneNotSupportedException 써줘야함

        

public class ObjectDem { 


    public static void main ( String [] args ) { 

        Student s1 = new Student ( "egoing"  ) ;

        s1.clone () ;  --> 에러가 난다. : Student 라는 클래스를 복제를 하려면 Student 클래                                    스가 복제가능한 클래스라고 자바 버추얼머신에 알려줘야 한다.(위)

         Cloneable 은 비어있다 . 비어있는 인터페이스를 구현 단지 Student 클래스가 복제가            능한 클래스라고 알려주기 위한 구분자의 역할                  

         class 에서 implements Cloneable 를 해줬는데도 오류가 계속 있다. (파랑) 

                    

         clone() 은 protected Object 이다. (public 이 아니다 )  -> protected 는 같은 패키지. 

        Object 는 java.lang 패키지에 속해 있다. ( 다른 패키지 ) 

        접근제어자가 public 이기 때문에Object 안에 있는 애들을 호출 할 수 이썼다. 


        (파랑 다음 ) -> 사용하는 쪽에서 throws 할건지 해결할건지 결정 해야함. 

        -->> try { 

                    Student s2 = (Student)s1.clone () ;      명시적형변환 필요 

                  

                  } catch ( CloneNoteSupportedException e ) { 

                        e.printStackTrace() ; 

                }

        }



어려우면 다시 한번 봐 : https://www.youtube.com/watch?v=g7zFI2Mr_Xc&list=PLuHgQVnccGMCeAy-2-llhw3nWoQKUvQck&index=137&ab_channel=%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9 


상수와 enum ( 1/4 ) : 상수에 대한 복습 

상수 2 - enum 

interface FRUIT { 

    int APPLE = 1 , PEACH = 2 , BANANA = 3 ;   // 인터페이스를 통해서 이름이 충돌할 가능성이 없어져서  접두사를 붙일 필요가 없다.

}

interface COMPANY { 

    int GOOGLE = 1, APPLE =2, ORACLE = 3 ; 

}


pubic class ConstantDemo { 

/*    public final static int APLLE = 1; 

    public final static int PEACH = 2; 

    ublic final static int BANANA = 3; 


    private final static int  COMPANY_GOOGLE = 1;  

    private final static int COMPANY_APPLE = 2; //APPLE 을 두번 쓸 수 있어서 접두사붙여줌

    private final static int COMPANY_ORACLE = 3; 

                    */


    public static void main ( String [] args ) { 

        

        if ( FRUIT.APPLE == COMPANY.APPLE) { 

            System.out.println("과일애플과 기업애플은 같습니다." ) 

           }   --> 컴파일오류가 나지 않지만 오류다 FRUIT.APPLE , COMPANY.APPLE 두개는                        모두 int 타입이라서 오류가 나지 않는데,  하나는 String 타입이었다면 

                    컴파일 단계부터 막혔겠지. 그런데 실상은 두개는 다른것이기 때문에 문제 

        int type = FRUIT.APPLE; 

        switch(type) { 

            case FRUIT.APPLE : 

                System.out.pritnl ( 57 + "kcal " ) ; 

                break; 

            case FRUIT.PEACH : 

                 System.out.println(34 + "kcal " ) ; 

                 break; 

            case FRUIT.BANANA : 

                System.out.println(93+"kcal" ) ; 

                break; 

        }




------------------------------> 위에 있는 녹색 문제 해결하기 서로 다른 애니까 컴파일에러 나게 하기 


class Fruit { 

    public static final Fruit  APPLE = new Fruit();    //인스턴스화 

    public static final Fruit  PEACH = new Fruit();  

    public static final Fruit  BANANA = new Fruit();  

      // APPLE , PEACH , BANANA 모두 다른 인스턴스이기 때문에 모두 다름 ( 데이터타입은 Fruit 로 같지만... ) 

}

class Company { 

    public static final Company  GOOGLE = new Company();    //인스턴스화 

    public static final Company  APPLE = new Company();  

    public static final Company  ORACLE = new Company();  

}


pubic class ConstantDemo { 


    public static void main ( String [] args ) { 

       if ( Fruit.APPLE == Company.APPL ) {  //컴파일에러가 뜸 

        데이터타입이 하나는 Fruit 하나는 Company 이기 때문에 

            System.out.println( "과일 애플과 회사 애플이 같다. ) 

        }

     int type = Fruit.APPLE; 

        switch(type) { 

            case Fruit.APPLE : 

                System.out.pritnl ( 57 + "kcal " ) ; 

                break; 

            case Fruit.PEACH : 

                 System.out.println(34 + "kcal " ) ; 

                 break; 

            case Fruit.BANANA : 

                System.out.println(93+"kcal" ) ; 

                break; 

        }



switch 문에 들어가는 조건이 제한적 데이터타입만을 사용할 수 있다. 

byte, short, char, in, enum , String , Character, Byte, Short  , Integer 

그런데 위에 예시로 든것은 class 타입으로 만든 상수를 switch 에서 사용불가. if 문에서는 사용 가능 

-----> 해결책 :  enum 사용하자 



상수와 enum ( 3/4)  : enum 의 문법 

enum 은 열거형 ( enumerated type ) 이라고 부른다 열거형은 서로 연관된 상수들의 집합이라고 할 수 있다. 


class   Fruit { 

    public static final Fruit APPLE = new Fruit(); 

     public static final Fruit PEACH = new Fruit(); 

     public static final Fruit BANANA = new Fruit(); 


}


                == 둘이 동일하다 


enum Fruit {   //Fruit 은 클래스다 . 위에 있는거랑똑같은 코드다.  

    APPLE , PEACH, BANANA 

}


public class ConstantDmo { 


    public static void main ( String[] args ) { 

        Fruit type = Fruit.APPLE; 

        switch ( type ) { 

            case APPLE :   // 앞에 Fruit 를 써주지 않아도 자바가 안다.  

            System.out.println( 57 + " kcal" )  ;

            break; 

        } 

    }

이 가능하다. 


기능 

코드가 단순해진다

인스턴스의 생성과 상속을 방지한다. 

enum 을 사용하는 Fruit 는 열거를 위한 목적을 알 수 있다. (구현의 의도) 



상수와 enum ( 4/4 ) : 열거형의 활용 


enum 은 사실상 class 따라서 생성자를 가질 수 있다. 

    public static final Fruit APPLE = new Fruit(); 

     public static final Fruit PEACH = new Fruit(); 

     public static final Fruit BANANA = new Fruit(); 


밑에 있는 것과 위에있는 거는 동일한것. 


enum Fruit { 

    APPLE("red"), PEACH("pink"), BANANA("yellow") ;   ( 인스턴스화한것 ) 

     Private String color;  //public 보다는 Private 으로 해서 직접 변하게하지 않게 (사용자들이) 

     public String getColor () { 

            return this.color ; 

    }                  

        Fruit(String color) {  // 컬러에 위에 있는 red , pink , yellow 가 들어가는것 

  // 생성자 -> 인스턴스(new)하면 생성자를 호출한다. -> 밑에가 실행이 되는데 여기서는 출력하는것을 적어놓은것 . 근데 위에 있는 보라부분이랑 위에 파랑부분이 동일하다고 했으니까.  세번 생성자를 호출한게 된다 

        System.out.println("Call Constructor " + this ); // ( this 는  APPLE, PEACH , BANANA 가 차례대로출력 )  

        this.color = color ( 전역변수 호출 ) 

        

    }

}


--> 상수가 3개인 경우에는 Call Constructor 가 3번 출력이 된다. 


Main 에 


Fruit type = Fruit.APPLE ; 

switch(type ) { 

    case APPLE : 

        System.out.println(57 + "kcal, color " + Fruit.Apple.getColor ) : 

        break; 



결론 : enum 은 그 필드안에 변수, 메소드 등도 다 들어갈 수 있는 클래스 같은것. 


values() 메소드 


public class ConstantDemo {

main ~ {

    for(Fruit f : Fruit.values() ) { 

        System.out.println(f); 

    } 

 }

}

열거형이 가지고 있는 상수들을 담은 배열들을 가지고 올 수 있어서 그 상수들을 하나하나 꺼내서 가지고 올 수 있다. 

배열처럼 상수들을 하나하나 꺼내서 처리할 수 있는 기능도 제공 ( values() 메소드)





댓글