[JAVA] 객체지향(생성자/상속/Import)
Categories: JAVA-Learn
📌 개인적인 공간으로 공부를 기록하고 복습하기 위해 사용하는 블로그입니다.
정확하지 않은 정보가 있을 수 있으니 참고바랍니다 :😸
[틀린 내용은 댓글로 남겨주시면 복받으실거에요]
생성자
- 생성자란?
- 인스턴스가 생성될 때마다 호출되는 ‘인스턴스 초기화 메서드’
- 인스턴스 초기화 - 인스턴스 변수에 적절한 값을 저장하는 것.
- 인스턴스 변수의초기화 또는 인스턴스 생성시 수행할 작업에 사용
- 몇가지 조건을 제외하고는 메서드와 같다.
-
모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.
1 2 3 4 5 6 7
Card c= new Card(); 1. 연산자 new에 의해서 메모리(heap)에 Card클래스의 인스턴스가 생성된다 //연산자 new에 의해서 인스턴스가 생성되는 것이지 생성자가 인스턴스 생성하는것이 아님. 2. **생성자 Card()**가 호출되어 수행된다. 3. 연산자 new의 결과로, 생성된 Card 인스턴스 주소가 반환되어 **참조변수 c**에 저장된다.
- 인스턴스가 생성될 때마다 호출되는 ‘인스턴스 초기화 메서드’
- 생성자의 조건
- 생성자의 이름은 클래스의 이름과 같아야 함.
- 생성자는 return 값이 없다. but void를 쓰지 않음.
1 2 3 4 5 6 7 8 9 10 11 12 13
클래스 이름 ( 타입변수명, 타입변수명,....){ //인스턴스 생성시 수행될 코드 //주로 인스턴스 변수의 초기화 코드를적는다. ex) class Card{ ... Card(){//매개 변수가 없는 생성자. //인스턴스 초기화 작업 Card(String Kind, int number) {//매개변수가 있는 생성자 //인스턴스 초기화 작업
- 기본 생성자
-
기본생성자란?
1 2
클래스이름(){} Card(){} //컴파일러에 의해 추가된 Card의 기본 생성자. 내용이 없음.
- 매개변수가 없는 생성자
-
클래스에 생성자가 하나도 없으면 컴파일러가 기본 생성자를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
class Data1{ int value; //생성자 정의 없음. } class Data2{ int value; Data2(int x){ //생성자 1개 정의되어 있음, value=x; } } class ConstructorTest{ public static void main (String[]agrs){ Data1 d1= new Data(); Data2 d2 = new Data2(); //compile error 발생!! } } 왜냐하면 Data1에서는 정의 되어 있는 생성자가 하나도 없어서 컴파일러가 하기와 같이 자동적으로 기본생성자를 추가해줌 class Data1 { int value; Data1(){} //기본생성자 } --- 에러가 발생하지 않도록 하기 위해서는 Data2의 인스턴스를 생성할 때 생성자 Data2(int x)를 사용 또는, 클래스 Data2에 생성자 Data2()를 추가로 정의해 주어야 한다.
- 생성자가 하나라도 있으면 추가하지 않음.
- == 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.
-
매개변수가 있는 생성자
1 2 3 4 5 6 7 8 9 10
class Car{ String color; //색상 String gearType; //변속기 종류-auto, manual int door; //문의 개수 Car(){} //생성자 Car(String c, String g, int d){ //생성자 color = c; gearType=g; door =d ;
ㄱ. 인스턴스 생성 후 인스턴스 값을 변경
1 2 3 4
Car c = new Car(); c.color = "white"; c.gearType = "auto"; c.door = 4;
ㄴ. 매개변수를 갖는 생성자
1
Car c = new Car("white","auto",4);
ㄱ와 ㄴ은 같은 역할을 하는 코드지만 ㄴ이 더 간결하고 직관적.
-
- this() - 생성자, 같은 클래스에서 다른 생성자 호출 하기
- this()생성자 : 같은 클래스의 다른 생성자를 호출할 때 사용, 다른 생성자의 호출은 생성자의 첫 문장에서만 가능.
b. 기존 코드
1 2 3 4 5 6
Car() { color = "white"; gearType = "auto"; door = 4; //지역변수 }
c. this 사용 >코드의 재사용성을 높인 코드
1 2 3 4
Car(){ this("white","auto",4); }
d. this는 인스턴스 자신을 가리키는 참조변수, 모든 인스턴스 변수에 숨겨진 채로 존재
- this(), this(매개변수)와는 완전히 다름.
변수의 초기화
- 변수의 초기화
- 변수를 선언하고 처음으로 값을 저장하는 것.
- 멤버변수(인스턴스변수, 클래스변수)와 배열은 각 타입의 기본 값으로 자동 초기화되므로 초기화를 생략 할 수 있다.
- 지역변수는 사용 전에 꼭!!!!!!! 초기화를 해주어야 한다
- 멤버 변수의 초기화
-
명시적 초기화-변수 선언과 동시에 초기화
1 2 3 4 5 6
class Car { int door = 4; //기본형 변수의 초기화 Engine e = new Engine(); //참조형 변수의 초기화 //.... }
-
생성자
1 2 3 4
Car(String color, String gearType, int door){ this.color = color; this.gearType = gearType; this.doo r= door;
-
초기화 블럭
인스턴스 초기화 블럭: { } /클래스 초기화 블럭: static{ }
1 2 3 4 5 6 7 8 9 10 11
class InitTest{ static int cv=1; //명시적 초기화 int iv =1; //명시적 초기화 static{cv=2;} //클래스 초기화 블럭 { iv=2; } // 인스턴스 초기화 블럭 InitTest(){ //생성자 iv=3; } }
- 인스턴스 초기화 블럭
- 생성자에서 공통적으로 수행되는 작업에 사용되며 인스턴스가 생성될때마다(생성자보다 먼저)실행
- 생성자를 주로 이용하므로 잘 사용되지 않는다.
- 클래스 초기화 블럭
- 클래스변수의 복잡한 초기화에 사용되며 클래스가 로딩될때 실행됨
- 단 1번 실행됨
- 인스턴스 초기화 블럭
-
초기화 시기와 순서
- 클래스 변수 초기화 시점 : 클래스가 처음 로딩될때 한번
- 인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때 마다
-
상속
- 상속의 정의와 장점
- 상속이란 ?
- 기존의 클래스를 재사용해서 새로운 클래스를 작성
- 두 클래스를 조상과 자손으로 관계를 맺어주는 것
- 자손은 조상의 모든 멤버를 상속 받음 (생성자, 초기화블럭 제외)
- 자손의 멤버개수는 조상보다 적을 수 없다.
- class 자손클래스 extends 조상클래스{ }
- 상속관계
- 공통부분은 조상에서 관리, 개별부분은 자손에서 관리
- 조상의 변경은 자손에 영향을 미치지만
- 자손의 변경은 조상에 아무런 영향을 미치지 않는다.
- 상속이란 ?
- 클래스간의 관계
- 포함관계
- 포함이란? 한 클래스의 멤버변수로 다른 클래스를 선언하는 것
-
작은 단위의 클래스를 먼저 만들고 이들을 조합해서 하나의 클래스로 만듬 - 재사용성 증가
1 2 3 4 5
class Circle{ int x; int y; int z; }
- 위 Cricle은 아래 두 클래스와 같이 변경할 수 있음
1 2 3 4 5 6 7 8
class Circle{ point c = new Point(); int r; } class Point{ int x; int y; }
- 클래스간의 관계 결정하기 : 상속 vs 포함
- 가능한 한 많은 관계를 맺어주어 재사용성을 높이고 관리하기 쉽게 한다.
- 대부분 포함관계
- 기존의 클래스에 기능이 추가된 새로운 클래스를 만들 때 상속관계를 맺어줌
-
예제1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
import javax.smartcardio.Card; public class Deck{ final int CARD_NUM=52; //카드의 개수 Card c[] =new Card[CARD_NUM]; // Deck(){ //Deck의 카드를 초기화 int i =0; for(int k=Card.KIND_MAX;k--){ for(int n=1; n<Card.NUM_MAX+1;n++{ c[i++]=new Card(k,n); } } } Card pick(int index){ //지정된 위치에 있는 카드 하나 선택 return c[index%CARD_NUM]; } Card pick(){ //Deck에서 카드 하나 선택 int index=(int)(Math.random()*CARD_NUM); return pick(index); } void shuffle(){ //카드의 순서를 섞는다 for(int n=0; n<1000; n++){ int i = (int)(Math.random()*CARD_NUM); Card temp=c[0]; c[0]=c[i]; c[i]=temp; } } } public static void main(String[] args) { Deck d = new Deck(); Card c = d.pick(); d.shuffle(); Card c2 = d.pick(55); }
- 포함관계
-
Java는 단일상속만 허용 - 하나만 상속가능. 나머지는 포함관계
1
class TVCR extends TV, VCR {...} //불가능
- Object class - 모든 클래스의 최고 조상
- 조상이 없는 클래스는 자동적으로 object class를 상속 받음.
- 상속계층도의 최상위는 Object 클래스가 위치
- 모든 클래스는 Object 클래스에 정의된 11개의 메서드를 상속받음.
- toString(), equals(Object obj), hashCode(),…
오버라이딩
- 오버라이딩이란?
- 조상클래스로부터 상속받은 메서드의 내용을 상속받는 클래스에 맞게 변경하는 것을 오버라이딩
- 오버라이딩 조건
- 선언부가 같아야함(이름, 매개변수, 리턴타입)
- 접근제어자를 좁은 범위로 변경할 수 없다.
- 조상의 메서드가 protected라면 범위가 같거나 넓은 protected나 public으로만 변경할 수 있다.
- 조상클래스의 메서드보다 많은 수의 예외를 선언할 수 있다.
- static 메서드를 인스턴스 메서드로 또는 인스턴스 메서드를 static메서드로 변경할 수는 없음.
-
오버로딩 vs 오버라이딩
1 2 3 4 5 6 7 8 9 10 11
class Parent { void paraentMethod(){} } class Child extends Parent{ void parentMethod(){}. //오버라이딩 void parentMethod(int i){} //오버로딩, 매개변수가 다름 void childMethod(){} void childMehtod(int i){} //오버로딩 void childMethod(){}. //에러, 중복 정의
- 오버로딩 :기존에 없는 새로운 메서드를 정의 (new)
- 오버라이딩 : 상속받은 메서드의 내용을 변경하는 것.(change,modify)
super
- this
- 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어있음
- 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재
- super
- this 와 같음, 조상의 멤버와 자신의 멤버를 구별하는데 사용
- 예제 1)
1 2 3 4 5 6 7 8 9 10 11 12
class Parent{ int x =10; } class Child extends Parent{ int x=20; void method(){ System.out.println("x="+x); System.out.println("this.x="this.x); System.out.println("super.x="super.x); } }
1 2 3 4 5 6 7 8 9 10
class Parent{ int x =10; } class child extends Parent{ void method(){ System.out.println("x="+x); //x=10 System.out.println("this.x="this.x); // 중복변수 없으므로 System.out.println("super.x="super.x);//super.x=10 } }
중복 변수 없으므로 super 사용 필요 없음, this 사용하는 걸로 충분
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Point{ int x; int y; String getLocation(){ return"x:"+x+",y:"+y; } } class Point3D extends Point{ int z; String getLocation(){ //오버라이딩 return super.getLocation()=",z:"+z; //조상의 메서드 호출 } }
- super()
- 조상의 생성자
- 자손클래스가 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성됨 ⇒ 조상의 멤버들도 초기화 되어야 하기 때문에
- 조상의 멤버들도 초기화되어야 하기 때문에 자손의 생성자의 첫 문장에서 조상의 생성자를 호출해야한다.
- Object클래스를 제외한 모든 클래스의 생성자 첫 줄에는 생성자(같은 클래스의 다른 생성자 또는 조상의 생성자)를 호출해야한다. 그렇지않으면 컴파일러가 자동적으로 ‘super();’를 생성자의 첫줄에 삽입함.
- 조상의 생성자
package와 import
패키지
- 서로 관련된 클래스와 인터페이스의 묶음
- 클래스가 물리적으로 클래스파일(*.class)인 것처럼, 패기지는 물리적으로 폴더에 해당
- 패키지는 서브패키지를 가질 수 있으며 ‘.’으로 구분
- 클래스의 실제이름 (full name)은 패키지명이 포함된 것이다.
- String 클래스의 full name은 java.lang.Stirng
- rt.jar는 Java API의 기본 클래스들을 압축한 파일
- (JDK설치경로\jre\lib에 위치)
- 패키지의 선언
- 패키지는 소스파일에 첫번째 문장(주석제외)으로 단 한번 선언한다.
- 하나의 소스파일에 둘 이상의 클래스가 포함된 경우 모두 같은 패키지에 속하게 된다.(하나의 소스파일에 단 하나의 public클래스만 허용)
- 모든 클래스느 하나의 패키지에 속하며, 패키지가 선언되지 않은 클래스는 자동으로 이름없는 (unnamed)패키지에 속하게 된다.
- 클래스패스 설정
- 클래스패스는 클래스파일을 찾는 경로. 구분자는 ;
- 클래스패스에 패키지가 포함된 폴더나 jar파일을 (*jar)나열한다.
- 클래스패스가 없으면 자동적으로 현재폴더가 포함되지만
- 클래스패스에 지정할 때는 현재폴더.도 함께 추가해주어야한다.
- 클래스패스 자동 포함된 폴더 for 클래스파일(*.class): 수동생성해야함.
- JDK설치경로\jre\lib\ext
import문
- 사용할 클래스가 속한 패키지를 지정하는데 사용
- import문을 사용하면 클래스를 사용할때 패키지를 생략가능
- java.lang패키지의 클래스는 import하지 않고도 사용할 수 있음
- String,Object,System,Thread… 매우 빈번하게 사용되어 생략할 수 있게 함.
- import문의 선언
- import문은 패키지문과 클래스 선언의 사이에 선언한다.
- 일반적인 소스파일(*java)의 구성은 다음의 순서로 되어있다.
- package문
- import문
- 클래스 선언
- import 문 선언 방법 - 여러번 사용 가능
- import 패키지명.클래스명;
- 또는 import 패키지명.*;
- 예제
- import문은 컴파일 시에 처리되므로 프로그램 성능에 아무런 영향 미치지 않음.
- 이름이 같은 클래스가 속한 두 패키지 import할때는 클래스 앞에 패키지명 붙여줘야한다.
Comment
참고자료 - 자바의 정석
Leave a comment