-
221210. 자바5 (클래스 형변환)스타터스 백엔드 3기 2022. 12. 13. 14:14
하루입니다.
StaticImportTest, BookMgr, SalaryTest, CastingTest, CastingTest2
복습!
생성자란?
- 객체 특성을 표현하는 게 아님.
- 클래스를 정의한 후, 객체를 생성하는 시점에서 수행해야 할 문장들을 정의한 것이다.
- 생성자는 객체가 생성될 때 생성되기에, new 뒤에 적혀야 한다. 메소드 호출하듯 적을 수는 없다.
- 클래스명과 같다.
- 메소드와 유사한 구조를 가지고 있다.
메소드 생성자 [modifier] 리턴타입 메소드이름 (매개변수) {
{
내용
}
}[modifier]메소드이름 (매개변수) {
{
객체 생성을 수행하는 문장
객체 변수들을 메모리에서 초기화하는 문장
}
}this
- 자신 객체를 의미하는 자바 키워드이다.
- super도 문장 처음에 와야 하기 때문에, 생성자의 경우 동시에 올 수 없다.
사용법 1. 현재 객체에 포함된 변수와 지역변수(매개변수)의 이름이 같은 경우에 구분하기 위해 사용한다.
생성자, 메소드 모두 사용 가능
사용법 2. this([매개변수]) : 현재 객체의 다른 생성자를 호출하는 용도이다.
생성자 내부의 첫 문장에 사용되어야 한다.
패키지 (캡슐화)
변수와 메소드를 묶어 클래스, 클래스들을 묶어 폴더를 만든다.
접근제어자
class 변수 메소드 생성자 public O O O O 모든 자바 클래스에서 사용 가능하다. protected 현재 패키지의 다른 클래스들 사용 가능하다 + 다른 패키지의 자식 클래스 사용 가능하다. no modifier
(default)O O O O 현재 패키지 안의 다른 클래스들은 사용 가능하다. private X O O O 현재 자바 클래스 안에서만 사용 가능하다. 상속
- 기존의 클래스 정의 후에 새로운 클래스 정의시 기존 클래스에 정의된 변수 + 메소드를 필요로 할 때 상속을 사용한다.
- 위의 상태이며 is - a 관계라면 상속받는다.
- 위의 상태이며 has - a 관계라면 객체를 생성한다. 클래스 내부에 객체를 가진다는 뜻이다.
상속의 변수
- 부모 클래스의 변수는 자식 클래스에 자동 포함된다.
- 단 private 변수에는 접근 불가능하다.
- 만약 부모 자식 동일 변수가 있다면 자식 클래스가 우선이다.
상속과 메소드 overrideng
- 부모 자식 동일한 이름의 메소드가 존재한다면
- 부모에서 정의한 메소드를 자식이 수정한다.
- 자식의 modifier는 부모보다 같거나 더 넓어야 한다.
- 리턴타입, 이름, 매개변수까지 완전히 동일해야 한다.
- 자식클래스의 overriding한 메소드가 우선된다.
상속과 생성자
- 자식클래스 생성자의 첫 문장은 super( ) 가 자동으로 정의된다.
- 부모클래스 기본 생성자를 호출하는 것이다. 부모객체가 생성되어야 그 안의 데이터를 사용할 수 있기에 자식 객체가 생성될 때 부모 객체도 같이 생성한다.
- super는 나의 부모 객체를 의미하는 키워드이다.
- 1. super.변수명 부모클래스의 변수
- 2. super.메소드명() 부모클래스의 메소드
- 3. super() 자식 클래스에 생성자 첫 문장에 자동으로 호출된다.
- 4. super(매개변수) 부모 클래스에 기본 생성자가 없다면 부모 클래스에서 매개변수가 정의된 다른 생성자를 호출한다. 명시적 정의가 필요하다.
static import
// Math의 noStatic 변수와 static의 변수를 모두 사용 허락한다. import java.lang.Math // Math의 static으로 된 변수와 메소드만 사용을 허락하겠다. import static java.lang.Math.*; // Integer의 static으로 된 변수와 메소드만 사용을 허락하겠다. import static java.lang.Integer.*; public class StaticImportTest { public static void main(String[] args) { // int ran = (int)(Math.random()*100)+1; 원래 이렇게 적어야 하지만 int ran = (int)(random()*100)+1; // static이라서 math 없애도 된다. // random()은 Stitic 메소드임! // public static double random() { } System.out.println(ran); System.out.println(MAX_VALUE); } }자바 실행 과정
- code 검증 - static 변수나 메소드 할당 - main 실행 - 객체 생성 - non-static변수나 메소드 할당
static 변수 1개 공유 - 클래스 영역 - 객체 생성 이전 할당 static 메소드 객체 생성 이전 할당
static 변수만 사용하는 메소드이다.
객체 생성 이전에 호출이 가능하다.non-static 메소드 static 변수 + non-static변수도 모두 사용하는 메소드이다. final
final 변수 변수갑 수정이 불가하다.
상수이다.final 메소드 메소드 구현부 수정이 불가하다.
메소드의 overriding이 불가하다.final 클래스 클래스 수정 불가하다.
상속 후 자식 클래스에서 모든 메소드의 overriding이 불가하다.
상속이 불가하다.
모든 메소드에 final을 붙인 것과 같은 의미이다.
사용하고 싶다면 객체를 생성해서 사용해야 한다.
사용하는 경우
0. 프로젝트를 할 때, 공통으로 사용하는 변경 금지인 클래스를 약속할 때 사용한다.
1. 절대불변의 진리값을 표현하는 경우
2. 아래의 경우class 수학공식 {
제곱();
제곱근();
final 근의 공식();
}class MyClass extends 수학공식 {
@override
근의 공식( ) { } // 오류이다.
}final class 수학공식 {
제곱();
제곱근();
근의 공식();
}class MyClass extends 수학공식 {
// class가 final이라 extends 받는 거 자체가 오류이다.
}
다형성.
내가 제일 좋아하는 다형성!!!
객체지향 언어의 조건
1. 캡슐화 / 정보은닉
2. 상속
3. 다형성 - 이름은 같지만 결과가 다르다.
overload, overroading
A a1 = new A();
A a1 = new AA();
기본형변수의 형변화 규칙을 다시 보자.
1. boolean은 제외
2. (데이터형) 변수 ===> 형변환연산자
자동형변환 규칙
byte - short - int - long - float - double
char - int - long - float - double
참조형변수의 형변화 규칙을 다시 보자.
1. 상속관계여야 한다.
2. 자동형변환 규칙
- 부모클래스 변수명1 = new 자식클래스객체;
- 변수명1.변수 ==> 부모클래스
- 변수명1.메소드() ==> 부모클래스
- 변수명1.overriding 메소드() ==> 자식클래스
- 부모의 메소드를 자식이 재정의했다면, 자식 클래스의 메소드가 우선이다.
3. 명시적(강제) 형변환
- 부모클래스 변수명1 = new 자식클래스객체;
- 자식클래스 변수명2 = (자식클래스명)변수명1;
- 변수명2.변수 ==> 부모클래스 + 자식클래스
- 변수명.메소드() ==> 부모클래스 + 자식클래스
class A { }
class B extends A { }
class C extends A { }
class D extends C { }
class F { }
A a1 = new A(); 형변환 불필요 A a2 = new B(); 자동형변환 가능 A a3 = new C(); 자동형변환 가능 A a4 = new D(); 자동형변환 가능 A a5 = new F(); 자동형변환 error (상속관계 X) B b1 = new C(); 자동형변환 error (상속관계 X) B b2 = new D(); 자동형변환 error (상속관계 X) B b3 = new A(); 자동형변환 error (부모를 자식으로 변환 불가) C c1 = new D(); 자동형변환 가능 C c2 = new C(); 형변환 불필요 class A { int i = 10; }
class B extends A { int j = 20; }
class C extends A { }
class D extends C { }
class F { }A a1 = new A(); 형변환 불필요
a1 . i 가능B b1 = (B) a1; 컴파일 오류 아니다. 실행오류이다. A a2 = new B(); 자동형변환 가능
a2 . i ; 가능 (A 객체로 판단되어 A객체 접근 가능)
a2 . j ; 불가능 (B 객체에 접근 불가능)B b2 = (B) a2; 명시적 형변환 가능. 자식클래스가 부모클래스에 담겼다가, 다시 자식 타입으로 형변환 되는 경우이다.
a2 . i ; 가능 (상속받음)
a2 . j ; 가능자식이 부모에 담겼다가 다시 자식 타입으로 형변환 되는 경우만 명시적 형변환이 가능하다. 자동형변환과 강제형변환의 존재이유
부모클래스
class Tire{ }class Car {
Tire t[] = new Tire[4];
t[0] = new 한국타이어();
t[1] = new 뫄뫄타이어();
t[2] = new 금호타이어();
t[3] = new 한국타이어();
}자식클래스
class 한국타이어 extends Tire{ }
class 금호타이어 extends Tire{ }
class 뫄뫄타이어 extends Tire{ }Test t = new Test();
t,ma(new 한국타이어())
t.ma(new 금호타이어())clss Test {
ma(Tire k) {
}
}상위클래스를 하나 더 두고, 유연하게 사용 가능하도록 한다.
서로 다른 타입의 여러 객체들이 있으면, 그 객체들의 타입을 통일하는 것이다.실습1
class Parent class Child1 extends Parent class Child2 extends Parent Parent p1 = new Parent();
System.out.println(p1.su);
p1.print();Child1 c1 = new Child1();
System.out.println(c1.su);
c1.print();Parent p2 = new Child1();
System.out.println(p2.su);
p2.print();su = 10
p1.print() = 10su = 20
c1.print() = 20su = 10
p2.print() = 20형변환을 했다는 건 앞의 객체를 참조하라는 뜻이다!!! 가리키라는 뜻이다!!! - p1이 만들어졌을때 p1은 10번지를 가리킨다. - parent 객체 먼저 만든다.
- child1 객체 만든다.
- c1은 child 가리킨다.
- child는 parent 가리킨다.- parent 객체 먼저 만든다.
- child1 객체 만든다.
- p2 변수가 parent를 가리킨다.
- parent의 su는 10이니까 syso(p2.su)는 10이다.
- print() 오버라이딩되었기에 child 클래스의 메소드를 사용한다. parent 클래스의 메소드는 감춰진다.
실습2
- p1은 mp() 메소드는 있으나 mc()는 메모리에 존재하지도 않는다.
- c1은 p1에서 mp()를 상속받고, mc()를 가지고 있어 둘 다 사용 가능하다.
- p2는 mc가() 메모리에는 있으나 사용할 수 없다.
- ((Child1)p2).mc(); 이렇게 명시적형변환을 해 주면 사용할 수 있다.

((Child1)p2).mc(); // 명시적형변환instanceof
if(p3 instanceof Child2) { ((Child2)p3).mc2(); } else { System.out.println("p3는 child2으로 형변환 불가"); }public class CastingTest2 { public static void main(String[] args) { Parent array[] = new Parent[3]; // 자동형변환은 여러가지 타입의 객체를 1개 타입으로 통일해서 사용하고 싶어서 사용하는 것이다. array[0] = new Parent(); array[1] = new Child1(); array[2] = new Child2(); for(int i = 0; i < array.length; i++) { System.out.println( array[i].getClass().getName() + ":" + i + "번 인덱스 객체"); array[i].print(); // Child2 객체인 경우에만 mc2를 호출하려고 한다. if(array[i] instanceof Child2) { System.out.println("if문: " + i); ((Child2)array[i]).mc2(); } } } } __________________________________________________________________________________ chap7.Parent:0번 인덱스 객체 10 chap7.Child1:1번 인덱스 객체 20 chap7.Child2:2번 인덱스 객체 40 if문: 2 Child2 클래스
이 코드를 보아라!
package chap7; class Parent { int su = 10; void print() { System.out.println(su); } void mp() { System.out.println("Parent 클래스"); // non-overriding한 메소드이다. } } class Child1 extends Parent { // int su = 10; 부모로부터 상속받은 su = 10;까지 있는 셈이다. int su = 20; void print() { System.out.println(su); // overriding한 메소드이다. } void mc() { System.out.println("Child1 클래스"); // 자식에서 추가한 메소드 } } class Child2 extends Parent { int su = 30; void print() { System.out.println(super.su + su); } void mc2() { System.out.println("Child2 클래스"); // 자식에서 추가한 메소드 } } public class CastingTest { public static void main(String[] args) { Parent p1 = new Parent(); // 형변환 발생 x Child1 c1 = new Child1(); // 형변환 발생 x Parent p2 = new Child1(); // 자동형변환 발생 System.out.println(p1.su); p1.print(); p1.mp(); // p1.mc(); 메모리에 존재하지도 않음 System.out.println(c1.su); c1.print(); c1.mp(); c1.mc(); System.out.println(p2.su); // 자동형변환발생 p2.print(); // 오버라이딩 메소드 - child1 p2.mp(); // 사용메소드 - perent // p2.mc(); 메모리에 있다. 어떻게 볼 수 있을까? if (p2 instanceof Child1) { ((Child1)p2).mc(); } else { System.out.println("p2는 child1으로 형변환 불가"); } ((Child1)p2).mc(); // 명시적 형변환 Parent p3 = new Child2(); // 자동형변환 발생 System.out.println(p3.su); // 사용변수 ㅣ parent p3.print(); // 오버라이딩메소드: child2 p3.mp(); if(p3 instanceof Child2) { ((Child2)p3).mc2(); } else { System.out.println("p3는 child2으로 형변환 불가"); } ((Child2)p3).mc2(); // 아하! 최초에 만들어진 타입으로 명시적 형변환이 가능한데, child2가 아닌 child1으로 변경하려고 해서 오류가 발생했구나@ } }public class CastingTest2 { void setParent(Parent target) { Parent p = target; } public static void main(String[] args) { Parent array[] = new Parent[3]; array[0] = new Parent(); array[1] = new Child1(); array[2] = new Child2(); for(int i = 0; i < array.length; i++) { System.out.println( array[i].getClass().getName() + ":" + i + "번 인덱스 객체"); array[i].print(); // Child2 객체인 경우에만 mc2를 호출하려고 한다. if(array[i] instanceof Child2) { System.out.println("if문: " + i); ((Child2)array[i]).mc2(); } } }형변환이 잘 정리되었다고 생각하는 코드이다.
'스타터스 백엔드 3기' 카테고리의 다른 글
자바의 내부클래스와 익명클래스의 이해 (0) 2022.12.14 221214 자바 7. 인터페이스, 내부클래스, 익명클래스, (0) 2022.12.14 221212. 자바 4 {생성자 (접근제한자, this, super, 상속) } (0) 2022.12.12 유데미 스타터스 취업 부트캠프 3기 - 백엔드 3주차 (0) 2022.12.09 221209. 자바4 (객체지향 프로그래밍, 클래스, 메소드, 변수, static, 오버라이딩, 호출스택) (0) 2022.12.09