2022. 10. 5. 14:53ㆍDev.Program/Java & Spring
p260
- 형변환을 처리하다가 java.lang.ClassCastException을 발생
- ⇒ 뭔가 해선 안되는 변환을 했다고 알려주는 오류!
< instanceof 연산자 >
- 좌변의 객체(참조변수)가 우변 클래스의 타입인지 판별하는 연산자
- (=실제 메모리에 있는 객체가 특정클래스 타입인지를 boolean 타입으로 리턴)
- 판별 결과가 true 이면 형변환이 가능한 관계(업캐스팅 또는 다운캐스팅)
- 판별 결과가 false 이면 절대로 형변환 불가능
- 형변환을 바로 수행하지 않고, instanceof 연산자를 통해 검사 후 수행하는게 안전하다
< 기본 문법 >
if(A instanceof B) {}
⇒ A 는 참조변수, B 는 클래스명
======== 오늘날짜 프로젝트 만들고 Ex.java 만들기
- in 까지만 치고 ctrl + space 누르면 자동완성
- 오류! 뒤에는 변수명 아니고 클래스명 (A is a B 생각해보기)
- 기본 문법 [참조변수 instanceof 클래스명]
- instance of 아니고 instanceof(띄어쓰기X) 입니다(자주하는 실수!! 특히 필기시험!!!!)
- c is a Parent? 질문과 동일
- 이건 아니다! 가 떴으니까 변환하면 오류난다는 것!
class HandPhone {
String number;
String model;
public HandPhone() {}
public HandPhone(String number, String model) {
this.number = number;
this.model = model;
}
public void call() {
System.out.println("전화 기능!");
}
public void sms() {
System.out.println("문자 기능!");
}
}
class SmartPhone extends HandPhone {
String osName;
→ 이 자리에서 Alt + Shift + S → O
public SmartPhone(String number, String model, String osName) {
super(number, model);
this.osName = osName;
}
→ 그럼 이 부분 자동 생성됨
public void kakaoTalk() {
System.out.println("카톡 기능!");
}
}
if(sp instanceof HandPhone) { // sp는 HandPhone 입니까?
System.out.println("sp는 HandPhone 이다!");
System.out.println("그러므로 sp 는 HandPhone 으로 형변환이 가능하다!");
HandPhone hp = sp;
} else {
System.out.println("sp는 HandPhone이 아니다!");
}
- 업캐스팅, 자동형변환(=묵시적 형변환)이 일어남.
- 스마트 폰 고유의 기능은 못쓴다!
문제 ) hp 는 SmartPhone 입니까? 만들어보기.
if(hp instanceof SmartPhone) {
System.out.println("hp는 SmartPhone 이다!");
} else {
System.out.println("hp는 SmartPhone이 아니다!");
}
- 출력창
이렇게 가능 한 경우가 딱 한가지 있었다! (업캐스팅 후 다운캐스팅 하기)
HandPhone hp2 = new SmartPhone("010-1111-2222", "갤럭시S9", "안드로이드");
업캐스팅 수행
문제 ) hp2 는 SmartPhone 입니까? 다시 물어보기.
if(hp2 instanceof SmartPhone) {
System.out.println("hp2 는 SmartPhone 이다!");
} else {
System.out.println("hp2는 SmartPhone이 아니다!");
}
- 출력창
- 위랑 질문이 똑같은데 스마트폰이라고 출력됨(true 출력)
- 그러므로 hp2 는 SmartPhone 으로 형변환 가능!
⇒ 그런데 적으면 오류남. Why? 자동 형변환이 지원 안되기 때문.
⇒ 강제 형변환이 필요하다
- 원래의 모든 기능들 다 사용 가능.
p.261
======== Ex2.java 만들기
p.264
< 동적 바인딩 >
- 상속 관계에서 업캐스팅 후 메서드를 실행할 때 컴파일(번역) 단계에서의 실행 대상과, 실행 단계에서의 실행 대상이 달라지는 것
- 참조 변수의 타입과 무관하게 실제 인스턴스의 메서드를 실행하는 것
- 단, 멤버변수를 사용할 때에는 참조변수 타입에 따라 접근되는 변수가 달라짐
Ex.java 에서 Parent, Child 긁어오기 (2로 만들기)
> Child2 클래스 안에 오버라이딩 자동으로 시켜보기
@Override
public void parentPrn() {
System.out.println("서브클래스에서 오버라이딩 된 ParentPrn()");
}
- Alt + Shift + S → V (오버라이딩 자동완성)
- p.parentPrn(); 만 보면 슈퍼클래스의 parentPrn()만 안다.
- 번역하는 시점에선모름. 실제 실행하는 시점에서 아는거
- ⇒ 이 걸 동적 바인딩이라고 부름
- ⇒ Parent2 타입이기 때문에 Child2꺼 안보임
- → 실행하는 시점이 되어서야 Parent2가 아니라 Child2꺼라는걸 알게 되서 출력창에선 Child2 의 parentPrn()을 실행시켜줌.
p.263 (3) - p.264
> 동적 바인딩은 메서드()에만 해당
- Child2 의 String name = "Child2"; 인데 Parent2 가 나옴. (동적 바인딩 X)
- 변수는 말 그대로 변할 수 있는 값! 굳이 부모의 변수명을 똑같이 가져 올 필요는 없다.
- → 메서드()는 실제 인스턴스에 따라 달라짐
- → 멤버변수는 참조변수 타입에 따라 달라짐
======== Ex3.java 만들기
다형성 얘기 하다 말아서 마저….ㅎㅎ
p.254 다형성
< 다형성 >
- 상속은 기본 전제
- 하나의 참조변수로 여러 인스턴스를 참조할 수 있는 특성
- 인스턴스를 업캐스팅 하여 슈퍼클래스 타입으로 서브클래스의 멤버를 다루는 것
- 독립적으로 만들어진 애들( 밑에 print()나 design() ) 은 사용 못함 ⇒ 단점
- → 그러나 다시 다운캐스팅 해서 쓸 수는 있다
- 업캐스팅 왜 하는지, 다형성 왜 쓰는지 ? 코드의 통일성을 위해서! (장점)
class Shape {
public void draw() {
System.out.println("도형 그리기!");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("원 그리기!");
}
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("사각형 그리기!");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("삼각형 그리기!");
}
}
public void paint() {
System.out.println("원 그리기(paint)!");
}
- class Circle extends Shape{} 에 추가
public void design() {
System.out.println("사각형 그리기(design)!");
}
- class Rectangle extends Shape{} 에 추가
> 슈퍼클래스의 메서드를 상속받아 오버라이딩을 할 경우 코드의 통일성이 향상되어 오버라이딩을 통해 draw(); 이름을 똑같이 만들어준다.
그런데,
c.draw();
r.draw();
t.draw();
이렇게 하는 것 보다 더 통일성을 줄 수 있다!
코드의 통일성을 더욱 향상시키기 위해 업캐스팅 활용
⇒ Circle과 Rectangle과 Triangle의 공통 슈퍼클래스인 Shape 클래스 타입 활용
Shape s = c;
s.draw();
s = r;
s.draw();
s = t;
s.draw();
이렇게 가능.
근데 s.print(); 나 s.design(); 은 가능할까? No.
- 오류! 부모가 이 메서드를 모름!
그래서 오버라이딩을 시킨다! (오버라이딩 하는 이유!)
> 다형성을 배열에 적용시키는 경우
Shape[] sArr = new Shape[3];
sArr[0] = new Circle(); // Circle → Shape 업캐스팅
sArr[1] = new Rectangle(); // Rectangle → Shape 업캐스팅
sArr[2] = new Triangle(); // Triangle → Shape 업캐스팅
- 원래 배열을 생성하려면 이렇게 각각 생성해야하는데
- 한번에 배열에 초기화 시키기!
- 이 자체가 업캐스팅이 수행된 것.
- 한번에 실행할 수 있다!
> 메서드에 다형성 활용
- 이게 한 번에 수행되려면 물음표 안에 뭐가 들어가야 할까?
polymorphism(c); // Circle → Shape
polymorphism(r); // Rectangle → Shape
polymorphism(t); // Triangle → Shape
}
public static void polymorphism(Shape s) {
// 메서드 호출 시 업캐스팅 일어남
s.draw();
}
- Shape s 만 넣어주면 한번에 오류 없어짐!
⇒ 뒷 부분에 추상클래스까지 배우면 완벽한 코드의 통일성을 쓸 수 있다!!!
p.182 3.3
======== Ex4.java
class StaticMember {
int a = 10;
int b = 20;
}
- 출력창 보면 s1.a 랑 s1.b 만 바뀜!
class StaticMember {
static int a = 10;
int b = 20;
}
- 앞에 static 써주면 a 기울어짐!
⇒ int a 앞에 static만 붙여줌! (차이)
- s1.a 값만 바꾼건데 s2.a 값까지 같이 바뀜(출력창) ⇒ static 변수이기 때문
- 정적(static) 변수 = 모든 인스턴스에서 공유하는 멤버변수
- StaticMember.a 로 접근하라고 경고창 띄워줌 (실행하면서 오류는 안남)
- ⇒ 정석대로 사용하는 방법(결과는 같음)
- 참조 변수 선언 전에 접근 불가
- 일반 멤버변수는 반드시 인스턴스 생성 후 참조변수를 통해서만 접근이 가능
- 근데 얘는 된다!
- static 멤버변수의 경우 클래스명만으로 인스턴스 생성과 상관없이 접근이 가능
★ < 자바 프로그램 실행 과정 > ★
0. 소스 코드 작성 및 컴파일(번역) 후 클래스 실행
1. 클래스 로딩 ⇒ static 변수 및 메서드가 메모리에 로딩됨
2. main() 메서드 실행 (자동 실행)
3. 인스턴스 생성 ⇒ 인스턴스 변수 및 메서드가 메모리에 로딩됨
4. (인스턴스 내의) 메서드 호출(실행) ⇒ 메서드 내의 로컬 변수가 메모리에 로딩됨
5. 결과 출력됨
System.out.println("StaticMember.a : " + StaticMember.a);
⇒ 그래서 바로 위의 이 문장이 오류가 안난거
인스턴스 생성을 하지 않더라도 접근 가능! “ 1. ” 에서 static 변수가 메모리에 로딩되기 때문.
- 우리는 항상 3번부터 시작했었다! ( 오늘 배운 static 을 배우기 전까지는 )
< static 키워드 >
- 클래스, 메서드, 변수의 지정자로 사용
- 메서드 또는 변수에 static 키워드를 사용할 경우 인스턴스 생성과 상관없이 클래스가 로딩되는 시점에 함께 메모리에 로딩됨
- ⇒ 따라서, 참조변수 없이 클래스명만으로 해당 멤버에 접근 가능
< 기본 문법 >
클래스명.멤버변수
또는
클래스명.메서드()
⇒ 이 시점에선 참조변수가 없기 때문에 클래스명. 을 사용
(참조변수가 있을 수도 있지만 클래스명. 을 사용하는게 좋음!)
< static 변수 >
- 인스턴스 생성 전, 클래스가 메모리에 로딩될 때 static 변수도 함께 로딩됨
- 참조변수 없이 클래스명만으로 해당 멤버에 접근 가능
- 멤버변수에 static 키워드를 사용할 경우 클래스 변수(정적 변수)로 취급되며 모든 인스턴스가 하나의 변수를 공유함(클래스 당 하나만 생성됨)
- 로컬변수가 만들어지는 시점 : 4. 메서드 호출()
- 없어지는 시점 : 메서드가 끝나는 시점
- 인스턴스변수가 만들어지는 시점 : 3. new 할 때!
- 없어지는 시점 : 인스턴스가 끝나는 시점
- static 변수가 만들어지는 시점 : class 가 시작될때
- 없어지는 시점 : class 가 끝날때 (=프로그램 종료)
p. 192
< Ex4.java >
자신의 클래스 내의 메서드에서 static 변수나 인스턴스 변수 접근 방법 동일
'Dev.Program > Java & Spring' 카테고리의 다른 글
[Java] 싱글톤 디자인 패턴(Singleton Design Pattern) / final 키워드 (0) | 2022.10.05 |
---|---|
[Java] static (0) | 2022.10.05 |
[Java] 형변환(Type Casting) - 업캐스팅/다운캐스팅 (0) | 2022.10.05 |
[Java] 메서드 오버라이딩(Overriding) (1) | 2022.10.05 |
[Java] 상속(Inheritance) (1) | 2022.10.05 |